数据结构与算法——堆排序
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特 点快速定位指定索引的元素.
(选择排序工作原理 - 第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置, 然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待 排序的数据元素的个数为零)
1. 排序核心实现
、
2. 具体算法实现
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 typedef struct _Heap 6 { 7 int *arr; //存储堆元素的数组 8 int size; //当前已存储的元素个数 9 int capacity; //当前存储的容量 10 }Heap; 11 12 bool initHeap(Heap &heap, int *orginal, int size); 13 bool popMax(Heap &heap, int &value); 14 void heapSort(Heap &heap); 15 static void buildHeap(Heap &heap); 16 static void adjustDown(Heap &heap, int index); 17 18 /*初始化堆*/ 19 bool initHeap(Heap &heap, int *orginal, int size) 20 { 21 //heap.arr = new int[capacity]; 22 heap.arr = orginal; 23 if (!heap.arr) return false; 24 25 heap.capacity = size; 26 heap.size = size; 27 28 //如果存在原始数据则构建堆 29 if(size > 0) 30 { 31 //方式一: 直接调整所有元素 32 //建堆 33 buildHeap(heap); 34 } 35 return true; 36 } 37 38 /* 从最后一个父节点(size/2-1 的位置)逐个往前调整所有父节点(直到根节点), 确保每一个父节点都是一个最大堆,最后整体上形成一个最大堆 */ 39 void buildHeap(Heap &heap) 40 { 41 int i; 42 for (i = heap.size / 2 - 1; i >= 0; i--) 43 { 44 adjustDown(heap, i); 45 } 46 } 47 48 /*将当前的节点和子节点调整成最大堆*/ 49 void adjustDown(Heap &heap, int index) 50 { 51 int cur = heap.arr[index]; //当前待调整的节点 52 int parent, child; 53 54 /*判断否存在大于当前节点子节点,如果不存在 ,则堆本身是平衡的,不需要调整; 55 如果存在,则将最大的子节点与之交换,交换后,如果这个子节点还有子节点,则要继续 56 按照同样的步骤对这个子节点进行调整*/ 57 for (parent = index; (parent * 2 + 1)<heap.size; parent = child) 58 { 59 child = parent * 2 + 1; 60 //取两个子节点中的最大的节点 61 if (((child + 1)<heap.size) && (heap.arr[child]<heap.arr[child + 1])) 62 { 63 child++; 64 } 65 //判断最大的节点是否大于当前的父节点 66 if (cur >= heap.arr[child]) 67 { 68 //不大于,则不需要调整,跳出循环 69 break; 70 } 71 else 72 { 73 //大于当前的父节点,进行交换,然后从子节点位置继续向下调整 74 heap.arr[parent] = heap.arr[child]; 75 heap.arr[child] = cur; 76 } 77 } 78 } 79 80 /* 实现堆排序 */ 81 void heapSort(Heap &heap) 82 { 83 if (heap.size<1) return ; 84 while(heap.size>0) 85 { 86 int tmp = heap.arr[0]; 87 heap.arr[0] = heap.arr[heap.size-1]; 88 heap.arr[heap.size-1] = tmp; 89 heap.size--; 90 adjustDown(heap, 0);// 向下执行堆调整 91 } 92 } 93 94 /* 删除最大的节点,并获得节点的值*/ 95 bool popMax(Heap &heap, int &value) 96 { 97 if (heap.size<1) return false; 98 value = heap.arr[0]; 99 heap.arr[0] = heap.arr[--heap.size]; 100 //heap.arr[0] = heap.arr[heap.size-1]; 101 //heap.size--; 102 adjustDown(heap, 0);// 向下执行堆调整 103 return true; 104 } 105 106 int main(void) 107 { 108 Heap hp; 109 int origVals[] = { 1, 2, 3, 87, 93, 82, 92, 86, 95 }; 110 int i = 0; 111 if(!initHeap(hp, origVals, sizeof(origVals)/sizeof(origVals[0]))) 112 { 113 fprintf(stderr, "初始化堆失败!\n"); 114 exit(-1); 115 } 116 117 for (i = 0; i<hp.size; i++) 118 { 119 printf("the %dth element:%d\n", i, hp.arr[i]); 120 } 121 122 //执行堆排序 123 heapSort(hp); 124 printf("堆排序后的结果:\n"); 125 for(i=0; i<sizeof(origVals)/sizeof(origVals[0]); i++) 126 { 127 printf(" %d", origVals[i]); 128 } 129 130 system("pause"); 131 return 0; 132 }
3. 快速查找无序集合中前 N 大(小)的记录