堆排序
2017-09-24 19:26
316 查看
概述
堆排序是利用堆的特性——堆顶元素一定是这个堆的最大值或者最小值,来使选择排序中每趟选择最值变得更加高效的思路。对于堆的相关内容移步我之前的博客:堆算法思想
这里我们默认从小到大排序。思路一:首先把通过数组构造一个最小堆,之后依次执行最小堆的删除操作直至最小堆为空则能得到一个从小到大的序列。对于时间复杂度一定是O(nlogn)。然而这个算法却带来了O(n)的空间复杂度。那么这显然是不划算的。故这就有了思路二。
思路二:首先通过n个数的数组构造一个最大堆,这是执行如下操作:把堆中最后一个元素(下标为n-1)与第一个元素(下标为0)互换位置,之后把0至n-2的数组调整为最大对,重复上述操作直至只剩一个元素。这样就避免了O(n)的空间复杂度。
全部代码
#include <iostream> #include <cstdlib> #include <ctime> using namespace std; const int MAX = 65535; class HeapSort{ private: int* data; int size; public: //构造函数 HeapSort(int* data,int len){ this->size = 0; this->data = new int[len+1]; this->data[0] = MAX; for(int i = 0 ; i < len ; i++){ this->data[++this->size] = data[i]; } this->BuildHeap(); } //把下标为n的子树调整为最大堆 void Predown(int start ,int end){ int parent ,child; int x = this->data[start]; for(parent = start ; 2*parent < end ; parent = child){ child = parent*2; //child+1不是最后一个元素,且右孩子大于左孩子 if(child+1 != this->size && this->data[child+1] > this->data[child]){ child++; } if(x >= this->data[child]){ break; }else{ this->data[parent] = this->data[child]; } } this->data[parent] = x; } //建堆函数 void BuildHeap(){ for(int i = this->size/2 ; i >= 0 ; i--){ this->Predown(i,this->size); } } void Swap(int* a,int* b){ *a = *a + *b; *b = *a - *b; *a = *a - *b; } //堆排序 void Heap_Sort(){ for(int i = this->size ; i > 0 ; i--){ //交换最后一个与第0个元素 this->Swap(&this->data[0],&this->data[i]); //把0到i-1个数调整为最大堆 this->Predown(0,i-1); } } void Print(int start , int end){ for(int i = start ; i <= end; i++){ cout<<this->data[i]<<" "; } cout<<endl; } }; int main() { cout<<"请输入数组长度:"<<endl; int size,*data; cin>>size; data = new int[size]; srand(time(0)); cout<<"随机初始化"<<size<<"个数"<<endl; for(int i = 0 ; i < size ; i++){ data[i] = rand()%100+1; } HeapSort sort(data,size); cout<<"堆排序前:"<<endl; sort.Print(1,size); cout<<"堆排序后:"<<endl; sort.Heap_Sort(); sort.Print(0,size-1); return 0; }
截图: