[BinaryTree] 最大堆的类实现

堆的定义:

最大树(最小树):每个结点的值都大于(小于)或等于其子结点(如果有的话)值的树。
最大堆(最小堆):最大(最小)的完全二叉树。

最大堆的抽象数据结构:

 1 class MaxHeap
 2 {
 3 private:
 4     T* heapArray;   //存放堆数据的数组
 5     int CurrentSize;//当前堆中元素数目
 6     int MaxSize;    //堆中能容纳的最大元素数目
 7 public:
 8     MaxHeap(T* array,int num,int max);
 9     virtual ~MaxHeap()
10     {
11         delete []heapArray;
12     }
13     void BuildHeap();
14     void Swap(int pos_x,int pos_y);     //交换位置x与y的元素
15     bool IsLeaf(int pos) const;         //如果是叶子结点,返回true
16     int LeftChild(int pos) const;       //返回左孩子位置
17     int RightChild(int pos) const;      //返回右孩子位置
18     int Parent(int pos) const;          //返回父结点位置
19     bool Remove(int pos,T& node);       //删除给定下标元素
20     void SiftDown(int left);            //筛选法函数,参数left表示开始处理的数组下标
21     void SiftUp(int position);          //从position向上开始调整,使序列成为堆
22     bool Insert(const T& newNode);      //向堆中插入新元素newNode
23     T& RemoveMax();                     //从堆顶删除最大值
24     void print();                       //输出函数
25 };

下面是一些简单函数的实现:

 1 template<class T>
 2 MaxHeap<T>::MaxHeap(T* array,int num,int max)
 3 {
 4     heapArray = array;
 5     CurrentSize = num;
 6     MaxSize = max;
 7 }
 8 template<class T>
 9 void MaxHeap<T>::Swap(int pos_x,int pos_y)
10 {
11     T temp = heapArray[pos_x];
12     heapArray[pos_x] = heapArray[pos_y];
13     heapArray[pos_y] = temp;
14 }
15 template<class T>
16 bool MaxHeap<T>::IsLeaf(int pos) const
17 {
18     return (pos>=CurrentSize/2)&&(pos<CurrentSize);
19 }
20 template<class T>
21 int MaxHeap<T>::LeftChild(int pos) const
22 {
23     return pos*2+1;
24 }
25 template<class T>
26 int MaxHeap<T>::RightChild(int pos) const
27 {
28     return pos*2+2;
29 }
30 template<class T>
31 int MaxHeap<T>::Parent(int pos) const
32 {
33     if(pos == 0)
34         return -1;
35     return (pos-1)/2;
36 }

下面来看几个重要的操作的实现:

·堆的插入操作

(1)新元素添加到末尾(保持完全二叉树的性质);
(2)为了保持堆的性质,沿着其祖先的路径,自下而上依次比较和交换该结点与父结点的位置,直到重新满足堆的性质位置;
(3)在插入过程中,总是自下而上逐渐上升,最后停留在某个满足堆的性质的位置,故此过程又称为 “筛选”。

 1 template<class T>
 2 bool MaxHeap<T>::Insert(const T& newNode)
 3 {
 4     if(CurrentSize == MaxSize)
 5         return false;
 6     heapArray[CurrentSize] = newNode;
 7     SiftUp(CurrentSize);
 8     CurrentSize++;
 9     return true;
10 }

·建堆过程

(1)首先将所有关键码放到一维数组中,这时形成的完全二叉树并不具备堆的特性,但是仅包含叶子结点的子树已经是堆 (即在有n个结点的完全二叉树中,当i > [n/2]-1时,以关键码Ki为根的子树已经是堆。
(2)这时从含有内部结点数最少的子树(这种子树在完全二叉树的倒数第二层,此时i = [n/2]-1开始,从右至左依次调整。
(3)对这一层调整完成之后,继续对上一层进行同样的工作,直到整个过程到达树根时,整棵完全二叉树就成为一个堆了

1 template<class T>
2 void MaxHeap<T>::BuildHeap()
3 {
4     for(int i = CurrentSize/2-1; i >= 0; i--)
5     {
6         SiftDown(i);
7     }
8 }

·堆的删除操作

(1)把最末端结点填入删除产生的空位(保持完全二叉树的性质)
(2)为了保持堆的性质,比较当前结点和其父节点的大小来决定向上还是向下“筛选”,直到重新满足堆的性质位置

 1 template<class T>
 2 bool MaxHeap<T>::Remove(int pos,T& node)
 3 {
 4     if(pos < 0 || pos >= CurrentSize)
 5         return false;
 6     node = heapArray[pos];
 7     heapArray[pos] = heapArray[--CurrentSize];
 8     if(heapArray[Parent(pos)] < heapArray[pos])
 9     {
10         SiftUp(pos);
11     }
12     else SiftDown(pos);
13     return true;
14 }

下面是删除堆顶元素的代码:

 1 template<class T>
 2 T& MaxHeap<T>::RemoveMax()
 3 {
 4     if(CurrentSize == 0)
 5     {
 6         cout<<"Can't delete"<<endl;
 7         exit(1);
 8     }
 9     else
10     {
11         Swap(0,--CurrentSize);
12         if(CurrentSize>1)
13         {
14             SiftDown(0);
15         }
16         return heapArray[CurrentSize];
17     }
18 }

下面是该类的核心代码:

向下筛选:

 1 template<class T>
 2 void MaxHeap<T>::SiftDown(int left)
 3 {
 4     int i = left;           //标识父结点
 5     int j = LeftChild(i);   //标识关键码较小的子结点
 6     T temp = heapArray[i];  //保存父结点
 7     while(j < CurrentSize)  //筛选
 8     {
 9         if((j < CurrentSize-1)&&(heapArray[j] < heapArray[j+1]))
10         {//若有右结点,且大于左结点
11             j++;    //则j指向右结点
12         }
13         if(temp < heapArray[j])
14         {//若父结点小于子结点的值则交换位置
15             heapArray[i] = heapArray[j];
16             i = j;
17             j = LeftChild(j);
18         }
19         else break;//找到恰当的位置,跳出循环
20     }
21     heapArray[i] = temp;
22 }

向上筛选:

 1 template<class T>
 2 void MaxHeap<T>::SiftUp(int position)
 3 {   //从position开始向上调整
 4     int tempos = position;
 5     T temp = heapArray[tempos];
 6     while((tempos > 0)&&(temp > heapArray[Parent(tempos)]))
 7     {
 8         heapArray[tempos] = heapArray[Parent(tempos)];
 9         tempos = Parent(tempos);
10     }
11     heapArray[tempos] = temp;
12 }

测试函数:

 1 int main()
 2 {
 3     int a[10] = {1,2,3,4,5,6,7,8,9,3};
 4     MaxHeap<int> S(a,10,20);
 5     cout<<"构建最大堆:"<<endl;
 6     S.BuildHeap();
 7     S.print();
 8     cout<<"插入元素10:"<<endl;
 9     int newNode = 10;
10     S.Insert(newNode);
11     S.print();
12     cout<<"删除堆顶元素:"<<endl;
13     S.RemoveMax();
14     S.print();
15     cout<<"删除pos = 1的元素:"<<endl;
16     int x;
17     S.Remove(1,x);
18     cout<<"x = "<<x<<endl;
19     S.print();
20     return 0;
21 }

测试结果:

 

posted @ 2017-03-20 19:30  Strawberry丶  阅读(423)  评论(0编辑  收藏  举报