堆排序的实现-C语言
2012-07-25 12:08
274 查看
堆
堆是一个完全二叉树的数组对象。树每一层都是满的,最后一层可能除外(从一个节点的左子树开始填)。
给定节点 i ,可以很容易计算父节点和子节点的位置。
Parent(i) =floor(i/2) :i/2再向下取整
LeftChild(i) =2*(i+1)-1 :因为i从0开始,这和c语言的数组从0开始相对应。可以用左移运算代替*,即LeftChild(i)=(i+1)<<1 - 1;
RightChild(i) = 2*(i+1) :RightChild(i) = (i+1)<<1;
堆排序
堆排序的时间复杂度是O(nlgn),是比较有效率的一种。其使用的是最大堆。最大堆的意思是父节点的值>=孩子的值。那么第0个节点必定是该堆的最大值。所以,堆排序的思想就是每次循环把最大值移走,然后从剩下的节点重新建立最大堆。
第一步:建立堆的结构体。
其中arr指针指向的是存放堆数据的数组。
heapMaxIndex是数组最大的序号。如数组定义为a[10],那么heapMaxIndex的值应该为9.
第二步:保持堆的性质。
这一步是堆排序的基础。这里将功能写成一个函数名为void maxHeapify(Heap *hp, unsigned int nodei),这个函数用于让一个数组变成一个符合堆性质的数组。时间复杂度为O(h),h是堆所属二叉树树的高度=lgn(n是节点个数)。
思想是:从一个节点i,和他的孩子leftchild(i),rightChild(i)中找到最大的,然后其索引存放在largest中。如果i是最大的。那么i为根的子树已经是最大堆,程序结束。
否则i的某个子节点有最大元素,那么i的值和largest的值交换。下标为largest的节点在交换后作为父节点,那么他可能又违反堆性质,因此递归调用该函数。
第三步 利用maxHeapify函数创建堆
对于1个个数为n的堆,从上面堆的图中可以分析得到,n/2-1之前的都是父节点。之后的都是叶子节点,我们只需要对父节点进行maxHeapify就可以了。
n/2可以用右移运算n>>1。
第四步:堆排序
设堆的数组为A[0..n-1],调用maxHeapify函数就可以得到最大值,然后将最大值和n-1互换,把堆的大小heapMaxIndex减1,再次调用maxHeapify,又得到最大值,存放在A[0],再和A[n-2]互换,把堆的大小再减一,这样循环下去,知道堆的大小为0。那么我们就得到了由小到大的排好序的数组。
测试堆排序
结果为:-85 -4 0 1 2 12 12 15 17 21 23 25 25 26 32 35 42 45 56 145
堆排序应用:
优先级队列,事件驱动模式响应队列等。
堆是一个完全二叉树的数组对象。树每一层都是满的,最后一层可能除外(从一个节点的左子树开始填)。
给定节点 i ,可以很容易计算父节点和子节点的位置。
Parent(i) =floor(i/2) :i/2再向下取整
LeftChild(i) =2*(i+1)-1 :因为i从0开始,这和c语言的数组从0开始相对应。可以用左移运算代替*,即LeftChild(i)=(i+1)<<1 - 1;
RightChild(i) = 2*(i+1) :RightChild(i) = (i+1)<<1;
堆排序
堆排序的时间复杂度是O(nlgn),是比较有效率的一种。其使用的是最大堆。最大堆的意思是父节点的值>=孩子的值。那么第0个节点必定是该堆的最大值。所以,堆排序的思想就是每次循环把最大值移走,然后从剩下的节点重新建立最大堆。
第一步:建立堆的结构体。
typedef struct heap_t{ int *arr; //point for an array to store heap value. int heapMaxIndex; //heap element max index number int arrLength; //array length of arr }Heap;
其中arr指针指向的是存放堆数据的数组。
heapMaxIndex是数组最大的序号。如数组定义为a[10],那么heapMaxIndex的值应该为9.
第二步:保持堆的性质。
这一步是堆排序的基础。这里将功能写成一个函数名为void maxHeapify(Heap *hp, unsigned int nodei),这个函数用于让一个数组变成一个符合堆性质的数组。时间复杂度为O(h),h是堆所属二叉树树的高度=lgn(n是节点个数)。
思想是:从一个节点i,和他的孩子leftchild(i),rightChild(i)中找到最大的,然后其索引存放在largest中。如果i是最大的。那么i为根的子树已经是最大堆,程序结束。
否则i的某个子节点有最大元素,那么i的值和largest的值交换。下标为largest的节点在交换后作为父节点,那么他可能又违反堆性质,因此递归调用该函数。
void maxHeapify(Heap *hp, unsigned int nodei) { unsigned int l = (nodei+1) << 1 - 1; //left child = 2i-1, -1 ?:arr[0..n-1] unsigned int r = (nodei+1) << 1 ; // right child = 2i unsigned int largest = 0; int heapMaxI = hp->heapMaxIndex; if(l <= heapMaxI && hp->arr[l] > hp->arr[nodei]) largest = l ; else largest = nodei ; if(r <= heapMaxI && hp->arr[r] > hp->arr[largest]) largest = r ; if(largest!=nodei) { //exchange int tmp ; tmp = hp->arr[largest]; hp->arr[largest] = hp->arr[nodei]; hp->arr[nodei] = tmp; maxHeapify(hp,largest); }else{ return ; } }
第三步 利用maxHeapify函数创建堆
对于1个个数为n的堆,从上面堆的图中可以分析得到,n/2-1之前的都是父节点。之后的都是叶子节点,我们只需要对父节点进行maxHeapify就可以了。
n/2可以用右移运算n>>1。
Heap *createHeap(int *arrp, int arrLength,Heap *heap) { int i; heap->arr = arrp; heap->heapMaxIndex = arrLength-1; heap->arrLength = arrLength; //for an heap a[0..n-1]; a[(n/2)..n-1] all are leaves for(i = arrLength>>1-1; i >=0; i--) maxHeapify(heap,i); return heap; }
第四步:堆排序
设堆的数组为A[0..n-1],调用maxHeapify函数就可以得到最大值,然后将最大值和n-1互换,把堆的大小heapMaxIndex减1,再次调用maxHeapify,又得到最大值,存放在A[0],再和A[n-2]互换,把堆的大小再减一,这样循环下去,知道堆的大小为0。那么我们就得到了由小到大的排好序的数组。
void heapSort(Heap *hp) { int tmp; int last; while(hp->heapMaxIndex>0) { last = hp->heapMaxIndex ; //exchange tmp = hp->arr[last]; hp->arr[last] = hp->arr[0]; hp->arr[0] = tmp; hp->heapMaxIndex -= 1; maxHeapify(hp,0); //make heap from root node 0 to heapMaxIndex } }
测试堆排序
void printArr(int *p, int size) { int i; for(i=0; i<size;i++) { printf("%d ",p[i]); } } int main() { int a[]={15,25,32,23,1,-4,35,2,-85,42,0,12,26,56,45,12,145,17,25,21}; printArr(a,20); printf("\n"); Heap hpa,*phpa; phpa = createHeap(a,20,&hpa); heapSort(phpa); printArr(a,20); putchar('\n'); return 0; }
结果为:-85 -4 0 1 2 12 12 15 17 21 23 25 25 26 32 35 42 45 56 145
堆排序应用:
优先级队列,事件驱动模式响应队列等。
相关文章推荐
- 常见排序算法的C语言实现之堆排序
- 堆排序及其c语言实现
- [数据结构]堆排序的C语言简单实现
- 堆排序的C语言实现
- 堆排序原理及c语言实现
- 堆排序的c语言实现
- C语言实现堆排序
- 堆排序(C语言实现)
- 堆排序及C语言实现
- 算法导论之插入排序,选择排序,归并排序,冒泡排序,希尔排序,堆排序,快速排序的c语言实现
- 【算法】C语言实现堆排序
- [原创]堆排序 C语言实现
- 排序【1】之堆排序的C语言实现
- 算法导论:堆排序递归实现 (c语言)
- 三种排序算法的C语言实现--直接插入、希尔、堆排序
- 程序员面试题--堆排序的C语言实现
- 堆排序的C语言实现
- 堆排序(C语言实现)迭代
- 数据结构之---C语言实现堆排序
- 算法导论(Introduction to Algorithms)之堆排序(C语言实现)