STL Heap

来源:互联网 发布:汽车电脑板维修编程 编辑:程序博客网 时间:2024/05/16 16:17
heap STL heap能够用来排序,其调整大顶堆或小顶堆的方法能够作为priority queue实现的低层机制,但细看了《STL源码剖析》中的有关Heap一节,才知道STL中并没有把heap作为一种容器组件,heap的实现亦需要更低一层的容器组件(诸如list,array,vector)作为其底层机制。Heap是一个类属算法,包含在algorithm头文件中。


         在《数据结构》的课时学习中,我们知道heap的图其实是一颗完全二叉树,基于其特征,可以用array来存储,且根据其需要,分为大顶堆和小顶堆。然而,在STL中,由于array的缺点(无法动态改变大小),改用vector代替array,并且只供应大顶堆max-heap。


         在此又不得不粗略提一下vector容器的实现原理。


Vector容器的数据结构实际就是一段线性连续空间,用迭代器start和finish分别指向连续空间中目前被使用的范围(就好像队列queue的头尾指针一样),就个人认为vector其实是和array几乎一样的存在。但vector为了实现快速的内存分配,在分配空间容量时会比当前所需空间多一些,用于存放新添加的元素;当预留空间用完时,以加倍当前容量的分配策略实现重新分配(事实上容量的重新分配需要“重新配置、元素移动、释放原空间”的过程,事实证明这个策略所变现出来的性能非常好)。然后,在基于array和快速内存分配的基础上,应用了迭代器begin、end和end_of_storage(连续可用空间的尾),提供了首尾标示、大小、容量、空容器、标注([ ])运算等等的机能。


         在STL中为堆heap的创建和操作提供了4种算法:make_heap,pop_heap,push_heap和sort_heap。其中:


         make_heap:利用区间[first,last)中的元素构造一个heap。





                    函数原型:void make_heap(first,last)


                    void make_heap(first,last ,compare_fuction)。


         pop_heap:  假定区间[first,last)中已包含一个堆,将first位置和last-1位置上的值交换,重新把[first,last-1)调整为一个堆。


    函数原型:void pop_heap(first,last);


              void pop_heap(first,last,compare_fuction)。


         push_heap: 假定区间[first,last-1)已经包含了一个堆,把区间[first,last)调整为一个堆(从而     把last-1位置上的元素压入堆。


    函数原型:void push_heap(first,last);


              void push_heap(first,last,compare_fuction).


         sort_heap: 对存储在堆中的元素进行排序。


                    函数原型:void sort_heap(first,last);


                              void sort_heap(first,last,compare_fuction)


         对比之前做过的堆排序的实验,感觉STL中的heap优化并不比教材里面介绍的强多少。想想也应该是,那算法思想是一模一样的,但在代码的实现上,STL中做到了规范化。其次,STL中应用了vector作为heap的底层机制,克服了教材中用array存储空间无法动态改变大小的缺点。其三,STL中关于heap的四个算法都实现了函数重载,虽然STL中关于heap默认调整成的是大顶堆,但却可以让用户利用自定义的compare_fuction函数实现大顶堆或小顶堆。其四,heap的低层机制vector本身就是一个类模板,heap基于vector便实现了对各种数据类型(无论基本数据类型还是用户自定义的数据类型)的堆排(前提是用户自定义的数据类型要提供比较机制compare_fuction函数)。


参考阅读书籍:《STL源码剖析》、《C++Primer中文版》、


《标准模板库自修教程与参考手册:STL进行C++编程》


----------------------------------



最大堆实现


#ifndef MAXHEAP_H
#define MAXHEAP_H
 
 template<class T>
 class MaxHeap
 {
 public:
     
    MaxHeap(T a[], int size,int maxsize=50);
   MaxHeap(int maxsize=50);
   virtual ~MaxHeap();
    void   Initialize(T arrays[],int size,int array_size);//用数组对堆重新进行初始化
    MaxHeap<T>& Insert( T value);
   MaxHeap<T>& DeleteMax(T& value );
    bool IsEmpty(){return CurrentSize==0?true:false;};
    int Size(){return CurrentSize;}
    void Init(T a[]);


private:
    void ModifyUp(int start);
    void ModifyDown(int start,int end);


private:
    T *Data;
    int MaxSize;
    int CurrentSize;


};




template<class T>
MaxHeap<T>::MaxHeap(T a[], int size,int maxsize)
{
    Data=a;
CurrentSize=size;
MaxSize=maxsize;
for( int i=CurrentSize/2;i>=1;i--)
{
ModifyDown(i,CurrentSize);


}


}


//-----------------------------------------------------------------------
template<class T>
void  MaxHeap<T>::Initialize(T arrays[],int size,int array_size)
{
if(Data)
delete[] Data;


Data=arrays;


CurrentSize=size;
MaxSize=array_size;


for(int i=CurrentSize/2;i>=1;i--)
{
ModifyDown(i,CurrentSize);
}
}


//-------------------------------------------------------------------------
template<class T>
MaxHeap<T>::MaxHeap(int maxsize)
{
    //0号单元不用舍弃,数据从一号单元填入
MaxSize=maxsize;
Data=new T[MaxSize+1];
CurrentSize=0;
}


//-------------------------------------------------------------------------
template<class T>
 MaxHeap<T>::~MaxHeap()
    {
    
    delete[] Data;
    
    }


//-------------------------------------------------------------------------
template<class T>
MaxHeap<T>& MaxHeap<T>::Insert(T value)
{
if(CurrentSize==MaxSize)
{
    cout<<"错误:堆空间已满."<<endl;
    throw exception("堆空间已满");


}


Data[++CurrentSize]=value;
ModifyUp(CurrentSize);//重新调整堆
return *this;
}
    
//-------------------------------------------------------------------------
template<class T>    
MaxHeap<T>& MaxHeap<T>::DeleteMax( T& value )
{


if(CurrentSize==0)
{
    cout<<"错误:堆空."<<endl;
    throw exception("堆空");


}
value=Data[1];


Data[1]=Data[CurrentSize--];


ModifyDown(1,CurrentSize);//重新调整堆
return *this;
}




//-------------------------------------------------------------------------
template<class T>
void MaxHeap<T>::ModifyUp(int start)
   {
    int i=start;
   T x=Data[i];
    //当未到达根结点并且start所指节点值大于其父节点时进行移动    
    while(i!=1&&x>Data[i/2])
    {
Data[i]=Data[i/2];//将父节点下移
i/=2;//i指针上移
    }
Data[i]=x;
return ;
    }


//----------------------------------------------------------------
template<class T>
void MaxHeap<T>::ModifyDown(int start,int end)
    {
    T x=Data[start];


    int c=2*start;
    while(c<=end)
    {
    if(c<end&&Data[c]<Data[c+1]) c++;
if(x>Data[c]) break;
 else
 {


 Data[c/2]=Data[c];//将孩子上移
c*=2;
 }//if
    }//while
Data[c/2]=x;    
    }
#endif





------------------------------------------

1.template<class T>   
2.class MaxHeap{   
3. public:   
4.  MaxHeap(T a[],int n);   
5.  MaxHeap(int ms);   
6.  ~MaxHeap();   
7.  bool Insert(const T &x);//插入一个元素,如果空返回false,否则返回true   
8.     bool RemoveMax(T &x);//删除最小的元素,如果空返回false,否则返回true   
9.  void MakeEmpty();//使堆为空   
10.  bool IsEmpty();   
11.  bool IsFull();   
12.  
13.protected:   
14.  void FilterDown(const int start,const int endOfHeap);//自顶向下构造堆   
15.  void FilterUp(const int start);//自底向上构造堆   
16. private:   
17.  T *heap;   
18.  int maxSize;   
19.  const int defaultSize;   
20.  int currentSize;   
21.};   
22.template<class T>   
23.MaxHeap<T>::MaxHeap(int ms):defaultSize(100){   
24. maxSize = ms > defaultSize ? ms : defaultSize;   
25. heap = new T[maxSize];   
26. currentSize = 0;   
27.}   
28.template<class T>   
29.MaxHeap<T>::MaxHeap(T a[],int n):defaultSize(100){   
30. maxSize = n > defaultSize ? n : defaultSize;   
31. heap = new T[maxSize];   
32. currentSize = n;   
33. for(int i = 0; i < n; i++)   
34.  heap[i] = a[i];   
35. int curPos = (currentSize - 2) / 2;   
36. while(curPos >= 0){   
37.   FilterDown(curPos,currentSize - 1);   
38.   curPos--;   
39. }   
40.}   
41.template<class T>   
42.MaxHeap<T>::~MaxHeap(){   
43. delete []heap;   
44.}   
45.template<class T>   
46.void MaxHeap<T>::FilterDown(const int start,const int endOfHeap){   
47. int i = start,j = i * 2 + 1;   
48. T temp = heap[i];   
49. while(j <= endOfHeap){   
50.   if(j < endOfHeap && heap[j] < heap[j+1]) j++;   
51.   if(temp > heap[j]) break;   
52.   else{   
53.    heap[i] = heap[j];   
54.    i = j;   
55.    j = 2 * i + 1;   
56.   }   
57. }   
58. heap[i] = temp;   
59.}   
60.template<class T>   
61.void MaxHeap<T>::FilterUp(const int start){   
62. int i = start, j = ( i - 1 ) / 2;   
63. T temp = heap[i];   
64. while(i > 0){   
65.   if(temp <= heap[j]) break;   
66.   else{   
67.    heap[i] = heap[j];   
68.    i = j;   
69.    j = (i - 1) / 2;   
70.   }   
71. }   
72. heap[i] = temp;   
73.}   
74.template<class T>   
75.bool MaxHeap<T>::RemoveMax(T &x){   
76. if(IsEmpty()){   
77.  cerr<<"Heap empty!"<<endl;   
78.  return false;   
79. }   
80. x = heap[0];   
81. heap[0] = heap[currentSize - 1];   
82. currentSize--;   
83. FilterDown(0,currentSize-1);   
84. return true;   
85.}   
86.template<class T>   
87.bool MaxHeap<T>::Insert(const T& x){   
88. if(IsFull()) {   
89.  cerr<<"Heap Full!"<<endl;   
90.        return false;   
91. }   
92. heap[currentSize] = x;   
93. FilterUp(currentSize);   
94. currentSize++;   
95. return true;   
96.}   
97.template<class T>   
98.bool MaxHeap<T>::IsEmpty(){   
99.  return currentSize == 0;   
100.}   
101.    
102.template<class T>   
103.bool MaxHeap<T>::IsFull(){   
104.  return currentSize == maxSize;   
105.}   
106.  
107.template<class T>   
108.void MaxHeap<T>::MakeEmpty(){   
109. currentSize = 0  
110.}   
111.  
112.MainApp.cpp测试文件:   
113.  
114.#include<iostream>   
115.#include"MaxHeap.h"  
116.using namespace std;   
117.  
118.void main(){   
119. int a[5] = {3,2,1,4,5};   
120.    MaxHeap<int> m_heap(a,5);   
121. int x,i;   
122. for(i = 0; i < 5; i++){   
123.   m_heap.RemoveMax(x);   
124.   cout << x << " ";   
125. }   
126. cout << endl;    
127.  
128.    for(i = 0; i < 5; i++){   
129.    m_heap.Insert(a[i]);   
130. }   
131.  
132. for(i = 0; i < 5; i++){   
133.   m_heap.RemoveMax(x);   
134.   cout << x << " ";   
135. }   
136. cout << endl;    
137.}  







原创粉丝点击