淺談排序算法(三)之堆排序

堆排序主要思想:
1.初始化數串成大頂堆(或小頂堆)
  1.1 先初始化一個非葉節點的小子樹爲大頂堆(或小頂堆)
  1.2 再初始化數串中的每個子樹成大頂堆(或小頂堆)
2.由步驟1中得到的堆頂即是當前未排序數串的最大值。由此繼續循環得到下個最大值

 

堆排序與選擇排序有點相似,都是先通過循環比較得到 未排序數串中的最大值,然後把它給已排序的數串中。

但是選擇排序中循環比較時會出現很多重複比較的情況,而堆排序中則可以保存部分比較的結果

堆排序的平均複雜度比較接近O(nlogn),而選擇排序爲O(n^2)

 

代碼一:

/*
**該函數使一個含有父子節點的小子樹形成一個大頂堆
**array是要排序的數組
**father是父節點(它的值代表它是數組中的第幾個,不是下標)
**size是要排序數組的大小
*/
int smallheap(int array[], int father, int size)  
{
	int max = father;                //用於暫存父子節點之間哪個最大,這裏首先假設父節點最大
	int rchild = father * 2 + 1;     
	int lchild = father * 2;
	
	if(rchild - 1 < size && array[rchild-1] > array[max-1]) //右節點與第max個數(這裏是父節點)比較
		max = rchild;
	if(lchild - 1 < size && array[lchild-1] > array[max-1]) //左節點與第max個數比較
		max = lchild;
	if(max != i)           //如果父節點和子節點沒發生交換
	{
		swap(array[max-1],array[father-1]);   //某個子節點(第max個)與父節點交換
		smallheap(array, max, size);     //交換後。遞歸檢查以第max個節點爲父節點的子樹是否滿足堆
	}
	return 0;
}

/*
**從數組後面逐漸往前掃描,依次把每個非葉節點的小子樹初始化成大頂堆
**array是要排序的數組
**size是要排序數組的大小
*/
int init(int array[], int size)
{
	for(int i = size/2; i > 0; i--) // size/2 是最末的一個非葉節點
	{
		smallheap(array,i,size);		
	}
	return 0;
}

/*
**循環得到未排序的數當中的最大值(最大父節點),
**並把它交換到後面,這樣已排序的數逐漸增多
**array是要排序的數組
**size是要排序數組的大小
*/
int heap_sort(int array[],int size)
{
	init(array,size);
	for(int i = size; i > 1;)
	{
		swap(array[0],array[i-1]);  //最大父節點與未排序數串中的末位交換
		smallheap(array,1,--i);     //重新調整未排序(大小爲--i)的數串爲大頂堆
	}
	return 0;
}

int main()
{
	int array[] = {2,3,44,77,66,7,4,10,55,3333};

	heap_sort(array,10);

	for(int i = 0; i < 10; i++)
		printf("%d  ",array[i]);

	return 0;
}

 

-----本人菜鳥一隻,如有錯誤,望大牛們指出^_^

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