码迷,mamicode.com
首页 > 编程语言 > 详细

数据结构--二叉堆与堆排序

时间:2016-04-29 19:06:03      阅读:235      评论:0      收藏:0      [点我收藏+]

标签:

  • 二叉堆的概念

二叉堆,BinaryHeap,是二叉树中的常见的一种结构。通常以最大堆和最小堆的形式呈现。最大堆指的是父节点大于等于孩子节点的value值,也就是说对于最大堆而言,根元素是二叉堆最大的元素。最小堆的概念是与最大堆的概念是相似的。下图是最大堆的示意图:
技术分享


  • 二叉堆和排序之间的联系

二叉堆最显著的特征就是根元素是二叉树元素间最大的或者最小的。因此每次将二叉树最大或者最小的元素取出来,同时保证每次进行这样的操作后,剩下的元素依然可以保持二叉堆的性质,这样迭代这个过程,就可以完成排序的目的。

所以,进行堆排序的过程,首先就需要进行待排序元素的堆建立过程。这里以最大堆为例。

堆的建立过程

在建立最大堆的过程中,每插入一个元素,就要对元素进行一个上浮的操作。上浮是指对每个即将插入最大堆的元素进行判断,判断与当前元素与其父元素的大小关系,保持父元素与孩子元素之间的大小关系,重复这个过程,直到从根元素开始,所有的父元素和孩子元素都和二叉堆的定义保持一致。具体实现过程如下:

首先是最大堆的ADT:

template<class T>
class BinaryHeap
{
public:
    BinaryHeap(int capacity);
    ~BinaryHeap();

    void filterUp(int start);
    void Insert(T &data);


    T delHeap();

    void BuildHeap(vector<T> initArray);
    void displayHeap();

private:
    T *m_pData;
    int mCurSize;
    int mCapacity;
};
然后是最大堆的建立过程:

template<class T>
void BinaryHeap<T>::filterUp(int start)
{

    int nIndex=start;
    T temp=m_pData[nIndex];
    int parentIndex=(int) start/2;

    while(nIndex>0)
    {
        if(m_pData[parentIndex]<temp)
        {
            m_pData[nIndex]=m_pData[parentIndex];
            nIndex=parentIndex;
            parentIndex=(int) nIndex/2;
        }
        else
            break;
    }
    m_pData[nIndex]=temp;

}

template<class T>
void BinaryHeap<T>::Insert(T &data)
{
    if(mCurSize>=mCapacity)
    {
        mCapacity*=2;
        mCurSize++;
    }
    m_pData[mCurSize]=data;
    filterUp(mCurSize);
}

完成了最大堆的建立,就可以进行最大元素的抽取了,将抽取的元素存起来,就可以进行迭代过程的排序了:

这里在抽取最大元素的抽取后,相应的元素个数就会减少一个,如果是把根元素的孩子结点移动到根元素的位置,然后从上往下进行这样的移动,这样不能很好的保持完全二叉树的性质。因此这里采取的小技巧是,将二叉树的最后一个元素移动到根元素的位置,这样仅仅只是交换value值,不需要频繁的移动元素的位置。以下是该过程的示意图:

第一步:

技术分享

技术分享

第二步:

技术分享

技术分享


这样就完成了最大元素的抽取过程了,然后下面是具体的实现过程:

template<class T>
T BinaryHeap<T>::delHeap()
{
    int parentIndex=0;
    T tempMax=m_pData[parentIndex];
    int nIndex=parentIndex*2+1;

    m_pData[parentIndex]=m_pData[mCurSize-1];
    T tempCur=m_pData[parentIndex];
    while((nIndex+1)<mCurSize)
    {

        if(tempCur>=m_pData[nIndex] && tempCur>=m_pData[nIndex+1])
        {

            break;
        }
        else
        {
            if(m_pData[nIndex]>m_pData[nIndex+1])
                {
                    m_pData[parentIndex]=m_pData[nIndex];
                    parentIndex=nIndex;
                }
            else
                {
                     m_pData[parentIndex]=m_pData[nIndex+1];
                     parentIndex=nIndex+1;
                }

                     nIndex=2*parentIndex+1;
        }
    }
    m_pData[parentIndex]=tempCur;
    if(mCurSize>1)
        mCurSize--;
    else
    {
        mCurSize--;
        cout<<"the heap size is zero!"<<endl;
    }
    return tempMax;

}

以上就是关键的过程的代码,下面是完整过程的代码:

首先是二叉堆的头文件:

#ifndef BINARYHEAP_H_INCLUDED
#define BINARYHEAP_H_INCLUDED

