用堆实现优先队列

 优先队列不同于普通队列采用先进先出的队列元素存取方式。插入队列元素时按照一定的规则插入,每次都是取队列中优先级最高的元素。可以采用最大堆来实现优先队列。

堆是一颗完全二叉树,每个结点有一个权。它的特点是根结点的权值最大,且根的两个子树也各是一个堆。可以用数组来模拟堆。堆的操作有两种:

(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实现的堆的相关操作:
以下内容为程序代码:


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;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值