「数组」堆排序 / 大根堆优化(C++)

目录

概述

核心概念:堆

堆结构

数组存堆

思路

算法过程

up()

down()

Code

优化方案

大根堆优化

Code(pro)

复杂度

总结


概述

「数组」快速排序 / 随机值优化|小区间插入优化(C++)中,我们介绍了三种基本排序中的冒泡排序与分治思想结合的算法:快速排序。

本文我们来讲第二种基本排序:选择排序与分治思想结合的产物:堆排序。

我们来回想选择排序:每次选出最小的元素放在数组头部位置,每次都扫描一遍整个数组,整体表现为O(n²)。

我们希望只进行少量比较就能得出数组中的最小元素,该怎么做呢?堆这种结构给了我们一点启发。


核心概念:堆

堆是一颗完全二叉树,它的特点是可以用一维数组来储存。

堆结构

在初学数组排序阶段就理解二叉树似乎有些困难,不过好在我们不必完全了解二叉树的所有概念。

我们只需要知道:

①一个堆是一个层状结构,除去最底一层,每层的每个节点都有左子节点和右子节点,层层布满。

节点从上到下,从左到右依次编号。

(对于这样的结构,我们称之为二叉树,每个父节点都有左右孩子指针指向子节点。) 

②只有最后一层允许节点不排满,但节点的排布仍然是严格从左到右的。

如下,图一和图二都是堆,但图三不是堆,因为它的最底层排布不是从左到右的。

 ③堆有两种:小根堆和大根堆。

小根堆要求父节点的值小于它的两个孩子,大根堆要求父节点的值大于它的两个孩子。

*注意*:一个节点的左右孩子之间的大小关系不做任何要求。

我们称二叉树的头结点为根,所以这种命名就很好理解了:小根堆的根最小,大根堆的根最大。

数组存堆

此时此刻我们完全不必知道二叉树的标准结构,因为数组就可以储存堆

观察:

我们发现,一个序号从0开始的堆结构,

### C++大根堆排序实现 堆排序是一种基于比较的选择排序方法,其核心思想是利用堆这种数据结构所设计的一种排序算法。堆分为大根堆和小根堆两种形式,在大根堆中,父节点的值总是大于等于子节点的值。 以下是C++实现的大根堆排序代码示例: ```cpp #include <iostream> using namespace std; // 调整堆的函数 void adjustHeap(int arr[], int i, int length) { int temp = arr[i]; // 取出当前元素i for (int k = 2 * i + 1; k < length; k = 2 * k + 1) { // 从i结点的左子结点开始 if (k + 1 < length && arr[k] < arr[k + 1]) { // 如果右子结点存在且较大,则指向右子结点 k++; } if (arr[k] > temp) { // 如果子结点大于父结点,则将较大的子结点赋值给父结点 arr[i] = arr[k]; i = k; } else { break; } } arr[i] = temp; // 将temp值放到最终的位置 } // 堆排序函数 void heapSort(int arr[], int length) { // 构建初始堆 for (int i = length / 2 - 1; i >= 0; i--) { adjustHeap(arr, i, length); } // 进行堆排序 for (int j = length - 1; j > 0; j--) { swap(arr[0], arr[j]); // 将当前最大值放到数组最后 adjustHeap(arr, 0, j); // 对剩余部分重新调整为堆 } } // 测试堆排序 int main() { int arr[] = {9, 8, 7, 6, 5, 4, 3, 2, 1}; int length = sizeof(arr) / sizeof(arr[0]); cout << "原始数组:" << endl; for (int i = 0; i < length; i++) { cout << arr[i] << " "; } cout << endl; heapSort(arr, length); cout << "排序后的数组:" << endl; for (int i = 0; i < length; i++) { cout << arr[i] << " "; } cout << endl; return 0; } ``` 上述代码实现了大根堆排序的核心功能[^3]。`adjustHeap` 函数用于维护堆的性质,而 `heapSort` 则完成了整个堆排序的过程。通过构建初始堆并将最大值逐步移至数组末端的方式完成排序过程。 #### 关键点解析 - **堆的构建**:从最后一个非叶子节点向上逐层调整,使得整个数组满足大根堆的特性。 - **交换与重建**:每次将堆顶的最大值与未排序序列中的最后一个元素互换位置,并对剩下的部分再次调用调整函数以恢复堆的性质。 此实现方式的时间复杂度为 O(nlogn),空间复杂度为 O(1)[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值