堆排序: 与归并排序一样,但不同于插入排序的的是,堆排序时间复杂度为Θ(nlgn)。与插入排序一样但不同于归并排序的是堆排序同样具有空间原址性,任何时候都只需要常数个额外的元素空间存储临时数据。所以堆排序是集合了归并排序和插入排序优点的排序算法。
(二叉)堆: 在学习堆排序之前需要了解下堆。此处的堆不是“垃圾收集存储机制”。而是一种堆数据结构。
它是一个数组,可以近似的堪称完全二叉树,树上每个节点对应数组中的一个元素。
二叉堆又可以分为两种形式:最大堆和最小堆。
最大堆(大顶堆)中结点的都要满足:
A[Parent(i)]>=A[i]
最小堆(小顶堆)中结点的都要满足:
A[Parent(i)]<=A[i]
排序思想: 根据大顶堆的性值,可以知道最大堆的根节点绝对是所有结点中数组最大的。所以我们把顶节点取出存进尾处,然后重新去除存进尾处的节点剩下的重新操作成最大堆。一直递归上述操作,直到堆中只剩两个节点,此时数组既是已经排好序的。
时间复杂度: Θ(nlgn)
与快排的比较: 时间复杂度相同,但大多数情况下堆排序时间复杂数的系数更大,并且堆排序对数据的存取操作更频繁,所以一般情况下,快排优于堆排序.但是用作一个高效的优先队列,堆排序一直很受欢迎。
c++:
// test_1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include<vector>
using namespace std;
#pragma region 堆排序
/// <summary>
/// 维护最大堆的性值
/// </summary>
/// <param name="list"></param>
/// <param name="i"></param>
void Max_Heapley(vector<int>& list,int i,int size)
{
int l =2 * i; //在最大堆中对于下标i的元素的左子节点的下边为2i
int r =2 * i + 1; //在最大堆中对于下标i的元素的右子节点的下边为2i+1
//找出在下标i的元素以及左右子节点元素中的最大值,如果下标i的元素最大,则不处理,否则交换i下标以及最大值下标的数据,然后递归对应下标此方法
int maxIndex = i;
if (l<= size && list[l-1]>list[i-1])
maxIndex = l;
if (r<= size && list[r -1]>list[maxIndex-1])
maxIndex = r;
if (maxIndex != i)
{
int temp = list[i-1];
list[i-1] = list[maxIndex-1];
list[maxIndex-1] = temp;
Max_Heapley(list, maxIndex,size);
}
}
/// <summary>
/// 建立最大堆
/// </summary>
/// <param name="list"></param>
/// <param name="size"></param>
void Build_Max_Heap(vector<int>& list)
{
//建立最大堆需要从下往上一次对每一个非子节点的节点进行维护最大堆性值的处理
int maxParent = list.size() / 2; //在堆中子节点的下标是从(n/2)+1开始到n的,而父节点的下标则是从0-2n
for (int i = maxParent ; i > 0; i--)
{
Max_Heapley(list, i, list.size());
}
}
/// <summary>
/// 堆排序
/// </summary>
/// <param name="list"></param>
void HeapSort(vector<int>& list)
{
//从数组最大长度开始循环
// 1.建立最大堆
// 2.交换当前首尾
// 3.最大长度减一
// 4.维护最大堆的性值
//循环234
Build_Max_Heap(list);
for (int i = list.size(); i > 1; i--)
{
int temp = list[i-1];
list[i-1] = list[0];
list[0] = temp;
Max_Heapley(list, 1, i-1);
}
}
#pragma endregion
int main()
{
int index = 1;
vector<int> intput_array;
int num;
cout << "输入一串数组:";
while (true)
{
cin >> num;
intput_array.push_back(num);
if (cin.get() == '\n')
break;
}
int length = intput_array.size();
cout << "排序结果为:" << endl;
#pragma region 堆排序
HeapSort(intput_array);
for (int i = 0; i < length; i++)
{
printf("%d ", intput_array[i]);
}
#pragma endregion
return 0;
}