堆的概念:
- 堆是一颗完全二叉树
- 满足父节点 > 子节点(大根堆)
完全二叉树:
除最后一层外,都是满二叉树,并且最后一层节点是从左到右依次添加。
堆化调整:
heapify的过程:
出现父节点小于子节点时,从中找出最大值,个根节点进行交换。交换后如下:
接着找刚刚交换的节点,再对4和5进行交换。
整个过程如下:
- 从h-1层开始:
2. 对h-1层所有节点进行heapify,使得框内子树成为一个堆。
3. 往上一层,接着进行heapify,直到调整到第一层。
堆的表示与构建:
好处,根据子节点,可以直接求得父节点,反之,亦可:
void swap(int arr[], int i, int j){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
void heapify(int tree[], int n, int i){
if(i >= n)
return;
int c1 = 2 * i + 1;
int c2 = 2 * i + 2;
int maxx = i;
if(c1 < n && tree[c1] > tree[maxx]){
maxx = c1;
}
if(c2 < n && tree[c2] > tree[maxx]){
maxx = c2;
}
if(maxx != i){
swap(tree, maxx, i);
heapify(tree, n, maxx);
}
}
void build_heap(int tree[], int n){
int last_node = n - 1;
int parent = (last_node - 1) / 2;
int i;
for(int i = parent; i >= 0; i--){
heapify(tree, n, i);
}
}
堆排序
- 最大节点和最后一个节点交换(将最大的节点放到最后一位了)
- 将最后一个结点砍断,重新heapify
- 重复1.2过程,直到剩下一个节点
void heap_sort(int tree[], int n){
build_heap(tree, n);
int i;
for(i = n - 1; i >=0; i--){
swap(tree, i, 0);
heapify(tree, i, 0);
}
}
参考B站视频:https://www.bilibili.com/video/av47196993/?spm_id_from=333.788.videocard.0