堆排序

/**
 * 堆排序:C++
 *
 * @author skywang
 * @date 2014/03/11
 */

#include <iostream>
using namespace std;

/*
 * (最大)堆的向下调整算法
 *
 * 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。
 *     其中,N为数组下标索引值,如数组中第1个数对应的N为0。
 *
 * 参数说明:
 *     a -- 待排序的数组
 *     start -- 被下调节点的起始位置(一般为0,表示从第1个开始)
 *     end   -- 截至范围(一般为数组中最后一个元素的索引)
 */
void maxHeapDown(int* a, int start, int end)
{
    int c = start;            // 当前(current)节点的位置
    int l = 2*c + 1;        // 左(left)孩子的位置
    int tmp = a[c];            // 当前(current)节点的大小
    for (; l <= end; c=l,l=2*l+1)
    {
        // "l"是左孩子,"l+1"是右孩子
        if ( l < end && a[l] < a[l+1])
            l++;        // 左右两孩子中选择较大者,即m_heap[l+1]
        if (tmp >= a[l])
            break;        // 调整结束
        else            // 交换值
        {
            a[c] = a[l];
            a[l]= tmp;
        }
    }
}

/*
 * 堆排序(从小到大)
 *
 * 参数说明:
 *     a -- 待排序的数组
 *     n -- 数组的长度
 */
void heapSortAsc(int* a, int n)
{
    int i,tmp;

    // 从(n/2-1) --> 0逐次遍历。遍历之后,得到的数组实际上是一个(最大)二叉堆。
    for (i = n / 2 - 1; i >= 0; i--)
        maxHeapDown(a, i, n-1);

    // 从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素
    for (i = n - 1; i > 0; i--)
    {
        // 交换a[0]和a[i]。交换后,a[i]是a[0...i]中最大的。
        tmp = a[0];
        a[0] = a[i];
        a[i] = tmp;
        // 调整a[0...i-1],使得a[0...i-1]仍然是一个最大堆。
        // 即,保证a[i-1]是a[0...i-1]中的最大值。
        maxHeapDown(a, 0, i-1);
    }
}

/*
 * (最小)堆的向下调整算法
 *
 * 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。
 *     其中,N为数组下标索引值,如数组中第1个数对应的N为0。
 *
 * 参数说明:
 *     a -- 待排序的数组
 *     start -- 被下调节点的起始位置(一般为0,表示从第1个开始)
 *     end   -- 截至范围(一般为数组中最后一个元素的索引)
 */
void minHeapDown(int* a, int start, int end)
{
    int c = start;            // 当前(current)节点的位置
    int l = 2*c + 1;        // 左(left)孩子的位置
    int tmp = a[c];            // 当前(current)节点的大小
    for (; l <= end; c=l,l=2*l+1)
    {
        // "l"是左孩子,"l+1"是右孩子
        if ( l < end && a[l] > a[l+1])
            l++;        // 左右两孩子中选择较小者
        if (tmp <= a[l])
            break;        // 调整结束
        else            // 交换值
        {
            a[c] = a[l];
            a[l]= tmp;
        }
    }
}

/*
 * 堆排序(从大到小)
 *
 * 参数说明:
 *     a -- 待排序的数组
 *     n -- 数组的长度
 */
void heapSortDesc(int* a, int n)
{
    int i,tmp;

    // 从(n/2-1) --> 0逐次遍历每。遍历之后,得到的数组实际上是一个最小堆。
    for (i = n / 2 - 1; i >= 0; i--)
        minHeapDown(a, i, n-1);

    // 从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素
    for (i = n - 1; i > 0; i--)
    {
        // 交换a[0]和a[i]。交换后,a[i]是a[0...i]中最小的。
        tmp = a[0];
        a[0] = a[i];
        a[i] = tmp;
        // 调整a[0...i-1],使得a[0...i-1]仍然是一个最小堆。
        // 即,保证a[i-1]是a[0...i-1]中的最小值。
        minHeapDown(a, 0, i-1);
    }
}

int main()
{
    int i;
    int a[] = {20,30,90,40,70,110,60,10,100,50,80};
    int ilen = (sizeof(a)) / (sizeof(a[0]));

    cout << "before sort:";
    for (i=0; i<ilen; i++)
        cout << a[i] << " ";
    cout << endl;

    heapSortAsc(a, ilen);            // 升序排列
    //heapSortDesc(a, ilen);        // 降序排列

    cout << "after  sort:";
    for (i=0; i<ilen; i++)
        cout << a[i] << " ";
    cout << endl;

    return 0;
}



#include<iostream>
using namespace std;
void swap(int a[],int i,int j)
{
    int temp=a[i];
    a[i]=a[j];
    a[j]=temp;
}

/*参数说明:
r[]是待排序的数组;
k是当前要筛选的结点的位置;
m是堆中最后一个结点的位置;
假设结点k的左右子树均是堆,即r[k+1]~r[m]满足堆的条件,堆调整算法的c++描述如下:*/

//筛选法调整堆的算法Sift
void Sift(int r[],int k,int m)
{
    int i=k;
    int j=2*i+1;//i指向被筛选结点,j指向结点i的左孩子
    while(j<=m)//筛选还没有进行到叶子
    {
        if(j<m&&r[j]<r[j+1])j++;//比较i的左右孩子,将j指向较大者
        if(r[i]>r[j])break;//根结点已经大于左右孩子中的较大者
        else
        {
            swap(r,i,j);//将根结点与结点j交换
            i=j;
            j=2*i+1;//被筛结点位于原来结点j的位置
        }
    }
}

//堆排序算法
void HeapSort(int r[],int n)
{
    for(int i=n/2-1; i>=0; i--)//初建堆,从最后一个分支结点至根结点
    {
        Sift(r,i,n-1);
    }
   /* for(int i=0; i<n-1; i++) //重复执行移走堆顶及重建堆的操作
    {
        swap(r,0,n-i);//将堆顶与堆中最后一个记录交换
        Sift(r,0,n-i-1);//重建堆
    }*/
    for (int i = n - 1; i > 0; i--)
    {
        // 交换a[0]和a[i]。交换后,a[i]是a[0...i]中最大的。
        swap(r,0,i);
        // 调整a[0...i-1],使得a[0...i-1]仍然是一个最大堆。
        // 即,保证a[i-1]是a[0...i-1]中的最大值。
        Sift(r, 0, i-1);
    }
}

int main()
{
    int a[] = {10,9,8,7,6,5,4,3,2,1,0};
     int len= sizeof(a) / sizeof(int);


    cout << "堆排序前:";

    for (int i=0; i<len; i++)
        cout << a[i] << " ";
    cout << endl;
    HeapSort(a,len);
    cout << "堆排序后:";
    for (int i=0; i<len; i++)
        cout << a[i] << " ";
    cout << endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值