您的位置:首页 > 其它

最小堆及堆排序

2016-05-18 01:01 369 查看
头文件.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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: