最小堆及堆排序

头文件.h:

 

#ifndef MINHEAP_H_INCLUDED
#define MINHEAP_H_INCLUDED
#define  DefaultSize 20                 //默认堆大小
class MinHeap
{
private:
    int  *heap;                         //指向存放最小堆元素的数组
    int currentSize;                    //最小堆中当前元素个数
    int MaxHeapSize;                    //最小堆最多允许元素
    void siftDown(int start,int over);           //下浮函数,从start到数组中最后一个元素 下滑调整成为最小堆
    void siftUp(int start);                //上浮函数,从start到0逐步调整成为最小堆
public:
    MinHeap(int A[],int n);                         //构造函数,通过一个数组建堆
    ~MinHeap(){delete []heap;}            //析构函数
    // new 分配的单个对象的内存空间的时候用 delete,回收用 new[] 分配的一组对象的内存空间的时候用 delete[]
    bool Insert(const int &x);          //将x插入到堆的合适位置
    bool RemoveMin(int &x);             //删除堆顶最小的元素,并保存到x值
    bool IsEmpty()const                 //判断堆是否为空
    {return (currentSize==0)?true:false;}
    bool IsFull()const                  //判断堆是否已满
    {return (currentSize==MaxHeapSize)?true:false;}
    void MakeEmpty(){currentSize=0;}    //置空堆
    void Traverse();                    //遍历堆
    void HeapSort(int A[],int &n);                    //最小堆排序,按照从小到大的顺序排序
};



#endif // MINHEAP_H_INCLUDED



源文件.cpp:

 

 

#include "MinHeap.h"
#include <iostream>
using namespace std;
//构造函数,通过传入的数组创建堆
MinHeap::MinHeap(int A[],int n)
{
    currentSize=n;
    MaxHeapSize=(n>DefaultSize)?n:DefaultSize;
    heap=new int[currentSize];                   //创建堆存储空间,并返回数组指针给堆指针
    for(int i=0;i<n;i++)
        heap[i]=A[i];                            //复制堆数组
    int position=(currentSize-2)/2;              //寻找最后一个非叶子节点
    while(position>=0)                            //自底向上逐步扩大形成堆
    {
        siftDown(position,currentSize-1);        //局部从上到下下滑调整
        position--;                              //向前移一位继续调整
    }


}
//siftDown: 从结点start开始到数组最后一个元素(包括)为止,自上向下比较,如果子女的值小于父结点的值,
//          则小的值上浮,继续向下层比较,这样将一个集合局部调整为最小堆
void MinHeap::siftDown(int start,int over)
{
    int i=start,j=2*i+1,t;                              //j为i的左子女下标
    while(j<=over)                                      //j超过over则跳出循环
    {
        if(j<over&&heap[j+1]<heap[j]) j++; //如果j没到over即说明i有右子女,若右子女较小,j指向右子女位置,最终j指向两子女中较小的位置
        if(heap[i]<=heap[j])   break;                   //如果父结点比左右子树最小的值还小,则不做调整,循环终止
        else {
                 t=heap[i];heap[i]=heap[j];heap[j]=t;   //否则交换两个结点的值
                 i=j;j=2*i+1;                           //i到j位置,j到j的左子女处
             }
    }

}

//插入结点到已有的堆中,利用siftUp函数
bool MinHeap::Insert(const int& x)
{
    if(currentSize==MaxHeapSize) return false;        //堆满
    heap[currentSize]=x;                              //将堆数组末尾插入x
    siftUp(currentSize);                              //传入当前要调整的结点位置
    currentSize++;                                   //堆的长度+1
    return true;
}
//siftUp: 从start到数组下标为0 的元素位置,自下向上比较,子女的值小于父结点的值
//        父结点下沉,将集合调整为最小堆(将原先创建好的最小堆 与新的结点调整为新的最小堆)
void MinHeap::siftUp(int start)
{
    int j=start,i=(j-1)/2,t;                            //j=2*i+1;无论j为左/右子女位置,i=(j-1)/2 得到的始终是父结点下标
    while(i>=0)
    {
        if(heap[i]<=heap[j])  break;                  //父结点值小,不调整,跳出循环
        else {
                t=heap[i];heap[i]=heap[j];heap[j]=t;  //插入结点小,与父结点交换
                j=i;i=(j-1)/2;                        //j移到父结点i的位置,i到i的父结点
             }
    }
}

//Remove删除堆顶最小的元素,将堆中最后一个元素移到堆顶,调用siftDown函数重新调整成最小堆
bool MinHeap::RemoveMin(int &x)
{
    if(currentSize==0) return false;                  //堆空
    x=heap[0];                                        //保存堆顶元素
    heap[0]=heap[currentSize-1];                      //将堆中最后一个元素移到栈顶
    currentSize--;                                    //堆的长度-1
    siftDown(0,currentSize-1);                                      //只要从0位置调整即可
    return true;
}
void MinHeap::Traverse()
{
    cout<<"遍历堆的结果:";
    int i;
    for(i=0;i<currentSize;i++)
        cout<<heap[i]<<" ";
    cout<<endl;
}
 <pre name="code" class="cpp">//最小堆,堆内部排序后得到的是从大到小的顺序
//最大堆,堆内部排序后得到的是从小到大的顺序

//堆排序,用数组A保存从小到大的排序结果,n保存数组长度void MinHeap::HeapSort(int A[],int &n){ int t,i,j; for(i=currentSize-1;i>=0;i--) //堆里面最终得到的是从大到小的顺序 { t=heap[0];heap[0]=heap[i];heap[i]=t; siftDown(0,i-1); } for(i=currentSize-1,j=0;i>=0;j++,i--) A[j]=heap[i]; n=currentSize; return ;}

 

 

 


主函数main.h:

 

 

 

 

#include <iostream>
#include "MinHeap.h"
using namespace std;
#define Max 20
int main()
{
    int A[Max],i=0,n,m,k;
    cout<<"请输入初始化堆的长度:";
    cin>>n;
    cout<<"请输入要创建的堆的数据,以f6/ctrl+Z结束:";
    for(i=0;i<n;i++)
        cin>>A[i];
    MinHeap h(A,n);             //初始化构造一个堆
    h.Traverse();
    cout<<"请输入要插入的结点:";
    cin>>m;
    h.Insert(m);
    cout<<"插入结点后:";
    h.Traverse();
    h.RemoveMin(k);
    cout<<endl<<"删除的元素为: "<<k<<endl;
    cout<<"删除结点后:"<<endl;
    h.Traverse();
    h.HeapSort(A,n);
    cout<<endl<<"排序后堆中元素(从大到小): ";
    h.Traverse();
    cout<<endl<<"按从小到大顺序:";
    for(i=0;i<n;i++)
        cout<<A[i]<<" ";
    cout<<endl;
    return 0;
}

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值