排序算法_堆排序
一、什么是堆
堆可以视为一棵完全的二叉树,完全二叉树的一个“优秀”的性质是,除了最底层之外,每一层都是满的,这使得堆可以利用数组来表示,每一个结点对应数组中的一个元素.
数组与堆之间的关系:
- 父节点i的左子节点在位置 (2*i+1);
- 父节点i的右子节点在位置 (2*i+2);
- 子节点i的父节点在位置 [i/2];
二、分类
最大堆:子结点的键值或索引总是小于它的父节点。
最小堆:子结点的键值或索引总是大于它的父节点。
三、算法描述
- 堆排序就是把堆顶的最大数取出。
- 将剩余的堆继续调整为最大堆。
- 再次将堆顶的最大数取出,直到剩余数只有一个时结束。
四、性能描述
数据结构 :数组
最差时间复杂度 :O(nlogn)
最优时间复杂度 :O(nlogn)
平均时间复杂度 :O(nlogn)
最差空间复杂度 :О(n)
五、图示
六、C++语言实现代码
View Code
1 #include <iostream> 2 using namespace std; 3 /* 4 #堆排序#% 5 #数组实现#% 6 */ 7 //#筛选算法#% 8 void sift(int d[], int ind, int len) 9 { 10 //#置i为要筛选的节点#% 11 int i = ind; 12 13 //#c中保存i节点的左孩子#% 14 int c = i * 2 + 1; //#+1的目的就是为了解决节点从0开始而他的左孩子一直为0的问题#% 15 16 while(c < len)//#未筛选到叶子节点#% 17 { 18 //#如果要筛选的节点既有左孩子又有右孩子并且左孩子值小于右孩子#% 19 //#从二者中选出较大的并记录#% 20 if(c + 1 < len && d[c] < d[c + 1]) 21 c++; 22 //#如果要筛选的节点中的值大于左右孩子的较大者则退出#% 23 if(d[i] > d[c]) break; 24 else 25 { 26 //#交换#% 27 int t = d[c]; 28 d[c] = d[i]; 29 d[i] = t; 30 // 31 //#重置要筛选的节点和要筛选的左孩子#% 32 i = c; 33 c = 2 * i + 1; 34 } 35 } 36 37 return; 38 } 39 40 void heap_sort(int d[], int n) 41 { 42 //#初始化建堆, i从最后一个非叶子节点开始#% 43 for(int i = n / 2; i >= 0; i--) 44 sift(d, i, n); 45 46 for(int j = 0; j < n; j++) 47 { 48 //#交换#% 49 int t = d[0]; 50 d[0] = d[n - j - 1]; 51 d[n - j - 1] = t; 52 53 //#筛选编号为0 #% 54 sift(d, 0, n - j - 1); 55 56 } 57 } 58 59 int main() 60 { 61 int a[] = {3, 5, 3, 6, 4, 7, 5, 7, 4}; //#QQ#% 62 63 heap_sort(a, sizeof(a) / sizeof(*a)); 64 65 for(int i = 0; i < sizeof(a) / sizeof(*a); i++) 66 { 67 cout << a[i] << ' '; 68 } 69 cout << endl; 70 return 0; 71 }
参考文档:
1. 堆排序_百度百科
http://baike.baidu.com/view/157305.htm
2. 堆排序原理图解
http://blog.csdn.net/jokers_i/article/details/8180533
3. 堆積排序