1. 程式人生 > >建立堆,堆排序的詳細實現過程,C++完整程式碼

建立堆,堆排序的詳細實現過程,C++完整程式碼

堆的基本概念不在此介紹,各位看官自行百度。由於堆的特性導致堆可以用陣列進行模擬,所以堆排序其實是在陣列(即堆)上進行排序的過程,在所有堆的操作中,都離不開一個操作:調整堆,該過程使堆保持堆的性質(大堆或小堆的性質)。在介紹堆排序之前必要要介紹如何建立堆,由於堆是使用陣列儲存的,所有我的理解是,建堆的過程就是堆化陣列,即使給定的陣列具有堆的性質。堆化的過程其實就是調整堆的過程,我們把調整堆的過程定義成一個單獨的函式void AdjustHeap(int heap[], int root_index, int heap_length),引數分別是代表堆的陣列,要調整的堆的根節點在陣列中的下標,注意是下標,建議讀者自己畫個圖模擬調整堆的過程。第三個引數是堆的長度,在這裡就讓他等於陣列的長度,其實可以不相等。

調整堆的過程如下:

1.根據根節點下標,確定左右子節點的下標。

2.找出根節點和左右子節點中最小值的下標,注意該過程要判斷邊界,即左右子節點的下標是否超出堆的長度。

3.如果最小值的下標等於根節點的下標,函式返回。

4.否則,交換把根節點與最小值交換,由於交換可能破壞了最小值所在子樹的對性質,所以遞迴呼叫AdjustHeap函式。

那麼現在還有一個問題,就是堆化的時候,從哪個節點開始調整堆呢?這個也是建堆的關鍵,我們可以這樣想,子節點已經是堆了,無需在調整了,所以我們沒必要從最後一個節點開始調整,一般是從(heap_length/2)開始調節,一直到下標1為止(堆的下標一般從1開始,0位置不用),從(heap_length/2)開始調節的原因是完全二叉樹的性質決定的。這樣遍歷一遍,對每個節點呼叫堆調整函式就完成建堆了。

堆排序的思想比較簡單,取出堆的第一個元素,調整堆,迴圈下去,知道取完為止。實現的過程就是先把堆頂元素和堆的最後一個元素互換,堆長度減1,再調整堆,知道堆的長度為1。這樣就使堆排序的空間複雜度為O(1)了,注意的是大頂堆排完序之後陣列中元素的順序是從小到大,小頂堆是從大到小。

完整程式碼如下:

#include <iostream>
#define Max 11
int heap[Max];

void AdjustHeap(int heap[], int root_index, int heap_length) //調整堆,這裡是最小堆
{
	int left_child_index = root_index * 2;
	int right_child_index = left_child_index + 1;
	int min_index = root_index;

	if (left_child_index < heap_length && right_child_index < heap_length)
	{
		if (heap[left_child_index] < heap[root_index])
		{
			if (heap[left_child_index] < heap[right_child_index])
				min_index = left_child_index;
			else
				min_index = right_child_index;
		}
		else
		{
			if (heap[right_child_index] < heap[root_index])
				min_index = right_child_index;
			else
				min_index = root_index;
		}
	}

	if (left_child_index < heap_length && right_child_index >= heap_length) //這種情況是左子節點是最後一個元素的情況
	{
		if (heap[left_child_index] < heap[root_index])
			min_index = left_child_index;
		else
			min_index = root_index;
	}

	if (min_index != root_index)
	{
		int t = heap[root_index];
		heap[root_index] = heap[min_index];
		heap[min_index] = t;

		AdjustHeap(heap,min_index,heap_length);
	}

	return;
}

void CreateHeap(int heap[], int heap_length) //建堆
{
	for (int i = (heap_length / 2); i >= 1; --i)
		AdjustHeap(heap, i, heap_length);
}

int main()
{
	heap[0] = -1;
	for (int i = 1; i != Max; ++i)//輸入陣列
		std::cin >> heap[i];

	CreateHeap(heap, Max); //建堆,即堆化
	for (int i = 0; i != Max; ++i)
		std::cout << heap[i] << " ";
	std::cout << std::endl;
	//堆建好的堆進行排序
	int t = Max;
	while (t != 1)
	{
		int tmp = heap[t - 1];
		heap[t - 1] = heap[1];
		heap[1] = tmp;
		AdjustHeap(heap, 1, t-1);
		--t;
	}

	for (int i = Max - 1; i != 0; --i)
		std::cout << heap[i] << " ";
	std::cout << std::endl;
}