堆的实现

顺序结构存储就是使用数组来存储只适合表示完全二叉树一般使用数组只适合于完全二叉树(物理上是一个数组,逻辑上是二叉树)-堆
堆的实现–大堆和小堆
堆是一颗完全二叉树
堆中某个结点的值总是不大于或不小于其父节点的值
作用:根节点最大为大堆根节点最小为小堆
堆:时间复杂度 O(log(n))
空间复杂度 O(1)
int tree[] 和 int size 合起来表示装堆的值的数组
int rootIdx 表示要调整的结点的下标
建堆首先要对其进行向下调整,因为是完全二叉树所以没有左孩子就一定没有右孩子,因为存的数是在数组里面,判断的标准就是左孩子下标是否越界
(1)假设调整结点为rootIdx,怎么求其左右孩子的下标
(2)最后一个节点的下标为(size-1)—parent=(child-1)/2
child=size-1 所以左孩子下标为rootidx
2+1 右孩子的下标为rootidx
2+2;
(3)当左边孩子的下标大于size则说明是叶子
(4)如果不是叶子则保存这个值和根比较,比根大则满足,如果比根小则进行交换
(5)交换后要继续向下调整因为下面的树的性质有可能被破坏了
void AdjustDown(int tree[], int size, int rootIdx) {
// 如果是叶子,调整结束,直接返回
if (2 * rootIdx + 1 >= size) {
return;
}
// 如果不是叶子,找到最小孩子的下标
int minIdx;
if (2 * rootIdx + 2 >= size) {
// 右孩子的下标数组越界了,所以没有右孩子
minIdx = 2 * rootIdx + 1;
}
else if (tree[2 * rootIdx + 1] <= tree[2 * rootIdx + 2]) {
minIdx = 2 * rootIdx + 1;
}
else {
minIdx = 2 * rootIdx + 2;
}
// 拿最小孩子的值 和 要调整的根的值进行比较
if (tree[rootIdx] <= tree[minIdx]) {
// 如果根的值比较小,调整结束,直接返回
(最小的已经是根了,满足堆的性质,停止)
return;
}
else {
// 否则,交换根的值 和 最小孩子的值,
int t = tree[minIdx];
tree[minIdx] = tree[rootIdx];
tree[rootIdx] = t;
// 继续堆刚才最小孩子的下标进行调整(如果发生了交换,则下面的树的堆性质可能被破坏了,继续调整)
AdjustDown(tree, size, minIdx);
}
}
向上调整
void AdjustUp(int tree[], int size, int child) {
if (child == 0) {
return;
}
int parent = (child - 1) / 2;
if (tree[child] >= tree[parent]) {
return;
}
int t = tree[child];
tree[child] = tree[parent];
tree[parent] = t;
AdjustUp(tree, size, parent);
}
void CreateHeap(int tree[], int size) {
for (int i = (size - 2) / 2; i >= 0; i–) {
AdjustDown(tree, size, i);
}
}
堆的插入log(n)
void HeapPush(Heap *pH, int v) {
pH->array[pH->size++] = v;
AdjustUp(pH->array, pH->size, pH->size - 1);
}
// O(log(n)) 堆的山存储每次出的是当前最小值
int HeapPop(Heap *pH) {
int v = pH->array[0];
pH->array[0] = pH->array[pH->size - 1];
pH->size–;
AdjustDown(pH->array, pH->size, 0);
return v;
}
为什么需要倒着调整,向下调整的前提有限制
必须左右子树已经是堆了,才可以向下调整
最后一个结点的下标是 size - 1(根据数组的特性)
最后一个非叶子结点就是最后一个结点的双亲
parent = (child - 1) / 2–带入 (size - 2) / 2
用途: 排降序,建小堆
// 建大堆,找出最大值后,会破坏堆结构
void HeapSort(int array[], int size) {
CreateHeap(array, size);
for (int i = 0; i < size; i++) {
int t = array[0];
array[0] = array[size - 1 - i];
array[size - 1 - i] = t;
AdjustDown(array, size - 1 - i, 0);
}
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值