常見的排序算法(二) 選擇排序

選擇排序(Selection sort)是一種簡單直觀的排序算法。它的工作原理是每一次從待排序的數據元素中選出最小(或最大)的一個元素,存放在序列的起始位置,直到全部待排序的數據元素排完。

選擇排序:

思想

n個記錄的文件的直接選擇排序可經過n-1趟直接選擇排序得到有序結果:

①初始狀態:無序區爲R[1..n],有序區爲空。

②第1趟排序

在無序區R[1..n]中選出關鍵字最小的記錄R[k],將它與無序區的第1個記錄R[1]交換,使R[1..1]和R[2..n]分別變爲記錄個數增加1個的新有序區和記錄個數減少1個的新無序區。

……

③第i趟排序

第i趟排序開始時,當前有序區和無序區分別爲R[1..i-1]和R(i..n)。該趟排序從當前無序區中選出關鍵字最小的記錄 R[k],將它與無序區的第1個記錄R交換,使R[1..i]和R分別變爲記錄個數增加1個的新有序區和記錄個數減少1個的新無序區。

因爲實現方法比較多,也易實現,故只給出一種代碼以下並非最優算法或者有所改進和優化。

因爲改進和優化的選擇排序可能存在BUG,並且實現和一下代碼差不多,故而,不在一一列舉。

void SelectiongSort(int* a, size_t size)  //選擇排序
{
	assert(a);
	int  min;
    for (int i = 0; i < size ; i++)
  {
         min = i;
        for (int j = i + 1; j < size; j++)
        if (a[j] < a[min])
            min = j;
        swap(a[i], a[min]);
   }

}

選擇排序的交換操作介於 0 和 (n - 1) 次之間。選擇排序的比較操作爲 n (n - 1) / 2 次之間。選擇排序的賦值操作介於 0 和 3 (n - 1) 次之間。

比較次數O(n^2),比較次數與關鍵字的初始狀態無關,總的比較次數N=(n-1)+(n-2)+...+1=n*(n-1)/2。交換次數O(n),最好情況是,已經有序,交換0次;最壞情況交換n-1次,逆序交換n/2次。交換次數比冒泡排序少多了,由於交換所需CPU時間比比較所需的CPU時間多,n值較小時,選擇排序比冒泡排序快。選擇排序是給每個位置選擇當前元素最小的,比如給第一個位置選擇最小的,在剩餘元素裏面給第二個元素選擇第二小的,依次類推,直到第n-1個元素,第n個元素不用選擇了,因爲只剩下它一個最大的元素了。那麼,在一趟選擇,如果一個元素比當前元素小,而該小的元素又出現在一個和當前元素相等的元素後面,那麼交換後穩定性就被破壞了。



堆排序

堆分爲大根堆和小根堆,是完全二叉樹。大根堆的要求是每個節點的值都不大於其父節點的值,即A[PARENT[i]] >= A[i]。在數組的非降序排序中,需要使用的就是大根堆,因爲根據大根堆的要求可知,最大的值一定在堆頂。

既然是堆排序,自然需要先建立一個堆,而建堆的核心內容是調整堆,使二叉樹滿足堆的定義(每個節點的值都不大於其父節點的值)。

(此處本欲給出圖片,但因網站的問題,便不給出,望讀者見諒。)

void Adjust(int* a, int i, int size)
{
	assert(a);
  
	int parent = i;
	int child = 2*i +1;
	while(child < size)
	{
	if(child+1 < size && a[child+1]>a[child])
		++child;

	if(a[parent] < a[child])
	{
		swap(a[parent],a[child]);
		parent  =child;
		child = 2*parent +1;
	}
	else
		break;
	}
}

void HeapSort(int* a, size_t size)   //堆排序
{
	for(int i = (size-2)/2 ; i >0; --i)
	   Adjust(a,i,size);

	for(int i = 0;i<size; ++i)    //每次把根節點和最後一個節點相交換
	{                               //也就是說把最大的數放到了最後一個位置
		swap(a[0],a[size-1-i]); //最後便排序完畢
		Adjust(a,0,size-i-1);
	}
	

}

算法分析

堆排序的時間,主要由建立初始堆和反覆重建堆這兩部分的時間開銷構成,它們均是通過調用Heapify實現的。

平均性能    O(N*logN)。

其他性能

由於建初始堆所需的比較次數較多,所以堆排序不適宜於記錄數較少的文件。

堆排序是就地排序,輔助空間爲O(1).

它是不穩定的排序方法。(排序的穩定性是指如果在排序的序列中,存在前後相同的兩個元素的話,排序前 和排序後他們的相對位置不發生變化)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章