算法导论:c++堆排序&优先队列

预习了一下算法导论的堆排序,以前数据结构课简直是一知半解。
这里写图片描述

这里写图片描述
建大根堆的过程为从数组中间向左遍历,然后不断调整左右子树使得最大数处于根节点。一开始以为堆排序一定要用二叉树还写了个傻傻的建树程序。。。

数组调整为大根堆

/*调整大根堆*/
void max_heapify(int data[], int cur, int heapsize)
{
    int left = 2 * cur + 1;
    int right =left+1;
    int largest = cur;
    if (left<heapsize && data[left] > data[largest]) {
        largest = left; //最大为左子树
    }
    if (right<heapsize && data[right] > data[largest]) {
        largest = right;//最大为右子树
    }
    if (largest != cur) //根不是最大,则要交换
    {
        int temp = data[cur];
        data[cur] = data[largest];
        data[largest] = temp;
        max_heapify(data, largest, heapsize); //继续调整
    }
}
/*建立大根堆*/
void build_max_heap(int data[], int heapsize) 
{   //只需要对除了叶子节点以外的节点进行调整
    for (int i = heapsize / 2 - 1; i >= 0; i--) {
        max_heapify(data, i, heapsize);
    }
}

测试一下,输入一个数组

int main()
{
    const int len = 9;
    int array[len] = { 1,2,3,4,5,6,7,8,9};
    //convertArray2Tree(array,len);
    build_max_heap(array, len);
    for (int i = 0; i < len; i++)
    {
        cout << array[i] << " ";
    }
}

调整后输出为:9 8 7 4 5 6 3 2 1

堆排序

这里写图片描述
调整为大根堆后继续进行排序,将数组的头和最尾元素进行交换后再调整,把次大调整到数组头,再继续

/*堆排序*/
void heap_sort(int data[], int heapsize)
{
    build_max_heap(data, heapsize);
    for (int i = heapsize - 1; i>0; i--) //交换调整后的数组第一个元素和最后一个元素,再调整
    {
        int temp = data[0];
        data[0] = data[i];
        data[i] = temp;
        max_heapify(data,0,i);
    }
}

调整后输出:1 2 3 4 5 6

优先队列

这里写图片描述

这里写图片描述
实现优先队列返回最大和删除最大:

/*堆实现优先队列返回最大*/
int heap_maximum(int data[], int heapsize)
{
    return data[0];
}
/*堆实现返回优先队列最大并删除*/
int heap_extract_max(int data[], int heapsize)
{
    int max = data[0];
    data[0] = data[heapsize - 1]; //将最后一个元素放到第一
    heapsize = heapsize - 1; //删除一个元素
    max_heapify(data, 0, heapsize);  //调整
    return heapsize;
}

接上文的输入用例,删除最大元素9

int main()
{

    const int len = 9;
    int array[len] = { 1,2,3,4,5,6,7,8,9};
    build_max_heap(array, len);
    int lenNew = heap_extract_max(array, len);

    for (int i = 0; i < lenNew; i++)
    {
        cout << array[i] << " ";
    }
}

输出:8 5 7 4 1 6 3 2

这里写图片描述

这里写图片描述
实现增加第8个元素值至15。

/*增加值*/
void heap_increase_key(int data[], int heapsize, int i, int key) 
{
    if (data[i] > key) {
        return;
    }
    data[i] = key;
    while (i>=0 && data[(i - 1) / 2]<data[i]) //当前父节点比当前节点小,需要交换
    {
        int temp = data[i];
        data[i] = data[(i - 1) / 2];
        data[(i - 1) / 2] = temp;
        i = (i - 1) / 2;
    }
}
int main()
{

    const int len = 10;
    int array[len] = { 16,14,10,8,7,9,3,2,4,1};
    //convertArray2Tree(array,len);
    build_max_heap(array, len);
    heap_increase_key(array, len, 8, 15);
    for (int i = 0; i < len; i++)
    {
        cout << array[i] << " ";
    }

}

输入同文章中相同

输出:16 15 10 14 7 9 3 2 8 1

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值