c++堆排序

十、堆排序(不稳定)

步骤:1、构造初始化堆,将给定无序序列构造成一个大顶堆。

​ 首先给定的是无序序列,从最后一个非叶子节点开始,第一个非叶子结点 arr.length/2-1 从左到右,从上到下及进行调整。

证明:n个节点,x个非叶子节点,y个叶子节点。x+y=n -> x=y-1 ,

初始状态:

img

进行从下到上的调整:(最后导致结构混乱,然后重新调整)

img

​ 2、将堆顶元素与末尾元素进行交换,使末尾元素最大。将剩余元素重新构成一个堆,反复执行,得到一个有序序列。(每次组成大顶堆的时候,交换根节点和最后一个节点,然后最大的就放到最后,然后重新创建大顶堆)

堆是具有以下性质的完全二叉树:

一般升序采用大顶堆,降序采用小顶堆)

每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;

每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。

img

最后按照堆中的结点按层进行编号:

img
// 堆使用一个数组表示, 它可以当作一个完全二叉树,除了最底层之外,其它层都是满的,
// 并且最底层也是从左到右填充的。
//
// 当堆的下标(数组的下标)从1开始时比较好计算。因为:
//      1. 当父结点为i时, 左孩子为2i,  右孩子为2i+1;
//      2. 当孩子结点的下标为j时,父结点的下标为j/2 (根结点为父结点);
//      3. 一个结点的下标为k时, 则它所有的深度为 floor(logK);
//      4. 当一个堆共n个元素时,它的高度为floor(logN).
//
//                    1
//                /       \
//             2             3
//           /   \         /    \
//         4      5       6       7
//        / \    / \     /  \   /   \
//      8    9  10  11  12   13 14   15
//
// 
// 但是,数组的下标都是从0开始的,所以呢,我们下代码时,还是需要从0开始,而此时:
//     1. 当父结点的下标为i时,左孩子为2i+1, 右孩子为2*(i+1)
//     2. 当孩子结点的下标为j时,父结点的下标为(j-1)/2.
//
//                    0
//                /       \
//             1             2
//           /   \         /    \
//         3      4       5       6
//        / \    / \     /  \   /   \
//      7    8  9  10  11   12 13   14
#define left(x) 2*x+1;         //获得左节点在数组中的下标
#define right(x) 2 * (x + 1); //获得右节点在数组中的下标

void MaxHeap(int a[],int i,int low,int high) {  // i 表示根节点。low和high表示这段数组
    int l = left(i);
    int r = right(i);
    int largest;       //保存数组中最大数的变量
 // int tmp;           //用于交换

    //完成最大值的交换
    if (l <= high && a[l] > a[i]) {
        largest = l;
    }
    else {
        largest = i;
    }
    if (r <= high && a[r] > a[largest]) {
        largest = r;
    }
    if (largest != i) {
        swap1(a[i],a[largest]);
        MaxHeap(a,largest,low,high );
    }
}

//建立一个堆  从下向上建立大顶堆
void BuildMaxHeap(int a[], int length) {
    for (int i = length / 2 - 1; i >= 0; i--) {
        MaxHeap(a, i, 0, length - 1);
    }
}

//堆排序
void HeapSort(int a[],int length) {
    BuildMaxHeap( a,length);
    for (int i = length - 1; i >= 1; i--) {
        swap1(a[0],a[i]);   //交换堆顶元素和最后一个
        MaxHeap(a,0,0,i-1);
    }
}
///

参考:

​ https://blog.csdn.net/zhangsy_csdn/article/details/91483600

​ https://www.bilibili.com/video/BV1bz411e7vY

​ https://blog.csdn.net/aaa958099161/article/details/90923288

​ https://www.cnblogs.com/yinheyi/p/10836167.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值