C++中二叉堆排序详解

C++中二叉堆排序详解

什么是二叉堆排序

二叉堆是一种特殊的二叉树,它有两个特性:

  1. 根节点的键值是所有节点中最小/最大的;
  2. 对于节点i的键值一定不大/小于它的父节点i/2。

根据第二个规则,我们可以对于任何一个节点i,以i为根的子树都是一个小根堆/大根堆。将二叉堆中最小/最大的根节点取出,然后将最后一个节点放到根位置,再对根节点进行一次向下调整的操作,就可以将次小/大的节点取出。以此类推,不断重复这个过程,直到所有的节点都取出来了,则排序完成。

C++实现

向下调整

向下调整的过程需要通过一个函数来实现,如果当前节点的子节点比当前节点更小(小根堆)或更大(大根堆),则需要对当前节点进行调整,将当前节点与子节点交换。

void adjustDown(vector<int>& nums, int i, int len) {
    int temp = nums[i];
    int targetIndex = i * 2 + 1;
    while (targetIndex < len) {
        if (targetIndex + 1 < len and nums[targetIndex+1] < nums[targetIndex]) {
            targetIndex ++;
        }
        if (nums[targetIndex] >= temp) {
            break;
        }
        nums[i] = nums[targetIndex];
        i = targetIndex;
        targetIndex = 2 * i + 1;
    }
    nums[i] = temp;
}

建立二叉堆

建立二叉堆其实就是将一个乱序的数组转化为二叉堆。我们可以在数组中依次取出每个数字,将其插入到构建好的二叉堆中。

void buildHeap(vector<int>& nums) {
    int len = nums.size();
    int endNode = len / 2 - 1;
    for (int i = endNode; i >= 0; i--) {
        adjustDown(nums, i, len);
    }
}

排序

当我们建立好一颗二叉堆时,有一个非常重要的性质就是:最小/大值一定在数组的第一个位置,我们可以将其直接取出并放在排序好后数组的最后。通过这个方式,我们不断取出最小/大值,一次放在排序后的数组中,直到整个数组都排序完成。

void heapSort(vector<int>& nums) {
    // 建立二叉堆
    buildHeap(nums);

    // 从最后一个节点开始往前取数
    int len = nums.size();
    for (int i = len - 1; i > 0; i--) {
        swap(nums[0], nums[i]);  // 将最后一个元素放在排序好的队列首部
        adjustDown(nums, 0, i);  // 建立一个新的二叉堆,并将下一个最小/大值放在根节点位置
    }
}

示例

以小根堆为例,对于一个乱序的数组 [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5],我们可以通过以下方式进行二叉堆排序:

vector<int> nums = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5};

// 将乱序数组转化为小根堆
buildHeap(nums);
// 输出建立完成的小根堆
cout << "Heap: ";
for (int num: nums) {
    cout << num << " ";
}
cout << endl;

// 对小根堆进行排序
heapSort(nums);
// 输出排序完成后的数组
cout << "Sorted nums: ";
for (int num: nums) {
    cout << num << " ";
}

输出结果如下:

Heap: 1 1 2 3 3 4 9 6 5 5 5 
Sorted nums: 1 1 2 3 3 4 5 5 5 6 9 

总结

