C++超详细分析优化排序算法之堆排序

C++超详细分析优化排序算法之堆排序

堆排序算法的思路

堆排序算法是一种树形选择排序算法。它的基本思想是:将待排序的序列构造成一个大根堆(或小根堆),此时,整个序列的最大(或最小)值就是堆顶的根节点。将它移走(其实就是将其与堆数组的末尾元素交换,此时末尾元素就是最大(或最小)值),然后将剩余的n-1个序列重新构造成一个堆,这样,每次找出最大(或最小)值的操作就可以比较快速的完成。

堆排序算法的具体步骤

  1. 将待排序序列构造成一个大根堆(或小根堆),并保存堆上的元素个数,设为heap_size;

c++
void build_max_heap(int a[], int len, int heap_size) {
for(int i = len / 2 - 1; i >= 0; i--) {
max_heapify(a, i, len, heap_size);
}
}

  1. 将堆顶元素与末尾元素进行交换,此时堆顶元素为序列的最大值,调整堆,在堆长度中减去1,将剩余元素再构造成堆,重复此步骤直到堆长度减为1;

c++
void heap_sort(int a[], int len) {
int heap_size = len;
build_max_heap(a, len, heap_size);
for(int i = len - 1; i >= 1; i--) {
swap(a[0], a[i]);
heap_size--;
max_heapify(a, 0, i, heap_size);
}
}

  1. 维护堆性质,使得以i为根节点的子树满足堆的定义。

c++
void max_heapify(int a[], int i, int len, int heap_size) {
int l = i * 2 + 1, r = i * 2 + 2, max_idx = i;
if(l < len && a[l] > a[max_idx]) max_idx = l;
if(r < len && a[r] > a[max_idx]) max_idx = r;
if(max_idx != i) {
swap(a[i], a[max_idx]);
--heap_size;
max_heapify(a, max_idx, len, heap_size);
}
}

堆排序算法的优化

  1. 尽可能的减少函数调用次数,使用inline关键字修饰重要的函数

```c++
inline void swap(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}

inline void max_heapify(int a[], int i, int len, int heap_size) {
int l = i * 2 + 1, r = i * 2 + 2, max_idx = i;
if(l < len && a[l] > a[max_idx]) max_idx = l;
if(r < len && a[r] > a[max_idx]) max_idx = r;
if(max_idx != i) {
swap(a[i], a[max_idx]);
--heap_size;
max_heapify(a, max_idx, len, heap_size);
}
}
```

  1. 由于每次构造堆之前已经将最大值剔除,所以构造堆时只需要从剩余元素的一半开始,逐级向上调整即可

c++
void build_max_heap(int a[], int len, int heap_size) {
for(int i = len / 2 - 1; i >= 0; i--) {
max_heapify(a, i, len, heap_size);
}
}

  1. 在调整堆性质时,减少交换次数也能有效提升堆排序的效率

c++
void max_heapify(int a[], int i, int len, int heap_size) {
int l = i * 2 + 1, r = i * 2 + 2, max_idx = i;
if(l < len && a[l] > a[max_idx]) max_idx = l;
if(r < len && a[r] > a[max_idx]) max_idx = r;
if(max_idx != i) {
a[i] ^= a[max_idx] ^= a[i] ^= a[max_idx];
--heap_size;
max_heapify(a, max_idx, len, heap_size);
}
}

堆排序算法的时间复杂度及稳定性

堆排序算法的时间复杂度为 O(nlogn),它是不稳定的排序算法。

堆排序算法的示例说明

示例一

待排序序列:6,8,2,3,5,7,1

构造的大根堆:8,6,7,3,5,2,1

第一次排序后:1,6,7,3,5,2,8

构造的大根堆:7,6,1,3,5,2

第二次排序后:2,6,1,3,5,7

构造的大根堆:6,3,1,2,5

第三次排序后:5,3,1,2,6

构造的大根堆:3,2,1,5

第四次排序后:1,2,3,5

构造的大根堆:2,1,3

第五次排序后:1,2,3

构造的大根堆:2,1

第六次排序后:1,2

示例二

待排序序列:23,51,10,34,12,2,87,63

构造的大根堆:87,63,23,51,12,2,10,34

第一次排序后:34,63,23,51,12,2,10,87

构造的大根堆:63,51,23,34,12,2,10

第二次排序后:10,51,23,34,12,2,63

构造的大根堆:51,34,23,10,12,2

第三次排序后:2,34,23,10,12,51

构造的大根堆:34,12,23,2,10

第四次排序后:10,12,23,2,34

构造的大根堆:23,12,10,2

第五次排序后:2,12,10,23

