父节点为i ——>左孩子2*i+1,右孩子2*i+2
子——>父:(i-1)/2
注意:升序用大根堆,降序用小根堆
堆排序是不稳定的排序,空间复杂度为O(1),平均时间复杂度是(nlogn)
大根堆:每个节点的值都小于或等于它的左右孩子的节点 最大的值就是堆顶的元素
思想:将顶端的数与末尾的数交换,此时,末尾的数为最大值,剩余待排序数的个数为n-1
将剩余的n-1个数在构造成大根堆,反复执行,便能得到有序数组
如何构造大根堆:从最后一颗子树开始,从后往前调整,每次调整,从上往下调整,调整为大根堆
最后一层第一个节点的索引为:节点总数/2,也就是第一个叶子节点 最后一个费叶子节点就是最后一个叶子节点所有-1,找到最后一个非叶子节点,比较它的左右节点中最大的一个值,是否比它大,如果比他大就交换位置,然后找到下一个非叶子节点,重复此操作
小根堆:~
代码 下标是从0开始的
#include
using namespace std;
void AdjustDown(int* arr, int n, int root) {
int parent = root;
while ((parent << 1) + 1 < n) {
int child = (parent << 1) + 1;
if (child + 1 < n && arr[child + 1] < arr[child])child++;
if (arr[child] < arr[parent])swap(arr[child], arr[parent]);
else break;
parent = child;
}
}
void HeapSort(int* arr, int n) {
for (int i = (n - 1 - 1)/2; i >= 0; i--) {
AdjustDown(arr, n, i);
}
int end = n-1;
while (end >= 0) {
swap(arr[0], arr[end]);
AdjustDown(arr, end, 0);
end--;
}
};
void print_arr(int* arr,int n) {
for (int i = 0; i
}
}
int main() {
int arr[] = { 1,9,2,8,3,7,4,6,5,10 };
int n = sizeof(arr) / sizeof(arr[0]);
HeapSort(arr, n);
print_arr(arr,n);
return 0;
}
一些操作
插入
void push(int x){//要插入的数
heap[++siz]=x;
now=siz;
//插入到堆底
while(now){//还没到根节点,还能交换
ll nxt=now>>1;//找到它的父亲
if(heap[nxt]>heap[now])swap(heap[nxt],heap[now]);//父亲比它大,那就交换
else break;//如果比它父亲小,那就代表着插入完成了
now=nxt;//交换
}
return;
}
while条件改为now!=1
删除操作
void pop(){
swap(heap[siz],heap[1]);siz--;//交换堆顶和堆底,然后直接弹掉堆底
int now=1;
while((now<<1)<=siz){//对该节点进行向下交换的操作
int nxt=now<<1;//找出当前节点的左儿子
if(nxt+1<=siz&&heap[nxt+1]
查询的话就是第一个元素了
priority_queue
priority_queue
q.top()//取得堆顶元素,并不会弹出
q.pop()//弹出堆顶元素
q.push()//往堆里面插入一个元素
q.empty()//查询堆是否为空,为空则返回1否则返回0
q.size()//查询堆内元素数量