程序猿面试之 堆排序 C++
堆是一颗完全二叉树,分为大顶堆和小顶堆:
大顶堆:每一个结点的值都大于其子节点
小顶堆:每一个结点的值都小于其子节点
堆排序分为两步:
- 将数组 vec 变为大顶堆,此时头结点 vec[0] 就是最大值
- 将头结点 vec[0] 和尾结点 vec[n-1] 交换,那么交换后,最大值就在尾部为vec[n-1];
- 将vec[0], vec[1], …, vec[n-2];重新构造为大顶堆;即将除去最后一个元素(最大值)的数组重建为大顶堆。此时堆顶vec[0]即为剩下的的元素中的最大值m。
- 将vec[0]和vec[n-2]交换,此时m就被换到vec[n-2];
- 不断的重建并交换,那么尾部的元素会被排序
堆排序关键是将最大的元素交换交换后的重建过程;这个过程被称为heapify;下面的程序中将其命名为MaxHeap.
//移除index处的节点后堆的重建方法
//index为需要调整的父节点下标,heapsize用来判断孩子是否越界;一开始的时候heapsize等于vec.size();而不是size -1;
void MaxHeap(vector<int>&vec, int index, int heapsize) {
//父亲下标
int dad = index;
//左孩子的下标; 右孩子下标left_son+1;
int left_son = 2*dad+1;
while(left_son < heapsize) {
//左右孩子决出最大值的下标
int largest = left_son +1 < heapsize && vec[left_son+1] > vec[left_son] ? left_son + 1: left_son;
//父亲和最大孩子之间pk得出最大值
largest = vec[largest] > vec[dad] ? largest:dad;
//如果比较下来,父亲还是最大的,那么不用比了,因为父亲>孩子,孩子>孩子的孩子;所以不用比了,直接跳出;
if(largest == dad) return;
//如果父亲不是最大,那么还需要往下调整
swap(vec[largest], vec[dad]);
dad = largest;
left_son = dad*2 +1;
}
}
//排序主函数
void HeapSort(vector<int>& vec) {
if(vec.size() < 2) return;
int heap_size = vec.size();
//从最后一个父亲开始调整,把数组调整为堆
for(int i = (heap_size -1)/2; i >= 0; i--) {
MaxHeap(vec, i, heap_size);
}
//交换第一个和最后一个元素,并将堆减小
swap(vec[0],vec[--heap_size]);
//不断的交换头结点并重建的过程
while(heap_size > 0) {
MaxHeap(vec, 0, heap_size);
swap(vec[0],vec[--heap_size]);
}
}
调用示例
#include<iostream>
#include<vector>
using namespace std;
//移除index处的节点后堆的重建方法
//index为需要调整的父节点下标,heapsize用来判断孩子是否越界;一开始的时候heapsize等于vec.size();而不是size -1;
void MaxHeap(vector<int>&vec, int index, int heapsize) {
//父亲下标
int dad = index;
//左孩子的下标; 右孩子下标left_son+1;
int left_son = 2*dad+1;
while(left_son < heapsize) {
//左右孩子决出最大值的下标
int largest = left_son +1 < heapsize && vec[left_son+1] > vec[left_son] ? left_son + 1: left_son;
//父亲和最大孩子之间pk得出最大值
largest = vec[largest] > vec[dad] ? largest:dad;
//如果比较下来,父亲还是最大的,那么不用比了,因为父亲>孩子,孩子>孩子的孩子;所以不用比了,直接跳出;
if(largest == dad) return;
//如果父亲不是最大,那么还需要往下调整
swap(vec[largest], vec[dad]);
dad = largest;
left_son = dad*2 +1;
}
}
//排序主函数
void HeapSort(vector<int>& vec) {
if(vec.size() < 2) return;
int heap_size = vec.size();
for(int i = (heap_size -1)/2; i >= 0; i--) {
MaxHeap(vec, i, heap_size);
}
//交换第一个和最后一个元素,并将堆减小
swap(vec[0],vec[--heap_size]);
while(heap_size > 0) {
MaxHeap(vec, 0, heap_size);
swap(vec[0],vec[--heap_size]);
}
}
int main() {
vector<int>vec = {3,25,6,2,7,35,25,6,36,3,4,7,8,3};
HeapSort(vec);
for(int i =0; i< vec.size(); i++) {
std::cout<<vec[i]<<" ";
}
return 0;
}