【数据结构】堆的常规操作(建堆,删除,插入)

写在前面:该篇文章转自柳婼【数据结构】堆、堆排序笔记

堆的一些性质:

堆是一棵完全二叉树,树的每个结点的值都不小于(或者不大于)其左右孩子的值。
父亲结点大于等于孩子结点的值叫做大顶堆,反之叫做小顶堆
大顶堆的每个结点的值都是以它为根结点的子树的最大值,反之最小值
下面都以大顶堆为例子:
两个兄弟之间不存在大小比较关系,堆只能说明某结点引导的子树的所有子结点都比它小,就像领导关系一样,下属之间或者领导之间可能有实力高低,但是领导是他的所有下属的最高级

建堆:把所有非叶子结点都向下调整(从n/2开始直到1)

void createHeap()
{
	for(int i=n/2;i>=1;i--)
		downAdjust(i,n);
}

向下调整:(不断和自己的左右孩子比较,把孩子的最大值和自己交换,直到结点的下标大于最后一个元素的数组下标high为止。记住:i结点的左孩子j结点满足j = i * 2;)

const int maxn = 100;
int heap[maxn], n = 10;

//对heap数组在[low, high]范围进行向下调整,其中low为欲调整的结点的数组下标,high一般为堆的最后一个元素的数组下标
void downAdjust(int low, int high) {
  int i = 1ow, j = i * 2;//i为将要调整的结点,j为它的左孩子
  while(j <= high) {
    if(j + 1 <= high && heap[j + 1] > heap[j])
      j = j + 1; //那就让j存储数值最大的那个结点所对应的下标
    if(heap[j] > heap[i]) {
      swap(heap[i], heap[j]);
      i = j; j = i * 2;
    } else {
      break;
    }
  }
}

删除堆顶元素(用最后一个元素覆盖堆顶元素,然后让n- -,然后向下调整)

void deleteTop() {
  heap[1] = heap[n--];
  downAdjust(1, n);
}

增加一个元素(添加到最后一个结点的后面,然后进行向上调整操作)

void insert(int x) {
  heap[++n] = x;
  upAdjust(1, n);
}

向上调整操作就是把将要调整的结点与父亲结点比较,如果权值比父亲结点大,那么就交换其与父亲结点,这样反复比较,直到到达堆顶或者是父亲结点的权值比较大为止

void upAdjust(int low, int high) {//low一般传入1,high为将要调整的结点的数组下标
  int i = high, j = i / 2; //i为将要调整结点,j为其父亲
  while(j >= low) {
    if(heap[j] < heap[i]) {
      swap(heap[j], heap[i]);
      i = j; j = i / 2;
    } else {
      break;
    }
  }
}

堆排序:
在建堆完毕后,堆排序就是取出堆顶元素,然后将堆的最后一个元素i替换至堆顶,再进行一次针对堆顶元素1向下调整(1, i – 1)范围,直到堆中只有一个元素为止(i == 2)

void heapSort() {
  createHeap();
  for(int i = n; i >= 2; i--) {
    swap(heap[i], hea[1]);
    downAdjust(1, i - 1);
  }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

给个选择

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值