分析
1.首先整个排序过程分为两部分:第一,是将所给数据变成最大堆的形式。第二,交换数据。变成最大堆后,
数组第一个元素总是最大的,然后将st[0],st[10]交换,交换后此时再将st[0]~st[9]变成最大堆,然后再
交换数据,以此类推。
2.堆结构,当前节点的左子节点下标是2*i+1,右子节点下标为2*i+2;节点的父节点是i/2-1;并且一般来说
堆都是完全二叉树
3.堆排序的时间复杂度是O(N*lgN)。假设被排序的数列中有N个数。
遍历一趟的时间复杂度是O(N),需要遍历多少次呢?堆排序是采用的二叉堆进行排序的,二叉堆就是一棵
二叉树,它需要遍历的次数就是二叉树的深度,而根据完全二叉树的定义,它的深度至少是lg(N+1)。
最多是多少呢?由于二叉堆是完全二叉树,因此,它的深度最多也不会超过lg(2N)。因此,遍历一趟的时间
复杂度是O(N),而遍历次数介于lg(N+1)和lg(2N)之间;因此得出它的时间复杂度是O(N*lgN)
附注:
1.最大堆通常被用来进行"升序"排序,而最小堆通常被用来进行"降序"排序
2
#include<iostream>
#include<stdlib.h>
using namespace std;
class MyClass
{
public:
void maxHeapSort(int st[],int start,int end){
int current = start;
int left = current * 2 + 1;
int tmp = st[current];
for (; left <= end; current = left, left = left * 2 + 1){
//选取左右节点中较大的U一个值和当前节点比较,此处left < end而不是<=,因为++可能越界
if (left < end&&st[left] < st[left + 1]){
++left;
}
//如果当前节点大,则结束,否则将大的和当前节点交换位置,接着对比当前节点
if (tmp >= st[left]){
break;
}
else{
st[current] = st[left];
st[left] = tmp;
}
}
return;
}
void heapSortAscend(int st[], int len){
//从开始到数组中间遍历,使其变为最大堆
for (int i = (len - 1) / 2; i >= 0; --i){
maxHeapSort(st, i, len - 1);
}
//交换数据
for (int i = len-1; i > 0; --i){
int tmp = st[0];
st[0] = st[i];
st[i] = tmp;
maxHeapSort(st, 0, i-1);
}
}
};
void main()
{
MyClass bb;
int i;
int a[] = { 20, 30, 90, 40, 70, 110, 60, 10, 100, 50, 80 };
int ilen = (sizeof(a)) / (sizeof(a[0]));
cout << "before sort:";
for (i = 0; i<ilen; i++)
cout << a[i] << " ";
cout << endl;
bb.heapSortAscend(a, ilen); // 升序排列
//heapSortDesc(a, ilen); // 降序排列
cout << "after sort:";
for (i = 0; i<ilen; i++)
cout << a[i] << " ";
cout << endl;
system("pause");
return;
}