基本概念:
堆排序原理和过程强烈推荐看这个up主 请叫我AXin
堆是一种经过排序的完全二叉树,其中任一非终端节点的数据值均不大于(或不小于)其左子节点和右子节点的值。
最大堆和最小堆是二叉堆的两种形式。
最大堆:根结点的键值是所有堆结点键值中最大者。
最小堆:根结点的键值是所有堆结点键值中最小者。
而最大-最小堆集结了最大堆和最小堆的优点,这也是其名字的由来。
最大-最小堆是最大层和最小层交替出现的二叉树,即最大层结点的儿子属于最小层,最小层结点的儿子属于最大层。
以最大(小)层结点为根结点的子树保有最大(小)堆性质:根结点的键值为该子树结点键值中最大(小)项。
代码关键:
1.下标为i的元素,父节点下标为 (i-1)/2
2.下标为i的元素,两个子节点下标为 左孩子:i * 2 + 1 右孩子:i * 2 + 2
3.长度为n的堆数组,从(n-1-1)/2 开始进行堆排序(对应代码中heapify),也就是n/2 - 1
代码:
class Heap {
public:
void heapify(vector<int>&arr, int idx, int n){ // 从idx开始调整堆
int left = (idx << 1) + 1, right = (idx << 1) + 2; // 孩子节点下标
int minIdx = idx;
if(left < n && arr[left] < arr[minIdx]) minIdx = left;
if(right < n && arr[right] < arr[minIdx]) minIdx = right;
if(minIdx != idx){ // 如果孩子节点的值比父节点小,那么久swap然后继续检查孙子节点
swap(arr[minIdx], arr[idx]);
heapify(arr, minIdx, n);
}
}
void heap(vector<int>&arr, int n){ // 之所以要指定堆大小,是因为arr可能比我们想要的堆更大
for(int i = (n >> 1) - 1; i >= 0; --i){ // 堆的大小为n,则从n/2 - 1 开始建堆
heapify(arr, i, n);
}
}
};
做笔记使用。如果有更好的写法还请赐教!!!!溜了溜了~