算法-堆排序
什么是堆?
http://www.cnblogs.com/mengdd/archive/2012/11/30/2796845.html
n个元素的序列{k1,k2,…,kn}当且仅当满足下列关系之一时,称之为堆。
情形1:ki <= k2i 且ki <= k2i+1 (最小化堆或小顶堆)
情形2:ki >= k2i 且ki >= k2i+1 (最大化堆或大顶堆)
若将和此序列对应的一维数组(即以一维数组作此序列的存储结构)看成是一个完全二叉树,则堆的含义表明,完全二叉树中所有非终端结点的值均不大于(或不小于)其左、右孩子结点的值。
由此,若序列{k1,k2,…,kn}是堆,则堆顶元素(或完全二叉树的根)必为序列中n个元素的最小值(或最大值)。
什么是堆排序?
http://www.cnblogs.com/mengdd/archive/2012/11/30/2796845.html
若在输出堆顶的最小值之后,使得剩余n-1个元素的序列重又建成一个堆,则得到n个元素的次小值。如此反复执行,便能得到一个有序序列,这个过程称之为堆排序。
堆的存储
一般用数组来表示堆,若根结点存在序号0处, i结点的父结点下标就为(i-1)/2。i结点的左右子结点下标分别为2*i+1和2*i+2。
二叉树左右儿子序关系证明
堆存储中 节点i 和 儿子的关系 为什么是 2i?
代码实现
https://github.com/fanqingsong/code-snippet/blob/master/C/heapSort/heapSort.c
其中CreateHeap为创建堆过程, 其实现了对最大元素选择到堆顶的操作, 此步骤保证, 每一个非叶子节点 都是一个 小的 子堆, 保证了部分有序。 见代码中的注释。
每一步的调整, 保证了从对树根到树叶的一次遍历。
#include <stdio.h> #include <string.h> #include <assert.h> #include <malloc.h> #include <stdarg.h> #include <ctype.h> typedef enum returnType { FAIL = 0, SUCCESS, } E_RETURN_TYPE; typedef enum boolType { FALSE = 0, TRUE, } E_BOOL_TYPE; void printArr(int arr[], int size) { int i = 0; printf("arr element is \n"); for (i=0; i<size; i++) { printf("%d\n", arr[i]); } } void SwapValue(int arr[], int index1, int index2) { int tmp = arr[index1]; arr[index1] = arr[index2]; arr[index2] = tmp; } // select the extreme value to 0 element, // 0~i-1 is non order list, and 0 element break the heap void HeapAdjust(int arr[], int breakIndex, int lastIndex) { int breakVal = 0; int leftChildIdx = 0; int leftVal = 0; int rightVal = 0; // condiction is predicting that the left child of breaking node is existing while ( (leftChildIdx=2*breakIndex+1) <= lastIndex ) { leftVal = arr[leftChildIdx]; rightVal = arr[leftChildIdx+1]; breakVal = arr[breakIndex]; // right child is beyond range, set its value to minmun value if (leftChildIdx+1 > lastIndex) { rightVal = 0X1 << (sizeof(int)*8 -1); } // find the max, swap with break node if ( leftVal > rightVal ) { if ( breakVal < leftVal ) { SwapValue(arr, breakIndex, leftChildIdx); breakIndex = leftChildIdx; } else { // break node is max, no more action need to be done break; } } else { if ( breakVal < rightVal ) { SwapValue(arr, breakIndex, leftChildIdx+1); breakIndex = leftChildIdx+1; } else { // break node is max, no more action need to be done break; } } } } // translate arr to heap with max top(0 index element is max) E_RETURN_TYPE CreateHeap(int arr[], int lastIdx) { int i = 0; int lastNonLeafIdx = lastIdx/2; // for creating a heap, must adjust from last non leaf node to 0 index node /* 0 ----- 0 height 1 2 ----- 1 height ......... x y .. z ----- n height x1 x2 ----- n+1 height note: as above, lastNonLeafIdx is x, y..z node has no child first, for handling n height node(x), we get the max of x, x1, x2, save as x second, for handling n-1 height nodes( .... ), we get the max of the tree with every node as root ... until reach 0 height, we get the max of tree with 0 as root, ie we get max top heap */ for ( i=lastNonLeafIdx; i>=0; i-- ) { HeapAdjust(arr, i, lastIdx); printf("--------- enter CreateHeap HeapAdjust %d\n", i); printArr(arr, lastIdx+1); } } E_RETURN_TYPE HeapSort(int arr[], int size) { int i = 0; CreateHeap(arr, size-1); printf("--------- after CreateHeap"); printArr(arr, size); /* execute size-1 times loop */ for ( i=size-1; i>0; i-- ) { // now arr[i] is the extreme value from 0 ~ i SwapValue(arr, 0, i); // 0~i-1 is non order list, and 0 element break the heap HeapAdjust(arr, 0, i-1); } } int main(void) { int arr [] = {8, 5, 6, 7}; printf("--------- before heap sort"); printArr(arr, sizeof(arr)/sizeof(int)); HeapSort(arr, sizeof(arr)/sizeof(int)); printf("--------- after heap sort"); printArr(arr, sizeof(arr)/sizeof(int)); } Status API Training Shop Blog About Pricing © 2016 GitHub, Inc. Terms Privacy Security Contact Help
出处:http://www.cnblogs.com/lightsong/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。