通过现在的学习,我们了解了什么是二叉堆排序,也实现了在C++中二叉堆排序的过程。二叉堆排序是常用的排序算法,其时间复杂度为O(nlogn)。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++中二叉堆排序详解 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • C语言实现文件内容按行随机排列的算法示例

    下面我将为您详细介绍“C语言实现文件内容按行随机排列的算法示例”的完整攻略。 1、问题描述 首先,这个算法的问题描述是:实现一个按行随机排列文件内容的算法,要求结果能够尽可能地随机、均匀。 2、算法思路 针对这个问题,我们可以采用以下算法思路: 首先读取文件的全部内容,将其中的每一行存在一个字符串数组中; 然后采用洗牌算法(shuffle algorithm…

    算法与数据结构 2023年5月19日
    00
  • JS中数组随机排序实现方法(原地算法sort/shuffle算法)

    JS中实现数组随机排序有两种常见方法:原地随机排序算法和使用shuffle算法。 原地随机排序算法 原地随机排序算法(in-place shuffle algorithm)是将数组中元素随机地乱序,同时保持每个元素之间的相对位置不变。算法的时间复杂度是O(n),空间复杂度是O(1),因为所有的操作都是在原数组上进行。 实现步骤 获取数组长度 从数组的最后一个…

    算法与数据结构 2023年5月19日
    00
  • 2019年京东前端工程师面试题(附答案)

    本次将会以京东前端工程师面试题为例,详细讲解如何准备和应对前端岗面试。 第一步:了解面试整体流程和考察的技能点 在准备面试前,需要先了解面试的整体流程和所考察的技能点,从而根据需要和缺点来进行有针对性的准备。 面试的整体流程一般包括: 自我介绍和岗位广告 聊聊项目和技术栈 问题解答和技术评测 算法/编码能力测试 HR面试 而在前端工程师的岗位面试中,考察的技…

    算法与数据结构 2023年5月19日
    00
  • Java冒泡排序法和选择排序法的实现

    Java的冒泡排序法和选择排序法都是常用的排序算法,冒泡排序法和选择排序法的原理都很简单,但是实现方法有一些区别。 冒泡排序法 冒泡排序法的原理是通过不断交换相邻的元素,比较他们的大小,将大的数不断上移或者将小的数下移,直到整个序列排好顺序。 以下是Java实现冒泡排序法的代码: public class BubbleSort { public static…

    算法与数据结构 2023年5月19日
    00
  • C语言实现单链表的快速排序算法

    下面是详细的攻略: 单链表快速排序算法的原理 在单链表上实现快速排序,需要了解快速排序算法的原理。快速排序是一种常用的基于比较的排序算法,它的基本思想是:选取一个基准元素(pivot),将数组分成两个部分,一个部分是小于基准元素的,一个部分是大于基准元素的。然后对这两个部分分别递归进行快排,最终得到排序后的数组。 在单链表上,选择基准元素也是一样的,不同的是…

    算法与数据结构 2023年5月19日
    00
  • java实现图形卡片排序游戏

    以下是“Java实现图形卡片排序游戏”的完整攻略。这个游戏的目标是将打乱的卡片,按顺序排好。具体的操作方法是通过拖拽卡片,让卡片位置移动进行排序。 技术栈 Java语言 Swing GUI库 排序算法 功能设计 加载卡片图片及绑定事件处理方法 卡片随机化处理 拖拽移动卡片 实现移动时的动画效果 判断拼图是否按顺序排好 记录游戏步骤、分数等信息 具体实现 加载…

    算法与数据结构 2023年5月19日
    00
  • C#归并排序的实现方法(递归,非递归,自然归并)

    下面是关于C#归并排序的实现方法的完整攻略: 什么是归并排序? 归并排序是一种基于分治法的算法,具体实现方法是将原序列分成若干个子序列,分别进行排序,然后将排好序的子序列合并成一个大的有序序列。 递归实现归并排序 递归实现归并排序分为三步: 分解数组:将要排序的数组从中间分成两个部分,即分为左右两个子数组。这里使用数组下标来实现。 递归排序子数组:对分解出来…

    算法与数据结构 2023年5月19日
    00
  • javascript冒泡排序小结

    JavaScript冒泡排序小结 什么是冒泡排序 冒泡排序是一种经典排序算法,它重复地走访过要排序的数列,每次比较相邻的两个元素,如果顺序不对则交换它们,直到没有需要交换的元素为止。 冒泡排序的步骤 冒泡排序的主要步骤如下: 比较相邻的元素。如果第一个比第二个大,就交换它们; 对每一对相邻的元素做同样的工作,从开始的第一对到结尾的最后一对,这样在最后的元素应…

    算法与数据结构 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部