堆與優先隊列


1.針對的問題:很快的找出最大的元素(最大堆)、很快的找出最小的元素(最小堆)

                         它不適用於從一堆數中檢索某一個數

   

   如何去定義一個堆?抓住兩點:

   完全二叉樹、任何一個內部結點的值大於等於其子節點的值

   一個堆一定是完全二叉樹的形式:節約空間、可以很方便的用數組表示

   

  最大堆:根大於等於任何一個子節點(堆排序)

  最小堆:根小於等於任何一個子節點(Krustral)


2.關鍵操作:shiftdown  和  buildHeap


   如何根據已知的元素建立一個堆?

   核心思想:(以最大堆爲例)假設左子樹與右子樹已經是堆了,如果根的值比左右節點的值都大,則不做任 何改變。否則,選取左右子樹中較大的那一個與根交換位置,然後一直shiftdown下去,直到當前已經是葉節點或已經在正確的位 置。


核心代碼:

void shiftDown(int pos)//從 pos開始shiftdown
{
	while (!isLeaf(pos))
	{
		int m = 2 * pos + 1, r = 2 * pos + 2;
		if (r<n&&heap[r]>heap[m])
			m = r;
		if (heap[pos] >= heap[m])return;
		else swap(heap, pos, m);

		pos = m;
	}
}

void buildHeap()
{
	for (int i = n / 2 - 1; i >= 0; i--)
		shiftDown(i);
}



  如何在已經建好的堆中插入一個元素?

  核心思想:每次把元素放到數組最後的位置,與父節點比較,如果它的值比父節點的值要大,則與父節點交換位置(shiftup)

   一直shiftup下去,直到已經是根節點或已經在正確的位置

  

void insert(const int& it)
{
	if (n < maxsize)
	{
		int curr = n++;
		heap[curr] = it;

		while (curr != 0 && heap[curr] > heap[parent(curr)])
		{
			swap(heap, curr, parent(curr));
			curr = parent(curr);
		}
	}

}











   

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