排序 堆的实现和利用堆来排序
Table of Contents
堆是最有趣的数据结构,看过《算法导论》的都会很容易的写出一个堆来。实现堆的过程总会让我们 YY 一起代码和数据都是我们自己来操控的
为了更方便的实现堆,我们通常从 1 开始计数,而不是 0,当然 0 号元素可以用来存堆的个数。为了方便,还是用一个变量来保存堆的大小,下面开始 YY
一些基本的定义
int a[100] = { 0, 4, 187, 109, 89, 13, 70, 29, 81, 168, 195 }; int len = 10; void swap(int i, int j) { int t = a[i]; a[i] = a[j]; a[j] = t; } int par(int i) { return i/2; } int left(int i) { return i*2; } int right(int i) { return i*2 + 1; }
heapy:调整堆
void heapy(int i) { int l = left(i); int r = right(i); int max = i; // 假设 i 是最大 // 找出最大的数是 i 还是 i 的左节点,还是 i 的右节点 if (l <= len && a[l] > a[max]) { max = l; } if (r <= len && a[r] > a[max]) { max = r; } if (i != max) { // i 不是最大,开始调整 swap(i, max); heapy(max); // 递归调整自己 } }
build:建堆
void build_heap() { for (int i = len/2; i >= 1; i--) { // 不能从 1 开始到 len/2 heapy(i); } } void show() { for (int i = 1; i <= len; i++) { printf("%d ", a[i]); } printf("\n"); } int main(void) { build_heap(); show(); return 0; }
insert:插入新的元素
void insert(int x) { len++; a[len] = x; int i = len; int p = par(i); while (a[i] > a[p]) { swap(i, p); i = p; p = par(i); } } int main(void) { build_heap(); show(); insert(175); show(); return 0; }
removetop:取出堆顶
int remove_top() { swap(1, len); // len 是最后一个 int x = a[len]; len--; // 注意先让长度 -1,再调整 heapy(1); // 重新调整堆 return x; } int main(void) { build_heap(); show(); insert(175); show(); int ret = remove_top(); show(); printf("\n%d\n", ret); return 0; }
现在来使用堆来排序,只要每次都 removetop 就行了
void heap_sort() { int num = len; // 先保存 len,因为 len 等下会 -1 for (int i = 1; i <= num; i++) { printf("%d ", remove_top()); } printf("\n"); } int main(void) { build_heap(); show(); heap_sort(); return 0; }