堆 概念
最大堆:最上面的结点数值最大
特点: 1.每个结点最多可以有两个结点
2.根结点的键值是所有结点中最大的,每个结点的值都比孩子的值大。
3.除了根节点 没有兄弟结点,最后一个 左子结点可以没有兄弟结点,其他结点必须有兄弟结点。(有这个限制,下面的求子结点和父结点的公式才能成立。)
最小堆:最上面的结点数值最小….其他同最大堆
堆是最有个性的树,用数组表示的树。
在数组中快速创建堆 左图——》右图
1.找到最后一个结点的父结点,(该父结点)与其子结点进行比较大小,若某个子结点大于父结点,则与该父结点交换位置。(就是从最后一个非叶子结点开始进行调整,(向下调整就是找到该父结结点的子结点,进行调整。))
2.再移动到前一个父结点,进行上述操作。
3……
补充:static修饰的全局函数
一个普通的全局的静态函数。. 这样的static函数与普通函数的区别是:用static修饰的函数,限定在本源码文件中,不能被本源码文件以外的代码文件调用。
链接——链接
相关接口实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 typedef struct _Heap { int * arr; int size; int capacity; }Heap; void buildHeap (Heap& hp) ;void adjustDown (Heap& hp, int index) ;bool insertHeap (Heap& hp, int val) ;bool initHeap (Heap& hp, int * orginal, int size) { int capacity = DEFAULT_CAPCITY > size ? DEFAULT_CAPCITY : size; hp.arr = new int [capacity]; if (!hp.arr) { return false ; } hp.capacity = capacity; hp.size = 0 ; if (size > 0 ) { for (int i = 0 ; i < size; i++) { insertHeap(hp, orginal[i]); } } return true ; } void buildHeap (Heap& hp) { for (int i = ((hp.size - 1 )-1 ) / 2 ; i >= 0 ; i--) { adjustDown(hp, i); } } void adjustDown (Heap& hp,int index) { int cur = hp.arr[index]; int parent = 0 ; int child = 0 ; for (parent = index; (parent * 2 + 1 ) < hp.size; parent = child) { child = parent * 2 + 1 ; if (((child + 1 ) < hp.size) && hp.arr[child] < hp.arr[child + 1 ]) { child++; } if (cur >= hp.arr[child]) { break ; } else { hp.arr[parent] = hp.arr[child]; hp.arr[child] = cur; } } } void adjustUp (Heap& hp, int index) { while (index > 0 ) { int temp = hp.arr[index]; int parent = (index - 1 ) / 2 ; if (temp > hp.arr[parent]) { hp.arr[index] = hp.arr[parent]; hp.arr[parent] = temp; index = parent; } else { break ; } } } bool insertHeap (Heap& hp, int val) { if (hp.size == hp.capacity) { return false ; } int index = hp.size; hp.arr[hp.size++] = val; adjustUp(hp,index); return true ; } void printHeap (Heap& hp) { int num = hp.size; int front = 0 ; int back = 1 ; int row = 1 ; while (num) { for (int j = front; j < back; j++) { cout << hp.arr[j] << " " ; } cout << endl ; num -= row; if (num <= 0 ) { break ; } row *= 2 ; front = back; if (num - row <= 0 ) { back = hp.size; } else { back += row; } } } void popTop (Heap& hp) { hp.arr[0 ] = hp.arr[hp.size - 1 ]; hp.size--; buildHeap(hp); }
构建堆 and 向下调整的图解
补充——打印输出
堆插入元素按升序(降序)排序的效率时很高的,因为只需要和父亲比较。父亲的父亲……
应用 构建优先队列
操作系统内核作业调度是优先队列的一个应用实例,它根据优先级的高低而不是先到先服务的方式来进行调度;
如果最小键值元素拥有最高的优先级,那么这种优先队列叫作升序优先队列 (即总是先删除最小 的元素),类似的,如果最大键值元素拥有最高的优先级,那么这种优先队列叫作降序优先队列 (即总是先删除最大的元素);由于这两种类型是完全对称的,所以只需要关注其中一种。
核心实现同上建最大堆 ,就是把其中的数据换成了Task(任务,里面包括优先级,等其他属性),根据优先级的大小,来创建堆。
堆排序
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特 点快速定位指定索引的元素。
选择排序工作原理:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置, 然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。
类似于上面构建最大堆时的弹出堆顶元素。只是不将最后一个元素删除(不size–),而是不断的将建好的大堆堆顶元素放到最后。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 #include <iostream> using namespace std ;void adjustDown (int * ary, int index, int tatal) { int cur = ary[index]; int parent = 0 ; int child = 0 ; for (parent = index; (parent * 2 + 1 ) < tatal; parent = child) { child = parent * 2 + 1 ; if (((child + 1 ) < tatal) && (ary[child] < ary[child + 1 ])) { child++; } if (cur >= ary[child]) { break ; } else { ary[parent] = ary[child]; ary[child] = cur; } } } void HeapSort (int * ary,int size) { int tempS = size; for (int i = (size - 1 - 1 ) / 2 ; i >= 0 ; i--) { adjustDown(ary, i, tempS); } int front = 0 ; int back = tempS - 1 ; for (;back > 0 ; back--) { int tempChange = ary[front]; ary[front] = ary[back]; ary[back] = tempChange; adjustDown(ary, front, --tempS); } } int main (void ) { int arraY[] = {3 ,1 ,2 ,4 ,56 ,7 ,89 ,99 }; int size = sizeof (arraY) / sizeof (arraY[0 ]); HeapSort(arraY, size); for (int i = 0 ; i < size; i++) { cout << arraY[i] << " " ; } return 0 ; }