堆的实现(手写堆

堆其实就是一个完全二叉树
堆分成大顶堆和小顶堆,大顶堆:节点的值 >= 其左孩子的值 且 >= 右孩子的值,对于所有节点成立。小顶堆相反。

关于建堆初始编号造成的困惑

如果根节点编号是 0,那么:

  • i 节点的父节点:(i-1)/2
  • i 节点的左孩子:i * 2 + 1
  • i 节点的右孩子:i * 2 + 2

如果根节点编号是 1,那么:

  • i 节点的父节点:i / 2
  • i 节点的左孩子:i * 2
  • i 节点的右孩子:i * 2 + 1

在这里插入图片描述

学习博客
初始化一个小顶堆
节点 i i i 的两个子节点编号为 2 ∗ i 2*i 2i 2 ∗ i + 1 2*i+1 2i+1
所以节点 i i i 除以 2 2 2 即可得到它的父节点
code:

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define mem(x, d) memset(x, d, sizeof(x))
#define eps 1e-6
using namespace std;
const int maxn = 2e6 + 9;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m;
int heap[maxn];

void up(int i){// 上调编号位i的节点
	if(i == 1) return;
	while(i != 1){
		if(heap[i] < heap[i / 2]) swap(heap[i], heap[i / 2]);
		else break;
		i /= 2;
	}
}
void work()
{
	cin >> n;
	for(int i = 1; i <= n; ++i){
		int x;cin >> x;
		heap[i] = x;//插入尾部
		up(i);// 上调
	}
	for(int i = 1; i <= n; ++i){
		cout << heap[i] << " ";
	}
}

int main()
{
	ios::sync_with_stdio(0);
//	int TT;cin>>TT;while(TT--)
	work();
	return 0;
}

L2-012 关于堆的判断 (25 分)
思路:
手写堆
题解
code:

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define mem(x, d) memset(x, d, sizeof(x))
#define eps 1e-6
using namespace std;
const int maxn = 1e5 + 9;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m;
int heap[maxn];
map <int, int> id;// 权值映射为堆里的编号

void up(int i){
	if(i == 1) return;
	while(i != 1){
		if(heap[i] < heap[i / 2]) swap(heap[i], heap[i / 2]);
		else break;
		i /= 2;
	}
}
void work()
{
	cin >> n >> m;
	for(int i = 1; i <= n; ++i){
		int x;cin >> x;
		heap[i] = x;
		up(i);
	}
	for(int i = 1; i <= n; ++i)	id[heap[i]] = i;
	while(m--){
		int x, y;cin >> x;
		string s;cin >> s;
		if(s[0] == 'a'){
			cin >> y >> s >> s;
			if(id[x] / 2 == id[y] / 2) cout << "T\n";
			else cout << "F\n";
		}
		else{
			cin >> s;
			if(s[0] == 'a'){
				cin >> s >> s >> y;
				if(id[y] == id[x] / 2) cout << "T\n";
				else cout << "F\n";
			}
			else{
				cin >> s;
				if(s[0] == 'r'){
					if(id[x] == 1) cout << "T\n";
					else cout << "F\n";
				}
				else{
					cin >> s >> y;
					if(id[x] == id[y] / 2) cout << "T\n";
					else cout << "F\n";
				}
			}
		}
	}
}

int main()
{
	ios::sync_with_stdio(0);
//	int TT;cin>>TT;while(TT--)
	work();
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值