构造的大根堆:12,2,10

第六次排序后:2,10,12

构造的大根堆:10,2

第七次排序后:2,10

构造的大根堆:10

第八次排序后:10

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++超详细分析优化排序算法之堆排序 - Python技术站

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

相关文章

  • TF-IDF与余弦相似性的应用(一) 自动提取关键词

    下面我将详细讲解“TF-IDF与余弦相似性的应用(一) 自动提取关键词”的完整攻略。 什么是TF-IDF? TF-IDF(Term Frequency-Inverse Document Frequency)是一种常用于信息检索与分类中的文本特征提取方法,用于评估一段文本中词的重要程度。TF-IDF的核心思想就是:一个词在一篇文档中出现的频次(TF)越高,同时…

    算法与数据结构 2023年5月19日
    00
  • c++深入浅出讲解堆排序和堆

    C++深入浅出讲解堆排序和堆 堆的定义 堆是一种特殊的树形数据结构,它满足以下两个特性: 堆是一个完全二叉树(Complete Binary Tree); 堆中每个节点的值都大于等于(或小于等于)其左右子节点的值。 可以看出,堆一般分为两种类型:大根堆(Max Heap)和小根堆(Min Heap)。大根堆的每个节点的值都大于等于其左右子节点的值,小根堆则相…

    算法与数据结构 2023年5月19日
    00
  • 大数据情况下桶排序算法的运用与C++代码实现示例

    桶排序算法是一种基于计数的排序算法,它的主要思想是把一组数据分成多个桶,对每个桶中的数据进行排序,最后依次把每个桶中的数据合并起来,得到排序后的结果。在大数据情况下,桶排序算法可以大幅减少排序时间,因为它可以快速地将数据分成多个桶,进行并行排序,最终合并起来。 以下是桶排序算法在大数据情况下的运用及C++代码示例: 算法思路 先确定桶的数量,也就是需要将数据…

    算法与数据结构 2023年5月19日
    00
  • 微信红包随机生成算法php版

    下面我会详细讲解“微信红包随机生成算法php版”的完整攻略。 算法简介 微信的红包算法采用的是二倍均值法,即将总金额分成若干个等份,然后按照一定的规则分配给每个红包领取者,使得每个红包领取者所得到的金额期望相等。具体来说,就是按照以下步骤来生成红包: 首先获取红包数量和总金额。 计算出每个红包的最大金额,即 max = totalAmount / num *…

    算法与数据结构 2023年5月19日
    00
  • 深入解析Radix Sort基数排序算法思想及C语言实现示例

    深入解析Radix Sort基数排序算法思想及C语言实现示例 什么是基数排序算法 基数排序即Radix Sort,是一种非比较型排序算法。相比于其他排序算法,如快速排序、归并排序等,基数排序的时间复杂度较为稳定,且不受数据规模的影响,适用于数据范围较小但位数较多的序列排序。 基数排序算法思想 基数排序算法的核心思想是按照不同位数上的数字对数据进行排序,从低位…

    算法与数据结构 2023年5月19日
    00
  • JS实现给数组对象排序的方法分析

    下面是一份详细讲解“JS实现给数组对象排序的方法分析”的攻略。 一、前言 数组是 JavaScript 中非常常见的一种数据结构,它可以用来存储一系列的数据。而在实际的开发过程中,我们会经常需要对数组进行排序,这里我们就来详细讲解一下如何使用 JavaScript 实现给数组对象排序的方法。 二、排序方法详解 JavaScript 提供了三个内置的方法来对数…

    算法与数据结构 2023年5月19日
    00
  • C语言冒泡排序算法代码详解

    下面是“C语言冒泡排序算法代码详解”的完整攻略: 1. 冒泡排序算法原理 冒泡排序是一种基础的排序算法,其基本思想是将待排序的数组中的相邻元素两两比较,如果前面的元素大于后面的元素,则交换它们的位置,直到比较完所有元素。这样一轮比较交换之后,最大(或最小)的元素会被放到最后(或最前),然后再对剩下的元素重复以上步骤,直到所有元素都排好序为止。 2. 冒泡排序…

    算法与数据结构 2023年5月19日
    00
  • JS栈stack类的实现与使用方法示例

    JS栈Stack类的实现与使用方法示例 一、栈的概念 栈(stack)是一种线性数据结构,它有两个主要操作:入栈(push)和出栈(pop)。栈的特点是先进后出(FILO,First In, Last Out)。从数据结构的角度来说,栈是在同一端进行插入和删除操作的一种数据结构。该端被称为栈顶,相对地,把另一端称为栈底。 在计算机科学中,栈具有非常重要的作用…

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