1. 程式人生 > >資料結構--6堆(優先佇列)

資料結構--6堆(優先佇列)

操作

插入:空穴上濾策略,新元素在堆中上濾直到找出正確位置。
刪除最小者(DeleteMin):返回並刪除佇列中最小的元素,將堆中最後一個元素放入合適位置,空穴下濾策略。
限制:不能進行Find操作。

 實現方式

1.利用簡單鏈表,在表頭O(1)插入,遍歷刪除最小元;或者,始終讓連結串列有序,則插入O(N),刪除O(1)。因為插入多於刪除,所以前者更好。
2.利用二叉查詢樹,插入和刪除都是O(logN),利用二叉查詢樹有些大材小用,因為它支援許多不需要的操作。
3.二叉堆,本文所講。

二叉堆性質

  1. 結構性質
    堆是一顆除底層外被完全填滿的二叉樹,底層上的元素從左到右填入,這樣的樹被稱為完全二叉樹。
    一顆高為h的完全二叉樹有2^h到2^h-1個節點,即完全二叉樹的高為logN,顯然是O(logN)。
    完全二叉樹很有規律,所以可以使用陣列而不需要指標來表示:
    對於陣列任一位置i,左二子在2i上,右兒子在(2i + 1)中,父親在i/2上。
    一個堆資料結構由一個數組,一個代表最大值的整數,以及當前的堆
    ;實現方法存在的問題:最大的堆需要事先估計。
  2. 堆序性質
    最小或最大元在根上,可以快速找到。

程式碼:主要是插入和刪除並返回最小元的操作。

#include <iostream>
using namespace std;

typedef struct HeapStruct
{
	int m_capacity;
	int m_size;
	int* m_array;
} *PriorityQueue;

PriorityQueue Initialize(int capacity);
void Destroy(PriorityQueue H);
void MakeEmpty(PriorityQueue H);
void Insert(PriorityQueue H, int x);//上濾
int DeleteMin(PriorityQueue H);
int FindMin(PriorityQueue H);
bool IsEmpty(PriorityQueue H);
bool IsFull(PriorityQueue H);

int main()
{

}

PriorityQueue Initialize(int capacity)
{
	PriorityQueue H = new HeapStruct;
	if (capacity < 0)
		cout << "堆容量要大於0" << endl;

	H->m_array = new int[capacity];
	H->m_capacity = capacity;
	H->m_size = 0;
	H->m_array[0] = -9999999;//MinData,標誌,相當於哨兵,連結串列中的頭結點
	return H;
}

void Insert(PriorityQueue H, int x)
{
	int i;
	if (IsFull(H))
	{
		cout << "堆已滿,無法插入" << endl;
		return;
	}
	//空穴位置;父節點>x;上濾。
	//此處類似於插入排序,避免交換操作。
	//注意H->m_arr[0]為標記,小於堆中的任何元素,用來跳出for迴圈
	for (i = ++H->m_size; H->m_array[i / 2] > x; i /= 2)
	{
		H->m_array[i] = H->m_array[i / 2];//父下移,移出空位
	}
	H->m_array[i] = x;//填入新元素
}

int DeleteMin(PriorityQueue H)
{
	int i, Child;
	int MinElement = H->m_array[1];
	int LastElement = H->m_array[--H->m_size];
	if (IsEmpty(H))
	{
		cout << "堆為空,刪除失敗" << endl;
		return H->m_array[0];
	}
	for (i = 1; i * 2 <= H->m_size; i = Child)
	{
		//找到空穴的較小兒子,以便空穴下濾
		Child = i * 2;
		if (Child != H->m_size && H->m_array[Child + 1] < H->m_array[Child])
			Child++;

		//類似於插入排序
		if (LastElement > H->m_array[Child])//堆中最後一個元素大於空穴的兒子,移出空位
			H->m_array[i] = H->m_array[Child];
		else//堆中最後一個元素小於空穴的兒子,停止下濾,跳出迴圈之後,最後一個元素填入空位
			break;
	}
	H->m_array[i] = LastElement;//入位
	return MinElement;
}