堆排序
本文章适合看过堆排序的人
总结
- 堆是一颗完全二叉树,一般直接用数组来存放数据就可以了,因为下标有规律
- 两种堆的调整方式
- 一种是pop最上面,把最后面的放在第一个,从上往下传递(堆排序运用的)
- 一种是尾插后,从下往上传递调整
自顶向下调整
//pop最上面,把最后面的放在第一个,从上往下传递
//下标从1开始,那么cur*2就是cur的左孩纸,cur*2+1就是cur的右孩子
//把cur当作根节点,对cur这颗树进行调整
//把cur先保存,后面的逐级往前放
//因为这里默认其他已经是最大堆排好的了
//从cur往下调整,不要交换,不必要的交换降低效率,合适的位置再放入cur
void heap_adjust(vector<int>&v, int cur, int size) {
int tmp = v[cur];
for (int i = cur * 2; i <= size; i*=2) {
if (i + 1 <= size && v[i] < v[i + 1])
i++;
if (tmp < v[i]) {
v[cur] = v[i];//补上去
cur = i;//补上去,空了
}
else
break;//找到应该插入的地方
}
v[cur] = tmp;
}
自下向上调整
//尾插,,从下往上调整
//也是逐级往上找位置,比val小的逐级往下拿
void heap_push(vector<int>&v, int val) {
v.push_back(val);
int cur = v.size() - 1;
for (int i = cur / 2; i >= 0; i /= 2) {
if (v[i] < val) {
v[cur] = v[i];
cur = i;
}
else break;
}
v[cur] = val;
}
堆排序主函数
//用最大堆从小到大堆排序
vector<int> heap_sort(vector<int>&v) {
//调整成一个最大堆
for (int i = (v.size() - 1) / 2; i >= 0; i--) {
heap_adjust(v, i , v.size() - 1);
}
//堆排序开始罗
int size = v.size() - 1;
for (int i = size; i > 0; i--) {
swap(v[1], v[i]);//把最大值放最后,最后一个拿到前面
heap_adjust(v, 1, size);//调整为最大堆
}
}