堆排序
2015-08-02 15:44
218 查看
#include "util.h" //堆排序 // //二叉堆的特性就是每个节点的数值都比子节点的数据大,所以二叉堆最顶端的数值是最大的 //这里采用数组来存储二叉堆,为了方便计算父节点与叶子节点的索引,数据索引0没有使用,数 //组有效索引从1开始, 给定任意节点索引X,该节点的父节点索引为X/2,该节点的左叶子节点索 //引为 X*2, 右叶子节点索引为X*2+1 // // 1 // --------- // | | // 2 3 // ----- ----- // | | | | // 4 5 6 7 // // array |0|1|2|3|4|5|6|7| // //堆排序的核心思想就是基于二叉堆的数据结构进行排序算法实现 //1 首先将数据构造成二叉堆 //2 之后将二叉堆顶端最大值与数组末尾的值进行交换,缩小数组长度,使得最大值停留在 //当前数组的末尾. //3 当之前数据末尾数据移到二叉堆顶端后,二叉堆可能失去了原来的性质,此时需要从二 //叉堆顶部重新进行下沉处理,使得数组剩余数据再次构成二叉堆特性. //4 重复步骤2~3,省得从二叉堆中依次取出最大值,并倒序放置到数组中,最终形成降序排序 void sort(int iArray[], int count) { int k = 0; //将原数组数据构造成二叉堆,从数组最后索引开始进行下沉处理来构造二叉堆, //之后数组索引不断进行递减,使得最终从顶端索引1进行下沉处理来完成最终的二叉 //堆构造 //k = count / 2,这里是为了跳过叶子节点,如上图示例,叶子节点4\5\6\7下面已经没 //有子节点了,所以不需要进行下沉处理. //k >= 1,是因为当前采用数组方式存储二叉堆,为了计算父子索引方便,数组索引0不 //使用,直接从索引1开始. for ( k = count / 2; k >= 1; k-- ) { sink(iArray, count, k); } //开始进行堆排序处理 //count > 2,是因为当前不使用数组0索引,所以如果二叉堆中至少需要2个数据进行 //排序处理,则至少数组长度应该大于2 while ( count > 2 ) { count--; //将二叉堆顶部索引1的数值与当前数组末尾的值进行交换 exch(iArray, count, 1); //数组末尾的值交换到二叉堆顶端后,从顶端开始进行下沉处理,保证二叉堆的 //特性有效 sink(iArray, count, 1); } } //二叉堆的特性就是每个节点的数值都大于子节点的数值 //当新加或删除节点后,就要重新进行处理,来保证二叉堆的特性不变,这 //里的算法是属于下降方式处理,其思想如下: //1 首先判断当前节点下还有子节点 //2 从左叶子节点及右叶子节点中选择一个最大的值 //3 使用该值与当前节点进行比较,因为当前节点是叶子节点的父节点,所以 // 按二叉堆的特性,该节点应该不能小于叶子节点,如果该节点大于叶子节 // 点,则满足二叉堆特性,退出处理,否则需要将此节点与最大的叶子节点 // 值进行交换 //4 如果在第3步中发生了交换,则当前新值已经移到了最大叶子节点的位置 // ,此时需要继续检查当前位置的值是否大于当前索引下的叶子节点,处理 // 方法同第1~3步相同 void sink(int iArray[], int count, int k) { //至少存在左叶子节点 while ( 2 * k < count ) { //左叶子节点索引值 int leaf = 2 * k; //如果存在右叶子节点, 则从两个叶子节点中挑出一个 //最大值的叶子索引 if ( leaf + 1 < count ) { if ( less(iArray[leaf], iArray[leaf + 1]) ) { leaf++; } } //如果当前父节点大于等于最大的叶子节点,则已经满足二叉堆 //特性,退出处理 if ( !less(iArray[k], iArray[leaf]) ) { break; } //当前父节点小于叶子节点,则进行父节点和叶子节点的数据交换 exch(iArray, k, leaf); //当前待处理的数据已经移到了最大的叶子节点位置,此时需要将 //当前索引更改为替换后的叶子索引位置,用于继续当前数据 //与下一叶子值的比较处理 k = leaf; } } int main() { int iArray[] = {-1, 2, 5, 6, 1, 8, 3, 9, 4, 3, 1, 7}; sort(iArray, 12); arrayShow(iArray, 12); return 0; }
#include <stdio.h> #include "util.h" void arrayShow(int iArray[], int size) { int i = 0; for ( i = 0; i < size; i++ ) { printf("%d ", iArray[i]); } printf("\r\n"); } int less(int a, int b) { if ( a < b ) return 1; return 0; } int compare(int a, int b) { if ( a > b ) return 1; if ( a < b ) return -1; return 0; } void exch(int iArray[], int indexA, int indexB) { int tmp = iArray[indexA]; iArray[indexA] = iArray[indexB]; iArray[indexB] = tmp; }
相关文章推荐
- 解决cgal中的surface_mesh_deformation,代码copy到别处报错
- Jquery
- Leetcode Valid Anagram
- intel实习第二个月总结
- RSA算法原理(二)
- 极客五控
- 多线程下载服务端图片资源
- Public Sale HDOJ
- poj 3481 Treap
- 跨域问题
- RSA算法原理(一)
- java单例模式
- 转载:解题笔记
- php中的$_SERVER从哪来
- leetcode 61: Rotate List
- NSString基本用法
- [poj 2960]S-Nim
- Font: a C++ class
- 用栈实现队列-用队列实现栈
- android record