#include<vector>
#include<queue>
#include<iostream>
using namespace std;
template<class T>
class BinaryHeap
{
public:
    BinaryHeap(int capacity);
    ~BinaryHeap();

    void filterUp(int start);
    void Insert(T &data);


    T delHeap();

    void BuildHeap(vector<T> initArray);
    void displayHeap();

private:
    T *m_pData;
    int mCurSize;
    int mCapacity;
};


template<class T>
BinaryHeap<T>::BinaryHeap(int capacity)
{
    mCurSize=0;
    mCapacity=capacity;
    m_pData=new T[capacity];
}

template<class T>
BinaryHeap<T>::~BinaryHeap()
{
    mCurSize=0;
    mCapacity=0;
    delete []m_pData;
}

template<class T>
void BinaryHeap<T>::filterUp(int start)
{

    int nIndex=start;
    T temp=m_pData[nIndex];
    int parentIndex=(int) start/2;

    while(nIndex>0)
    {
        if(m_pData[parentIndex]<temp)
        {
            m_pData[nIndex]=m_pData[parentIndex];
            nIndex=parentIndex;
            parentIndex=(int) nIndex/2;
        }
        else
            break;
    }
    m_pData[nIndex]=temp;

}

template<class T>
void BinaryHeap<T>::Insert(T &data)
{
    if(mCurSize>=mCapacity)
    {
        mCapacity*=2;
        mCurSize++;
    }
    m_pData[mCurSize]=data;
    filterUp(mCurSize);
}

template<class T>
void BinaryHeap<T>::BuildHeap(vector<T> initArray)
{
    int nSize=initArray.size();
    if(nSize==0)
        return;
    else
    {
        for(int i=0;i<nSize;i++)
        {
            Insert(initArray.at(i));
            if(mCurSize<mCapacity)
                mCurSize++;
            else
            {
                mCapacity*=2;
                mCurSize++;
            }
        }

    }
}

template<class T>
T BinaryHeap<T>::delHeap()
{
    int parentIndex=0;
    T tempMax=m_pData[parentIndex];
    int nIndex=parentIndex*2+1;

    m_pData[parentIndex]=m_pData[mCurSize-1];
    T tempCur=m_pData[parentIndex];
    while((nIndex+1)<mCurSize)
    {

        if(tempCur>=m_pData[nIndex] && tempCur>=m_pData[nIndex+1])
        {

            break;
        }
        else
        {
            if(m_pData[nIndex]>m_pData[nIndex+1])
                {
                    m_pData[parentIndex]=m_pData[nIndex];
                    parentIndex=nIndex;
                }
            else
                {
                     m_pData[parentIndex]=m_pData[nIndex+1];
                     parentIndex=nIndex+1;
                }

                     nIndex=2*parentIndex+1;
        }
    }
    m_pData[parentIndex]=tempCur;
    if(mCurSize>1)
        mCurSize--;
    else
    {
        mCurSize--;
        cout<<"the heap size is zero!"<<endl;
    }
    return tempMax;

}

template<class T>
void BinaryHeap<T>::displayHeap()
{
    for(int i=0;i<mCurSize;i++)
    {
        cout<<m_pData[i]<<"---";
    }
    cout<<endl;
}



#endif // BINARYHEAP_H_INCLUDED


然后是主过程的调用,在主过程完成排序:

#include <iostream>
#include<cstdlib>
#include<ctime>
#include"BinaryHeap.h"

using namespace std;

int main()
{
    srand(unsigned(time(NULL)));

    vector<int> initArray;
    int data=rand()%100;
    int length=rand()%15;
    int cnt=0;
    while(cnt<length)
    {
        initArray.push_back(data);
        data=rand()%100;
        cnt++;
    }

    cout<<"待排序序列:"<<endl;
    for(int i=0;i<length;i++)
        cout<<initArray.at(i)<<"---";
    cout<<endl;

    BinaryHeap<int> heap(30);
    heap.BuildHeap(initArray);
    cout<<"建立好的最大堆:"<<endl;
    heap.displayHeap();

    int maxEle;
    vector<int> sortedArray;
    for(int i=0;i<initArray.size();i++)
    {
        maxEle=heap.delHeap();
        sortedArray.push_back(maxEle);

    }

    cout<<"排序完成的序列:"<<endl;
    for(int i=0;i<sortedArray.size();i++)
    {
        cout<<sortedArray.at(i)<<"---";
    }
        cout<<endl;
    cout << "Hello world!" << endl;
    return 0;
}


然后结果如下:

技术分享


数据结构--二叉堆与堆排序

标签:

原文地址:http://blog.csdn.net/mao19931004/article/details/51236246

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!