首页 技术 正文
技术 2022年11月19日
0 收藏 996 点赞 2,189 浏览 2825 个字

上次用Java实现了最大堆的封装,这次就来写一下最小堆的实现吧


插入函数的思路:

向堆中插入元素有两种情况,一种是堆为空,那么就让插入值作为根节点即可;另一种是堆不为空,那么此时就要进行判断当前节点与其父节点的大小关系比较。此时仍有两种情况,一种是当前节点大于父节点,这样正是我们所希望的;另一种是当前节点的值小于父节点,那么就要将二者的值进行调换,然后记得更新当前节点为原来父节点的位置,而父节点的位置同样需要更新(循环正常终止的时候说明已经到了根节点,此时最小值必定为根节点)

 bool Insert(T data){        if(currentPos==MaxSize){            cout<<"Sorry , this heap is full!"<<endl;            return false;        }        currentPos++;        int targetPos=currentPos-1;        heap[targetPos]=data;        while(targetPos>0){            int parentPos=(targetPos-1)/2;            if(heap[parentPos]<heap[targetPos]){                break;            }else{                heap[targetPos]=heap[parentPos];                targetPos=parentPos;            }        }        return true;    }    //存在的bug是对根节点的大小比较,因为有可能targetPos=0而退出,此时就缺少了一次比较

siftDown调整过程思路:

给定要进行调整的节点的下标,我们只需要让它和它的两个子节点中最小的那个比较即可(前提是当前节点不是叶子节点),需要注意的是要先保存当前节点的值,比较之后按大小调整顺序即可。

 void siftDown(int siftPos){        int siftPosition=siftPos;        T temp=heap[siftPosition];        int minChildPos=2*siftPosition+1;        while(minChildPos<currentPos){          //保证比较的条件成立            if((minChildPos<currentPos-1)&&(heap[minChildPos]>heap[minChildPos+1])){                minChildPos++;            }            if(temp<heap[minChildPos]){                break;            }else{                heap[siftPosition]=heap[minChildPos];                siftPosition=minChildPos;                minChildPos=2*siftPosition+1;            }        }        //作用:当要进行调换的位置不满足循环要求时,说明要进行调换的位置是叶子节点,那就不需要变换咯(这里也包括正常比较情况,可正常使用)        heap[siftPosition]=temp; }

删除对顶元素

需要注意的是currentPos的大小要实时的进行更新,然后返回所删除的堆顶元素即可

 T& deleteTop(){        if(currentPos<0){            cout<<"Sorry ,this heap is empty!"<<endl;        }        T target=heap[0];        heap[0]=heap[currentPos-1];        currentPos--;        siftDown(0);        return target;    }

下面是完整的C++关于最小堆的实现的代码

#include <iostream>using namespace std;template<class T>class MinHeap{    T *heap;    int MaxSize;    int currentPos;public:    MinHeap(int MS){        heap=new T[MS];        currentPos=0;        MaxSize=MS;    }    bool Insert(T data){        if(currentPos==MaxSize){            cout<<"Sorry , this heap is full!"<<endl;            return false;        }        currentPos++;        int targetPos=currentPos-1;        heap[targetPos]=data;        while(targetPos>0){            int parentPos=(targetPos-1)/2;            if(heap[parentPos]<heap[targetPos]){                break;            }else{                heap[targetPos]=heap[parentPos];                targetPos=parentPos;            }        }        return true;    }    void siftDown(int siftPos){        int siftPosition=siftPos;        T temp=heap[siftPosition];        int minChildPos=2*siftPosition+1;        while(minChildPos<currentPos){          //保证比较的条件成立            if((minChildPos<currentPos-1)&&(heap[minChildPos]>heap[minChildPos+1])){                minChildPos++;            }            if(temp<heap[minChildPos]){                break;            }else{                heap[siftPosition]=heap[minChildPos];                siftPosition=minChildPos;                minChildPos=2*siftPosition+1;            }        }        //作用:当要进行调换的位置不满足循环要求时,说明要进行调换的位置是叶子节点,那就不需要变换咯        heap[siftPosition]=temp;        ////////////////////////////////////////////    }    T& deleteTop(){        if(currentPos<0){            cout<<"Sorry ,this heap is empty!"<<endl;        }        T target=heap[0];        heap[0]=heap[currentPos-1];        currentPos--;        siftDown(0);        return target;    }};int main(){    cout << "Hello world!" << endl;    MinHeap<int> minHeap(7);    minHeap.Insert(1);    minHeap.Insert(2);    minHeap.Insert(4);    minHeap.Insert(3);    minHeap.Insert(6);    minHeap.Insert(7);    minHeap.Insert(5);    for(int i=1;i<=7;i++){        cout<<minHeap.deleteTop()<<endl;    }    return 0;}

程序运行结果如下


总结:

代码中存在一定得错误,出在 Insert函数中。个人认为需要对targetPos为0的特殊情况再加一层判断,估计就能解决。但是对正常添加元素还是能得到比较正常的结果的。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,084
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,559
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,408
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,181
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,818
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,901