排序3-堆排序
2015-06-29 10:21
190 查看
基本思想
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以看作是对选择排序的改进。通常堆是通过一维数组来实现的。在起始数组为0的情形中:
父节点i的左子节点在位置(2*i+1);
父节点i的右子节点在位置(2*i+2);
子节点i的父节点在位置floor((i-1)/2);
在堆的数据结构中,堆中的最大值总是位于根节点。堆中定义以下几种操作:
最大堆调整(Max_Heapify):将堆的末端子节点作调整,使得子节点永远小于父节点
创建最大堆(Build_Max_Heap):将堆所有数据重新排序
堆排序(HeapSort):移除位在第一个数据的根节点,并做最大堆调整的递归运算
时间复杂度分析
建立N个元素的二叉堆需要花费O(n)O(n),在正式排序时,第ii次取堆顶的数据事,重建堆需要用O(logi)O(\log{i}),总共取n−1n-1次堆顶,所以重建堆需要花费O(nlogn)O(n\log{n})。因此,堆排序的时间复杂度为O(nlogn)O(n\log{n}),又因为堆排序对原数据的初始状态不敏感,所以最好、最坏和平均时间复杂度均为O(nlogn)O(n\log{n}); 可以原地进行,空间复杂度O(1)O(1)。代码实现
最大堆调整有递归和非递归实现方式。[code]void Heap_adjust(int arr[], int index, int len) { while(true) { int iMax = index; int iLeft = 2 * index + 1; int iRight = 2 * index + 2; if(iLeft < len && arr[index] < arr[iLeft]) iMax = iLeft; if(iRight < len && arr[iMax] < arr[iRight]) iMax = iRight; if(iMax != index) { swap(arr[index], arr[iMax]); index = iMax; } else break; } } void Heap_adjust2(int arr[], int index, int len) { int iMax = index; int iLeft = 2 * index + 1; int iRight = 2 * index + 2; if(iLeft < len && arr[index] < arr[iLeft]) iMax = iLeft; if(iRight < len && arr[iMax] < arr[iRight]) iMax = iRight; if(iMax != index) { swap(arr[index], arr[iMax]); Heap_adjust2(arr, iMax, len); } } void Build_maxheap(int arr[], int len) { for(int i = len / 2; i >= 0; i --) { Heap_adjust(arr, i , len); } } void Heap_Sort(int arr[], int len) { Build_maxheap(arr, len); for(int i = len - 1; i > 0; i --) { swap(arr[0], arr[i]); Heap_adjust(arr, 0, i); } }
测试代码
[code]#include <iostream> #include <cstring> #include <ctime> #include <cmath> using namespace std; #define ArraySize 100000 void swap(int *x, int *y) { int temp; temp = *x; *x = *y; *y = temp; } void Bubble_sort(int arr[], int len) { for(int i = 0; i < len; i ++) { for(int j = i + 1; j < len; j ++) if(arr[i] > arr[j]) swap(arr[i], arr[j]); } } void Bubble_sort1(int arr[], int len) { for(int i = 0; i < len; i ++) { for(int j = len - 1; j >= i; j --) { if(arr[i] > arr[j]) swap(arr[i], arr[j]); } } } void Bubble_sort2(int arr[], int len) { bool flag = true; while(flag) { flag = false; for(int i = 0; i < len; i ++) for(int j = len - 1; j >= i; j --) if(arr[i] > arr[j]) swap(arr[i], arr[j]); } } void Slect_sort(int arr[], int len) { for(int i = 0; i < len; i ++) { int min_index = i ; for(int j = i + 1; j < len; j ++) { if(arr[min_index] > arr[j]) min_index = j; } if(i != min_index) swap(arr[i],arr[min_index]); } } void Insert_sort(int arr[], int len) { for(int i= 1; i < len; i ++) { int key = arr[i]; int j = i; while(j && arr[j - 1] > key) { arr[j] = arr[j - 1]; j --; } arr[j] = key; } } void Shell_sort(int arr[], int len) { int increment = len / 2; while(increment) { for(int i = increment; i < len; i ++) { int key = arr[i]; /*int j ; for(j = i; j >= increment; j -= increment) { if(arr[j-increment] > key ) arr[j] = arr[j-increment]; else break; }*/ int j = i; while(j >= increment && arr[j-increment] > key) { arr[j] = arr[j-increment]; j -= increment; } arr[j] = key; } increment /= 2; } } void Shell_sort1(int arr[], int len) { int increment = 0; for(increment = len/2; increment > 0; increment /=2) { for(int i = increment; i < len; i++) { int key = arr[i]; int j = 0; for(j = i; j >= increment; j -=increment) { if(arr[j-increment] > key) arr[j] = arr[j-increment]; else break; } arr[j] = key; } } } void Shell_sort2(int arr[], int len) { int index = log( 2*len + 1) / log(3.0); //cout << index << endl; int increment = ( pow(3.0, index) - 1 ) / 2; //cout << increment << endl; while(increment) { for(int i = increment; i < len; i ++) { int key = arr[i]; /*int j ; for(j = i; j >= increment; j -= increment) { if(arr[j-increment] > key ) arr[j] = arr[j-increment]; else break; }*/ int j = i; while(j >= increment && arr[j-increment] > key) { arr[j] = arr[j-increment]; j -= increment; } arr[j] = key; } index -= 1; increment = ( pow(3.0, index) - 1 ) / 2; } } void Heap_adjust(int arr[], int index, int len) { while(true) { int iMax = index; int iLeft = 2 * index + 1; int iRight = 2 * index + 2; if(iLeft < len && arr[index] < arr[iLeft]) iMax = iLeft; if(iRight < len && arr[index] < arr[iRight]) iMax = iRight; if(iMax != index) { swap(arr[index], arr[iMax]); index = iMax; } else break; } } void Heap_adjust2(int arr[], int index, int len) { int iMax = index; int iLeft = 2 * index + 1; int iRight = 2 * index + 2; if(iLeft < len && arr[index] < arr[iLeft]) iMax = iLeft; if(iRight < len && arr[index] < arr[iRight]) iMax = iRight; if(iMax != index) { swap(arr[index], arr[iMax]); Heap_adjust2(arr, iMax, len); } } void Build_maxheap(int arr[], int len) { for(int i = len / 2; i >= 0; i --) { Heap_adjust(arr, i , len); } } void Heap_Sort(int arr[], int len) { Build_maxheap(arr, len); for(int i = len - 1; i > 0; i --) { swap(arr[0], arr[i]); Heap_adjust(arr, 0, i); } } void Print_array(int arr[], int len) { for(int i = 0; i < len; i++) { cout << arr[i] << " "; } cout << endl; } int main(int argc, char const *argv[]) { /* code */ int Array[ArraySize]; int Array1[ArraySize]; int Array2[ArraySize]; time_t begin , end; srand(time(NULL)); for(int i = 0; i < ArraySize; i ++) { Array[i] = rand()%ArraySize; //cout << Array[i] << " "; } memcpy(Array1, Array, ArraySize * sizeof(Array1[0])); memcpy(Array2, Array, ArraySize * sizeof(Array2[0])); // Print_array(Array, ArraySize); /* begin = clock(); Bubble_sort2(Array, ArraySize); end = clock(); cout << "Bubble_sort runtime: " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl; begin = clock(); Slect_sort(Array1, ArraySize); end = clock(); cout << "Slect_sort runtime: " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl; begin = clock(); Insert_sort(Array2, ArraySize); end = clock(); cout << "Insert_sort runtime: " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl;*/ begin = clock(); Shell_sort1(Array1, ArraySize); end = clock(); cout << "Shell_sort1 runtime: " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl; begin = clock(); Shell_sort2(Array2, ArraySize); end = clock(); cout << "Shell_sort2 runtime: " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl; begin = clock(); Heap_Sort(Array, ArraySize); end = clock(); cout << "Heap_Sort runtime: " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl; //Print_array(Array2, ArraySize); return 0; }
运行结果如下:
[code]Shell_sort1 runtime: 0.038s Shell_sort2 runtime: 0.021s Heap_Sort runtime: 0.026s
参考资料
堆排序 - 维基百科,自由的百科全书https://zh.wikipedia.org/wiki/%E5%A0%86%E6%8E%92%E5%BA%8F
常见排序算法 - 堆排序 (Heap Sort) | bubkoo
http://bubkoo.com/2014/01/14/sort-algorithm/heap-sort/
相关文章推荐
- poj 3160 Father Christmas flymouse (SCC缩点+SPFA求最长路)
- 新锐房地产销售管理系统(部分流程)技术解析(十) 销售管理_销售优惠设置
- MySQL分表
- 免安装sql使用
- [转]IO - 同步,异步,阻塞,非阻塞
- Java基础:字符串
- JavaScript实现把数字转换成中文
- win10预览版10151简体中文iso镜像下载地址(64位)
- java如何实现系统监控、系统信息收集、sigar开源API的学习
- eclipse svn 修改了类名之后提交
- inux读取ISO文件或是光驱的方法--挂载
- Web前端从入门到精通-3 html简介
- oracle数据库敏感操作前创建还原点
- JPA中的@MappedSuperclass
- 需求图形化分析模型
- 在Linux系统中将Redmine和SVN整合入Nginx的方法
- ORA-03113数据库无法正常启动
- 原码, 反码, 补码 详解
- MFC的CString使用
- Linux 常用命令 总结