堆的构建及堆排序(C++)

首先给出堆的定义(这里转自https://blog.csdn.net/u011068702/article/details/52771173

n个元素的序列{k1,k2,…,kn}当且仅当满足下列关系之一时,称之为堆。

  情形1:k_{i} <= k_{2i} 且k_{i} <= k_{2i + 1} (最小化堆或小顶堆)

  情形2:k_{i} >= k_{2i} 且k_{i} >=  k_{2i + 1}(最大化堆或大顶堆)

  其中i=1,2,…,n/2向下取整;

这边两个定义是由序号从0开始取还是从1开始取决定的。

说明一下定义的意思,因为堆是完全二叉树(官方定义是:若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树),其实很简单即只有最后一层可以不全,其他各层节点都是满的,而且就算最后一层不全,也不能出现只有右孩子而没有左孩子的情况,即所有结点都连续集中在最左边。

而且二叉树的序列化即写成数组形式用的是层遍历,因此有个很好的性质即第i个节点的左右孩子序号分别为2i和2i+1,而且最后一个有孩子的节点序号为n/2,n为节点个数。(这里序号从1开始)

因此在构建大根堆的时候我们可以从最后一个有孩子的节点序号开始向前遍历,如果该节点比它的孩子小就交换(只需要考虑当前节点和他的孩子)。

而堆排序很巧妙,首先构建好大根堆,然后我们拿出头节点和最后一个节点交换,因为头节点一定是最大的,所以现在已经将最大的值放入数组最后了,然后使用除了最后一个元素的数组再次构建大根堆,这样循环下来就可以将数组排序。代码如下:

#include<iostream>
using namespace std;
class HeapSort {
public:
    void heapSort(int* A, int n)
    //堆排序
    {
        int i,temp;
        for(i=n/2-1;i>=0;--i)//从最后一个有孩子的节点开始循环来构建大根堆
            HeapAdjust(A,i,n-1);
        for(i=n-1;i>0;i--)//交换头节点和第i个元素,并使用前i个元素构建新的大根堆
        {
            temp=A[0];
            A[0]=A[i];
            A[i]=temp;
            HeapAdjust(A,0,i-1);
        }
    }
    void HeapAdjust(int *A,int s,int m)
    //已知A[s,...,m]中记录的关键字除A[s]之外均满足堆的定义,本函数调整A[s]
    //的关键字,使A[s,...,m]成为一个大顶堆(对其中记录的关键字而言)
    {
        int j,rc=A[s];
        for(j=2*s+1;j<=m;j=2*j+1)
        {
            if(j<m&&A[j]<A[j+1])j++;//右孩子更大
            if(rc>A[j])break;//比孩子大则跳出
            A[s]=A[j];
            s=j;
        }
        A[s]=rc;
    }
};
int main()
{
    int arr[]={54,35,48,36,27,12,44,44,8,14,26,17,28};
    HeapSort a;
    a.heapSort(arr,13);
    for(int i=0;i<13;i++)
        cout<<arr[i]<<" ";
    cout<<endl;
    return 0;
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
堆排序是一种使用数据结构进行排序的算法。是一种特殊的二叉树结构,具有以下性质:对于每个节点i,其父节点为(i-1)/2,左子节点为2*i+1,右子节点为2*i+2。堆排序的基本思想是将待排序的数组构建成一个最大(或最小),然后不断地将顶元素与的最后一个元素交换,并进行调整操作,直到所有元素都被排序。以下是堆排序的步骤: 1. 构建最大(或最小):从待排序数组中构建一个二叉,使得每个父节点的值都大于(或小于)它的子节点的值。 2. 交换顶元素与的最后一个元素:将顶元素与的最后一个元素交换位置,将最大值(或最小值)放在数组的末尾。 3. 进行调整:对交换后的进行调整,使其满足的性质。 4. 重复步骤2和步骤3,直到所有元素都被排序。 以下是使用C++实现堆排序的代码示例: ```cpp #include <iostream> using namespace std; void heapify(int arr[], int n, int i) { int largest = i; // 顶元素 int left = 2 * i + 1; // 左子节点 int right = 2 * i + 2; // 右子节点 // 比较左子节点与顶元素 if (left < n && arr[left] > arr[largest]) largest = left; // 比较右子节点与顶元素 if (right < n && arr[right] > arr[largest]) largest = right; // 如果顶元素不是最大值,则交换位置并进行调整 if (largest != i) { swap(arr[i], arr[largest]); heapify(arr, n, largest); } } void heapSort(int arr[], int n) { // 构建最大,从最后一个非叶子节点开始进行调整 for (int i = n / 2 - 1; i >= 0; i--) heapify(arr, n, i); // 交换顶元素与的最后一个元素,并进行调整 for (int i = n - 1; i >= 0; i--) { swap(arr[0], arr[i]); heapify(arr, i, 0); } } int main() { int arr[] = {64, 25, 12, 22, 11}; int n = sizeof(arr) / sizeof(arr[0]); heapSort(arr, n); cout << "排序后的数组:\n"; for (int i = 0; i < n; i++) { cout << arr[i] << " "; } cout << endl; return 0; } ``` 这段代码中,定义了一个`heapify`函数用于进行调整操作,使得以节点i为根的子树满足的性质。然后,通过`heapSort`函数进行堆排序,首先构建最大,然后不断地交换顶元素与的最后一个元素,并进行调整。在`main`函数中,声明了一个待排序的数组`arr`,然后通过调用`heapSort`函数对其进行排序。最后,打印出排序后的数组。 运行以上代码,输出结果为:11 12 22 25 64,表示数组已成功排序。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值