优先队列不同于普通队列采用先进先出的队列元素存取方式。插入队列元素时按照一定的规则插入,每次都是取队列中优先级最高的元素。可以采用最大堆来实现优先队列。
堆是一颗完全二叉树,每个结点有一个权。它的特点是根结点的权值最大,且根的两个子树也各是一个堆。可以用数组来模拟堆。堆的操作有两种:
(1)插入:方法是将新的元素i插到当前数组最后一个元素的下一个位置,然后对i进行上升调整。当i比它的父亲大 的时候,把i和它的父亲进行交换。
(2)删除:方法是先用堆的最后一个结点i覆盖要删除的结点,再把i进行下降调整。即当i比它的某一个儿子小的时候,把i和它的较大儿子交换。
时间复杂度:插入与删除的最坏时间复杂度都是O(nlogn),取最大值的时间复杂度是O(1)。
堆的代码实现:
#include <deque>
using namespace std;

enum HeapType...{MaxHeap, MinHeap};
template <class T, int capacity>
class Heap
...{
public:
Heap(HeapType type = MaxHeap)
...{
this->size = 0;
this->type = type;
this->Q.clear();
this->Q1.clear();
}

~Heap()...{}
int heap_insert(T& item)
...{
size++;
if(size > capacity)
...{
return -1;
}
/**//*
* 将item插到新的位置,然后对item作上升调整(交换元素)到合适的位置
* 即当item比它父亲小(最小堆)/大(最大堆)时,把item和它的父亲交换
*/
arr[size-1] = item;
return this->siftUp(size-1);
}
bool heap_del(int pos, T& result)
...{
if(pos < 0 || pos >= size)
...{
return false;
}

/**//*
* 用最后一个结点last把要删除的结点覆盖,再把last下降调整到合适的位置,即当last比它的某一个儿子大(最小堆)/小(最大堆)时,
* 把last和它的较小儿子(最小堆)/较大儿子(最大堆)交换
*/
result = arr[pos];
arr[pos] = arr[size-1];
size--;
this->siftDown(pos);
return true;
}
bool heap_delMax(T& result) //only valid for max heap
...{
if(type == MaxHeap)
...{
return this->heap_del(0, result);
}
else
...{
return false;
}
}
bool heap_delMin(T& result) //only valid for min heap
...{
if(type == MinHeap)
...{
return this->heap_del(0, result);
}
else
...{
return false;
}
}
bool find(T& item)
...{
bool found = false;
if(size > 0)
...{
Q.push_back(arr[0]);
Q1.push_back(0);
while(!Q.empty()&& !found)
...{
T q = Q.front();
int i = Q1.front();
int j = (i<<1) + 1;
if(q == item)
...{
found = true;
}
else if((this->type == MaxHeap? q > item : q < item))
...{
if(j < size)
...{
Q.push_back(arr[j]);
Q1.push_back(j);
}
if(j + 1 < size)
...{
Q.push_back(arr[j+1]);
Q1.push_back(j+1);
}
}
Q.pop_front();
Q1.pop_front();
}
}
return found;
}
void heap_sort()
...{
if(this->size <= 0)
...{
return;
}
int i;
for(i = this->size >> 1; i > 0; i--)
...{
this->siftDown(i-1);
}
int tsize = this->size;
while(this->size > 0)
...{
T temp = arr[0];
arr[0] = arr[this->size - 1];
arr[this->size - 1] = temp;
this->size--;
this->siftDown(0);
}
this->size = tsize;
}
protected:
T arr[capacity]; //完全二叉树.
int size; //arr[0..size-1]
HeapType type;
deque<T> Q;
deque<int> Q1;
int siftUp(int pos)
...{
int i = pos;
int j = ((i+1) >> 1) - 1;
T temp = arr[pos];
while(j >= 0 && ((type==MaxHeap) ? (arr[j] < temp):(arr[j] > temp)))
...{
arr[i] = arr[j];
i = j;
j = ((i+1) >> 1) - 1;
}
arr[i] = temp;
return i;
}
int siftDown(int pos)
...{
int i = pos;
int j = (i<<1) + 1;
bool finished = false;
T temp = arr[pos];
while(j < size && !finished)
...{
if(j + 1 < size && ((type == MaxHeap) ? (arr[j] < arr[j+1]):(arr[j] > arr[j+1])))
...{
j++;
}
if((type == MaxHeap) ? (temp >= arr[j]): (temp <= arr[j]))
...{
finished = true;
}
else
...{
arr[i] = arr[j];
i = j;
j = (i<<1) + 1;
}
}
arr[i] = temp;
return i;
}
};
以下是我参考过的一篇帖子
数据结构——堆的操作和实现
当应用优先级队列或者进行堆排序时,一般利用堆来实现。堆是一个完全(除最底层
外都是满的)二叉树,并满足如下条件:
1、根结点若有子树,则子树一定也是堆。
2、根结点一定大于(或小于)子结点。
因为要求堆必须是完全二叉树,所以可以用线性的数据结构,比如数组,来实现堆。
利用数组实现,则对于长为N的堆中的元素从0到N-1排列,有:
i的父结点:Parent(i)=(i+1)/2-1
i的左叶子:Left(i)=(i+1)*2-1
i的右叶子:Right(i)=(i+1)*2
堆的操作主要以一个“堆化”(Heapify)操作为基础,调整堆中的结点后,应用堆化操
作将其下降至合适的高度,且保持堆的性质。
插入时结点时,先将结点放入堆的最后位置,再逐步提升至合适的位置即可。
以下是用C实现的堆的相关操作:
当应用优先级队列或者进行堆排序时,一般利用堆来实现。堆是一个完全(除最底层
外都是满的)二叉树,并满足如下条件:
1、根结点若有子树,则子树一定也是堆。
2、根结点一定大于(或小于)子结点。
因为要求堆必须是完全二叉树,所以可以用线性的数据结构,比如数组,来实现堆。
利用数组实现,则对于长为N的堆中的元素从0到N-1排列,有:
i的父结点:Parent(i)=(i+1)/2-1
i的左叶子:Left(i)=(i+1)*2-1
i的右叶子:Right(i)=(i+1)*2
堆的操作主要以一个“堆化”(Heapify)操作为基础,调整堆中的结点后,应用堆化操
作将其下降至合适的高度,且保持堆的性质。
插入时结点时,先将结点放入堆的最后位置,再逐步提升至合适的位置即可。
以下是用C实现的堆的相关操作:
以下内容为程序代码:
int Heap_Init(Heap* h,Heap_Index size)
{
if(!h)
return 1;
if(!(h->data=(Heap_Data*)malloc(sizeof(Heap_Data)*size)))
return 1;
h->size=size;
h->length=0;
return 0;
}/* Heap_Init */
void Heap_Heapify(Heap* h,Heap_Index i,int Heap_Comp(Heap_Data,Heap_Data))
{
Heap_Index l,r,m;
Heap_Data t;
l=HEAP_LEFT(i); r=HEAP_RIGHT(i);
if(l<h->length && Heap_Comp(h->data[l],h->data[i])>0)
m=l;
else
m=i;
if(r<h->length && Heap_Comp(h->data[r],h->data[m])>0)
m=r;
if(m!=i)
{
t=h->data[i]; h->data[i]=h->data[m]; h->data[m]=t;
Heap_Heapify(h,m,Heap_Comp);
}
}/* Heap_Heapify */
int Heap_Increase_Key(
Heap* h,Heap_Index i,Heap_Data x,
int Heap_Comp(Heap_Data,Heap_Data))
{
if(Heap_Comp(x,h->data[i])<0)
return 1;
while(i>0 && Heap_Comp(x,h->data[HEAP_PARENT(i)])>0)
{
h->data[i]=h->data[HEAP_PARENT(i)];
i=HEAP_PARENT(i);
}
h->data[i]=x;
return 0;
}/* Heap_Increase_Key */
int Heap_Insert(Heap* h,Heap_Data x,int Heap_Comp(Heap_Data,Heap_Data))
{
Heap_Index i;
if(h->length >= h->size)
return 1;
i=h->length++;
if(i>0 && Heap_Comp(x,h->data[HEAP_PARENT(i)])>0)
{
h->data[i]=h->data[HEAP_PARENT(i)];
return Heap_Increase_Key(h,HEAP_PARENT(i),x,Heap_Comp);
}
else
h->data[i]=x;
return 0;
}/* Heap_Insert */
Heap_Data Heap_Top(Heap* h)
{
return h->data[0];
}/* Heap_Top */
int Heap_Delete(Heap* h,Heap_Data* x,int Heap_Comp(Heap_Data,Heap_Data))
{
if(h->length <= 0)
return 1;
*x=h->data[0];
h->data[0] = h->data[--h->length];
Heap_Heapify(h,0,Heap_Comp);
return 0;
}/* Heap_Delete */
int Heap_Destory(Heap* h)
{
if(!h || !(h->data))
return 1;
free(h->data);
h->data=NULL;
return 0;
}/* Heap_Destory */
int Heap_Clean(Heap* h)
{
if(!h)
return 1;
h->length=0;
return 0;
}/* Heap_Clean */
int Heap_Sort(
Heap_Data* data,Heap_Index size,
int Heap_Comp(Heap_Data,Heap_Data))
{
Heap h;
Heap_Index i;
Heap_Data t;
if(!data)
return 1;
h.length=h.size=size;
h.data=data;
for(i=h.length/2;i>=0;i--)
Heap_Heapify(&h,i,Heap_Comp);
for(h.length--;h.length>=0;h.length--)
{
t=h.data[0];h.data[0]=h.data[h.length];h.data[h.length]=t;
Heap_Heapify(&h,0,Heap_Comp);
}
return 0;
}
return i;
int Heap_Init(Heap* h,Heap_Index size)
{
if(!h)
return 1;
if(!(h->data=(Heap_Data*)malloc(sizeof(Heap_Data)*size)))
return 1;
h->size=size;
h->length=0;
return 0;
}/* Heap_Init */
void Heap_Heapify(Heap* h,Heap_Index i,int Heap_Comp(Heap_Data,Heap_Data))
{
Heap_Index l,r,m;
Heap_Data t;
l=HEAP_LEFT(i); r=HEAP_RIGHT(i);
if(l<h->length && Heap_Comp(h->data[l],h->data[i])>0)
m=l;
else
m=i;
if(r<h->length && Heap_Comp(h->data[r],h->data[m])>0)
m=r;
if(m!=i)
{
t=h->data[i]; h->data[i]=h->data[m]; h->data[m]=t;
Heap_Heapify(h,m,Heap_Comp);
}
}/* Heap_Heapify */
int Heap_Increase_Key(
Heap* h,Heap_Index i,Heap_Data x,
int Heap_Comp(Heap_Data,Heap_Data))
{
if(Heap_Comp(x,h->data[i])<0)
return 1;
while(i>0 && Heap_Comp(x,h->data[HEAP_PARENT(i)])>0)
{
h->data[i]=h->data[HEAP_PARENT(i)];
i=HEAP_PARENT(i);
}
h->data[i]=x;
return 0;
}/* Heap_Increase_Key */
int Heap_Insert(Heap* h,Heap_Data x,int Heap_Comp(Heap_Data,Heap_Data))
{
Heap_Index i;
if(h->length >= h->size)
return 1;
i=h->length++;
if(i>0 && Heap_Comp(x,h->data[HEAP_PARENT(i)])>0)
{
h->data[i]=h->data[HEAP_PARENT(i)];
return Heap_Increase_Key(h,HEAP_PARENT(i),x,Heap_Comp);
}
else
h->data[i]=x;
return 0;
}/* Heap_Insert */
Heap_Data Heap_Top(Heap* h)
{
return h->data[0];
}/* Heap_Top */
int Heap_Delete(Heap* h,Heap_Data* x,int Heap_Comp(Heap_Data,Heap_Data))
{
if(h->length <= 0)
return 1;
*x=h->data[0];
h->data[0] = h->data[--h->length];
Heap_Heapify(h,0,Heap_Comp);
return 0;
}/* Heap_Delete */
int Heap_Destory(Heap* h)
{
if(!h || !(h->data))
return 1;
free(h->data);
h->data=NULL;
return 0;
}/* Heap_Destory */
int Heap_Clean(Heap* h)
{
if(!h)
return 1;
h->length=0;
return 0;
}/* Heap_Clean */
int Heap_Sort(
Heap_Data* data,Heap_Index size,
int Heap_Comp(Heap_Data,Heap_Data))
{
Heap h;
Heap_Index i;
Heap_Data t;
if(!data)
return 1;
h.length=h.size=size;
h.data=data;
for(i=h.length/2;i>=0;i--)
Heap_Heapify(&h,i,Heap_Comp);
for(h.length--;h.length>=0;h.length--)
{
t=h.data[0];h.data[0]=h.data[h.length];h.data[h.length]=t;
Heap_Heapify(&h,0,Heap_Comp);
}
return 0;
}
455

被折叠的 条评论
为什么被折叠?



