最大堆、最小堆C++实现

来源:互联网 发布:ipad pro 记笔记 知乎 编辑:程序博客网 时间:2024/05/18 00:12
最近学习了最大堆、最小堆数据结构,这个并不难懂,但在编程、编写学习笔记时,发现有不少错误、理解不深刻,有比较多的细节需要注意的,特别是孩子节点的访问条件、几个节点之间的比较出了不少错误,但经过一番努力,终于解决了。下面是最大堆的实现过程


最大堆、最小堆 C++实现
最大堆概念:每个节点的值都大于其子节点的值的完全二叉树。
最小堆概念:每个节点的值都小于或等于其子节点的值的完全二叉树。


使用数组存储完全二叉树



在数组中存储二叉树,父节点 i 与孩子节点的关系是 2i + 1、2i + 2
左孩子:2i + 1 
有孩子:2i + 2




最大堆构造过程
下面将讲述五个元素{2,5,4,7,9} 构造最大堆过程。开始,插入关键值为2节点,节点2处于树根,插入结束。当插入关键值为5的节点时,由于节点5 比父节点 2大,互换。节点5处于树根,插入结束。插入节点4时,节点4比父节点5小,不用交换,插入结束。插入节点7时,节点7比父节点2大,互换。节点7比父节点5大,继续互换。交换完毕后节点7处于树根,插入结束。插入节点9,节点9比父节点5大,互换。节点9比节点7大,互换。此时节点9位于树根,插入结束。



算法过程:
首先检测堆是否已满,如果堆不满,i值编程 n+1,即新堆的长度,然后为item定位,确定它的堆中位置。while循环完成定位工作,具体做法是,从最大堆的新叶子i开始,与位于i/2的父亲比较,这样逐层向上,知道一个父亲关键字不少于它的位置,或者一直到根。(P175《数据结构基础 C语言版》第二版 Ellis Horowitz 、Sartaj Sahni、Susan Anderson-Freed 著)
说明:当初始为1开始,节点i的父亲下标为 i/2,初始以0位开始,节点i的父亲下标为
 (i-1)/2


部分代码
void push(T ielement)
 {                
     m_vecheap.push_back(ielement);//为向量增加一个元素位置空间                                        
     int hole=m_vecheap.size()-1;
     while(hole !=0 && ielement > m_vecheap[(hole-1)/2])
     {
  m_vecheap[hole]=m_vecheap[(hole-1)/2];
hole =(hole-1)/2;                        
      }
      m_vecheap[hole]=ielement;        
 }   


最大堆删除过程
保存最后一个节点node,将二叉树中最后一个节点删除,将hole指向0,【1】通过比较node、hole的孩子节点,得到最大的节点max, 如果max是node,则将node存放到hole指向的空间,结束删除动作,否则 将max放到hole指向的空间,然后hole指向max位置。重复【1】步骤,直到hole没有孩子节点,然后将node存放到hole指向的空间。



算法过程:
沿堆下滑,一路上比较父亲与孩子的关键字,并做必要交换,直到满足堆性质为止。


部分代码

void pop(){vector<int>::iterator itr = m_vecheap.end()-1;int element = *itr;m_vecheap.pop_back();                int hole=0;        int child=1;int nNum=m_vecheap.size();while(child< nNum){                                                                if ((child  < nNum -1) && (m_vecheap[child] < m_vecheap[child+1])){                                child++;}                        if (element > m_vecheap[child]){break;}m_vecheap[hole] = m_vecheap[child];        hole=child;child =2*child+1;}m_vecheap[hole]=element;}


C++  完成代码模板实现

template<class T>class CHeap{public:        explicit CHeap(){}        ~CHeap(){}        void push(T ielement)        {                                m_vecheap.push_back(ielement);//为向量增加一个元素位置空间                                                        int hole=m_vecheap.size()-1;                while(hole !=0 && ielement > m_vecheap[(hole-1)/2])                {                        m_vecheap[hole]=m_vecheap[(hole-1)/2];                        hole =(hole-1)/2;                                        }                m_vecheap[hole]=ielement;                }                void pop()        {                vector<int>::iterator itr = m_vecheap.end()-1;                int element = *itr;                m_vecheap.pop_back();                                int hole=0;                        int child=1;                int nNum=m_vecheap.size();                while(child< nNum)                {                                                                                        //通过比较,找出关键值最大的节点                        if ((child  < nNum -1) && (m_vecheap[child] < m_vecheap[child+1]))                        {                                                                child++;                        }                                                if (element > m_vecheap[child])                        {                                break;                        }                        m_vecheap[hole] = m_vecheap[child];                                hole=child;                        child =2*child+1;                }                m_vecheap[hole]=element;        }public:        vector<T> m_vecheap;        };

int main(void){CHeap<int> heap;heap.push(2);heap.push(4);heap.push(5);heap.push(7);heap.push(9);for (unsigned i=0 ; i < heap.m_vecheap.size(); i++){TRACE("%d ",heap.m_vecheap[i]);}TRACE("\n=================================\n");heap.pop();for (unsigned i=0 ; i < heap.m_vecheap.size(); i++){TRACE("%d ",heap.m_vecheap[i]);}TRACE("\n============================\n");heap.pop();for (unsigned i=0 ; i < heap.m_vecheap.size(); i++){TRACE("%d ",heap.m_vecheap[i]);}TRACE("\n============================\n");heap.pop();for (unsigned i=0 ; i < heap.m_vecheap.size(); i++){TRACE("%d ",heap.m_vecheap[i]);}TRACE("\n============================\n");system("pause");return 0;}



0 0
原创粉丝点击