堆排序学习笔记
Posted 药菌
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆排序学习笔记相关的知识,希望对你有一定的参考价值。
1.堆介绍
堆的物理存储结构是一维数组,逻辑存储结构是完全二叉树,它满足下列性质:
堆中任意节点的值总是不大于(不小于)其子节点的值;
堆总是一棵完全树;
将任意节点不大于其子节点的堆叫做最小堆或小根堆,而将任意节点不小于其子节点的堆叫做最大堆或大根堆。二叉堆一般都通过"数组"来实现。数组实现的二叉堆,父节点和子节点的位置存在一定的关系。假设"第一个元素"在数组中的索引为 0 的话,则父节点和子节点的位置关系如下:
索引为i的左孩子的索引是 (2*i+1);
索引为i的左孩子的索引是 (2*i+2);
最大堆和最小堆示意图如下:
2.堆排序过程
堆排序是选择排序的一种,主要包括建堆和调整堆两个过程。首先是根据序列元素构建大顶堆。此时,整个序列的最大值就是堆顶的根节点。然后将根节点最后一个节点进行交换,再将前面剩下的n-1个节点继续进行堆调整的过程,然后再将根节点取出,这样循环一直到所有节点都取出。堆排序过程的时间复杂度是O(nlgn),也是不稳定的排序算法。
3.程序实现
1#include <iostream>
2#include <ctime>
3#include <vector>
4
5using namespace std;
6
7//输出函数
8template <class T>
9void printArr(T *arr, int length)
10{
11 for (int i = 0; i < length; ++i)
12 {
13 cout << arr[i] << " ";
14 }
15 cout << endl;
16}
17
18
19//交换函数
20template <class T>
21void swap(T *a, T *b)
22{
23 T temp;
24 temp = *a;
25 *a = *b;
26 *b = temp;
27
28}
29
30//建立最大堆函数
31void adjust(int arr[], int length, int index)
32{
33 int left = 2 * index + 1;
34 int right = 2 * index + 2;
35 int maxIdx = index;
36
37 if (left < length&&arr[left] > arr[maxIdx])
38 {
39 maxIdx = left;
40 }
41 if (right < length&&arr[right] > arr[maxIdx])
42 {
43 maxIdx = right;
44 }
45
46 if (maxIdx != index)// 如果maxIdx的值有更新
47 {
48 swap(arr[maxIdx], arr[index]);
49 adjust(arr, length, maxIdx);// 递归调整其他不满足堆性质的部分
50 }
51}
52
53//堆排序
54void HeapSort(int *arr, int length)
55{
56 /*
57 * 从最后一个非叶结点开始.对每一个非叶结点进行最大堆调整
58 */
59 for (int i = length / 2 - 1; i >= 0; i--)
60 {
61 adjust(arr, length, i);
62 }
63
64 for (int j = length - 1; j >= 0; j--)
65 {
66 swap(arr[j], arr[0]);// 将当前最大的元素放置到数组末尾
67 cout << "第" << j << "次排序结果:" << endl;
68 printArr<int>(arr, 10);
69 adjust(arr, j, 0); // 将未完成排序的部分继续进行堆排序
70 }
71}
72
73int main()
74{
75 int a[] = { 101, 2, 32, 43, 5, 3, 90, 8, 7, 100 };
76
77 cout << "堆排序前:" << endl;
78 printArr<int>(a, 10);
79
80 clock_t ibegin, iend;
81 ibegin = clock();
82 HeapSort(a, 10);
83 iend = clock();
84 cout << "用时" << iend - ibegin << "毫秒" << endl;
85
86 cout << "堆排序后:" << endl;
87 printArr<int>(a, 10);
88
89 system("pause");
90 return 0;
91}
4.运行结果
可以看到,每运行一次,便将最大的元素交换到序列末尾,n-1次后便可排序完成。
参考:https://blog.csdn.net/lzuacm/article/details/52853194,点击“阅读原文”阅读。
以上是关于堆排序学习笔记的主要内容,如果未能解决你的问题,请参考以下文章