HeapSort
堆排序的原理比较简单,首先明白优先队列的二叉堆,还有它的插入和删除操作就可以了,不懂的话,请看我之前的一篇文章:优先队列的二叉堆实现。
排序操作分两步:
第一步构造堆
这个不能和优先队列的插入操作一样,虽然看起来时间复杂度差不多,每次都进行插入操作是O(1)和O(logN)之间,所以总运行时间是平均复杂度是O(N)而不是O(NlogN)最坏时间复杂度,我们的做法是先把数列构造成一棵树,然后依次下滤。时间复杂度也是O(N),最多用到2N次比较。
第二部删除堆顶元素
一共要删除N次,每次删除进行2logi次比较,因为堆顶元素一直是最大值,或者是最小值(小顶堆)。把删掉的元素找个地方存起来~ 这样子就是有序的数列了。放到哪里呢= =。一种是开个O(N)的空间,舍弃这种方法。一种是把删掉的元素放到 数列尾部啊,因为删掉一个元素,原数列尾部就空出一个位置了,这样子不断存放,就是有序的了。至于大顶堆还是小顶堆看你要从大到小还是从小到大了。
代码实现
//
// main.cpp
// heapSort
//
// Created by Alps on 14-8-2.
// Copyright (c) 2014年 chen. All rights reserved.
//
#include <iostream>
#define ElementType int
#define MinItem -1
using namespace std;
void Swap(int &a, int &b){
a = a+b;
b = a-b;
a = a-b;
}
void BuildHeap(ElementType *A, int length){
for (int i = length/2; i > 0; i--) {
for (int j = i; j*2 <= length;) {
if (j *2 != length) {
if (A[j*2] > A[j*2+1] && A[j*2] > A[j]) {
Swap(A[j*2], A[j]);
j *= 2;
}else{
if (A[j*2+1] > A[j*2] && A[j*2+1] > A[j]) {
Swap(A[j*2+1], A[j]);
j = j*2+1;
}else{
break;
}
}
}else{
if (A[j*2] > A[j]) {
Swap(A[j*2], A[j]);
j *= 2;
}else{
break;
}
}
}
}
}
ElementType DeleteMax(ElementType *A, int length){
int MaxElement, LastElement;
int i,temp;
MaxElement = A[1];
LastElement = A[length];
for (i = 1; i*2 < length; i = temp) {
temp = i*2;
if (A[temp] > A[temp+1]) {
A[i] = A[temp];
}else{
A[i] = A[temp+1];
temp++;
}
if (LastElement > A[i]) {
A[i] = LastElement;
break;
}
}
A[i] = LastElement;
return MaxElement;
}
void HeapSort(ElementType *A, int length){
BuildHeap(A, length);
for (int i = 0; i < length; i++) {
A[length-i] = DeleteMax(A, length-i);
}
}
int main(int argc, const char * argv[])
{
ElementType A[]={MinItem,53,26,41,59,97,31,58};
int length = sizeof(A)/sizeof(ElementType) -1;
HeapSort(A, length);
// BuildHeap(A, length);
for (int i = 1; i <= length; i++) {
printf("%d ",A[i]);
}
printf("\n");
// for (int i = 0; i < length; i++) {
// A[length-i] = DeleteMax(A, length-i);
// printf("%d ",A[length-i]);
// }
printf("\n");
return 0;
}