数据结构--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;
}

 

猜你喜欢

转载自blog.csdn.net/vict_wang/article/details/83278442