数据结构-堆详解

图片:

二叉堆的父节点为这个子树的最值。

如何维护它。
我们发现它是一棵二叉树,那就自然满足若父节点为 x x x 则左儿子节点为 x × 2 x\times2 x×2 右儿子为 x × 2 + 1 x\times 2 + 1 x×2+1 这是显然的,但如果写成指针或结构体就太麻烦了,所以考虑用数组来维护它。

用一个数组 T T T 来存储这颗二叉树,根节点为 T 1 T_1 T1 根据二叉树的性质对于每个子节点 x x x 则有:

  1. x > 1 x>1 x>1 则fa[x]=i/2;
  2. 2 × x > n 2\times x>n 2×x>n x x x 没有儿子,如果 2 × x + 1 > n 2\times x+1>n 2×x+1>n x x x 没有右儿子。
  3. 如果节点 x x x 有孩子,则 x x x 的左儿子为 x × 2 x\times 2 x×2 右儿子为 x × 2 + 1 x\times 2 + 1 x×2+1

复杂度分析:

这样做由于二叉树只有 log ⁡ 2 n \log_2n log2n 层,自然单次复杂度为 O ( log ⁡ 2 n ) O(\log_2n) O(log2n)可以解决 n ≤ 1 0 6 n\leq 10^6 n106 及以下的问题。

那么该如何让这个二叉树平衡?通常使用上浮法与下沉法。
例子:
假设你已经有一个堆了,就是上面那个

这个时候你如果想要给它加入一个节点怎么办,比如说0?

先插到堆底(严格意义上来说其实0是在5的左儿子的,图没画好放不下去,不过也不影响)

然后你会发现它比它的父亲小啊,那怎么办?不符合小根堆的性质了啊,那就交换一下他们的位置

交换之后还是发现不符合小根堆的性质,那么再换

还是不行,再换

好了,这下就符合小根堆的性质了。

事实上堆的插入就是把新的元素放到堆底,然后检查它是否符合堆的性质,如果符合就丢在那里了,如果不符合,那就和它的父亲交换一下,一直交换交换交换,直到符合堆的性质,那么就插入完成了。
删除同理这里不在复述了。

代码:

插入:

void push(int x){
	h[++len] =x;
	int i=len;
	while(i>1 && h[i]<h[len/2]){
		swap(h[i],h[i/2]);
		i/=2;
	}
}

删除:

void pop(){
	h[1] = h[len--];
	int i=1;
	while((i<<1)<=len){
		int son=(i<<1);
		if(son<len&&h[son+1]<h[son]){
			son++;
		}
		if(h[son]<h[i]){
			swap(h[son],h[i]);
			i=son;
		}
		else break;
	}
}

STL堆:

算法竞赛中虽然STL没有手写快但是否好像实用代码:

定义一个大根堆即堆内为递减的序列

priority_queue<int> Q;

小根堆:

priority_queue<int,vector<int>,greater<int>> Q2;

使用:

插入一个数:

void insert(int x){
	q.push(x);
}

删除堆头:

void erase(){
	q.pop();
}

访问堆头

int front(){
	return q.top();
}

建议使用STL的堆

相关推荐

  1. 数据结构-

    2024-04-15 06:30:04       43 阅读
  2. 数据结构--排序

    2024-04-15 06:30:04       28 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-15 06:30:04       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-15 06:30:04       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-15 06:30:04       20 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-15 06:30:04       20 阅读

热门阅读

  1. python课本基础练习——列表推导式

    2024-04-15 06:30:04       14 阅读
  2. 2024/4/12 网络编程day2

    2024-04-15 06:30:04       16 阅读
  3. 初识DOM

    初识DOM

    2024-04-15 06:30:04      16 阅读
  4. 双向冒泡算法(C语言版)

    2024-04-15 06:30:04       16 阅读
  5. Android之图片压缩几种方式

    2024-04-15 06:30:04       15 阅读
  6. Android之启动优化

    2024-04-15 06:30:04       21 阅读
  7. 链表linked list: 将新节点链接到链表的末尾

    2024-04-15 06:30:04       24 阅读
  8. 7天八股速记之C++后端——Day 1

    2024-04-15 06:30:04       14 阅读
  9. 创建一个flutter的左划重命名,右划隐藏的功能

    2024-04-15 06:30:04       18 阅读