数据结构--二叉树--洛谷

1.题目:【深基16.例1】淘汰赛

1.1 问题解决

  • 我的思路:用顺序表储存,逐层遍历并记录胜出者,直到顺序表只剩两个元素。比较输出
  • 奇思妙想:顺序表一分为二,两边分别诞生一个冠军与亚军,排序并比较即可
#include <bits/stdc++.h>
using namespace std;

bool cmp(const pair<int, int> &a, const pair<int, int> & b){
	return a.first < b.first;
}

int main() {
	//input 
	int n;
	cin >> n;
	n = 1 << n;
	
	vector<pair<int, int> > q(n);
	int x;
	for(int i = 0; i < n; i++){
		cin >> x;
		q[i] = make_pair(x, i);
	}

	//operator
	
	sort(q.begin(), n / 2 + q.begin(), cmp);
	sort(n/2 + q.begin(), q.end(), cmp);
	
	//ouput 
	cout << (q[q.size() / 2 - 1] > q.back() ? q.back().second : q[q.size() / 2 - 1].second) + 1 << endl;
	
    return 0;
}

1.2 意外收获

  • sort()函数对数对排序
  1. 对pair<int, int>元素排序

bool cmp(const pair<int, int> &a, const pair<int, int> & b){
	return a.first < b.first;
}

sort(n/2 + q.begin(), q.end(), cmp);  
  1. 对结构体元素排序
struct Q{
	int id;
	int value;
}; 

bool cmp(Q a, Q b){
	return a.value < b.value;
}

sort(q, q + n / 2, cmp);	//[0, n / 2)排序   

2. 二叉树深度

2.1 问题解决

  • 我的思路

错误:用顺序表记录深度,下标代表节点,在读入时记录深度数据。
读入的二叉树不完整时深度数据错乱

  • 正解

建立二叉树,遍历

#include <bits/stdc++.h>
using namespace std;

struct Node{
	int l;
	int r;
};
Node t[1000001];

int dfs(int n){
	if(n == 0)	return 0;
	
	int l = t[n].l;
	int r = t[n].r;
	return max(dfs(l), dfs(r)) + 1;
}

int main() {
	//input 
	int x, l, r, n;
	cin >> n;
	
	t[0].l = t[0].r = 0;
	for(int i = 1; i <= n; i++){
		cin >> t[i].l >> t[i].r;
	}
	
	//operator
	int ans = dfs(1);
	
	//ouput 
	cout << ans << endl;
	
    return 0;
}  

2.2 意外收获

3 美国血统 American Heritage

3.1 问题解决

  • 参考的题解解决的
#include <bits/stdc++.h>
using namespace std;

void solve(string pre, string in){
	if(pre.empty())	return;
	
	char root = pre[0];

	int k = in.find(root);
	
	
	pre.erase(pre.begin());
	
	string leftPre = pre.substr(0, k);
	
	string rightPre = pre.substr(k);
	
	string leftIn = in.substr(0, k);
	
	string rightIn = in.substr(k + 1);
	
	solve(leftPre, leftIn);
	
	solve(rightPre, rightIn);
	
	cout << root;
} 

int main() {
	//input 
	string in, pre;
	cin >> in >> pre;

	//operator
	solve(pre, in);
	
	//ouput 

	
    return 0;
}

3.2 收获

  • string操作
    string pre, in; 
	
	char root = pre[0];

	int k = in.find(root);
	//root是字符,返回第一次出现的下标 
	
	pre.erase(pre.begin());
	//pre.erase(a)   删除指针a处元素
	//pre.erase(start, end) 删除指针[start, end)范围元素 
	//pre.erase(a, n)  删除从指针a开始的n个元素 
	
	string leftPre = pre.substr(0, k);  //返回[0, k) 字符串 
	
	string rightPre = pre.substr(k);	//返回[k, pre.size() )字符串   

4 普通二叉树(简化版)

4.1 问题解决

  • 我的思路:用multiset容器做数据结构(有序、可重复),遍历解决
#include <bits/stdc++.h>
using namespace std;

int main() {
	//input 
	multiset<int> s;
	s.insert(-2147483647);
	s.insert(2147483647);
	int n, x, a;
	cin >> n;
	//operator
	while(n--){
		int num = 0;
		cin >> x >> a;
		multiset<int>::iterator k = s.begin();
		switch(x){
			case 1:{
				
				for(; *k < a; k++, num++);
				
				cout << num << endl;
				break;
			}
			case 2:{
				
				for(; num != a; k++, num++);
				
				cout << *k << endl;
				
				break;
			}
			case 3:{
				
				for(; *k < a; k++, num++);
				cout << *--k << endl;
				
				break;
			}
			case 4:{
				k = upper_bound(s.begin(), s.end(), a);
				cout << *k << endl;
				
				break;
			}
			case 5:{
				s.insert(a);	
				break;
			}
		}
	}
	
	//ouput 

	
    return 0;
}

4.2 收获

5 医院设置

5.1 问题解决

  • 通过Floyed算法记录每两个节点最短路径,然后遍历计算
#include <bits/stdc++.h>
using namespace std;

int main() {
	//init
	int n;
	cin >> n;
	int g[n+1][n+1];
	int w[n+1];
	for(int i = 0; i <= n; i++)	{
		for(int j = 0; j <= n; j++){
			//
			g[i][j] = 1e9;
		}
	}
		
	//input 
	int sum, l , r;
	for(int i = 1; i <= n; i++){
		cin >> w[i] >> l >> r;
		g[i][i] = 0;
		if(l)	g[i][l] = g[l][i] = 1;
		if(r)	g[i][r] = g[r][i] = 1;
	}
	
	//operator
	for(int k = 1; k <= n; k++){
		for(int i = 1; i<= n; i++){
			for(int j = 1; j<= n; j++){
				if(i != j && j != k && i != k && g[i][k] + g[k][j] < g[i][j]){
					g[i][j] = g[i][k] + g[k][j];
				}
			}
		}
	}

	int ans = 1e9;
	for(int i = 1; i <= n; i++){
		int tem = 0;
		for(int j = 1; j <= n; j++){
			tem += w[j] * g[i][j];
//			cout << "tem- " << i << " :" << tem << ' ';
		}
//		cout << endl;
		ans = min(tem, ans);
	}
	
	//ouput 
	cout << ans << endl;
	
    return 0;
}

5.2 收获

  • 图的遍历——Floyed.

6 遍历问题

6.1 问题解决

  • 根据前序遍历与后序遍历找出中序遍历可能的个数,关键在于找到单子叶节点个数n, 中序遍历可能的个数为2n.
#include <bits/stdc++.h>
using namespace std;

int main() {
	//init
	string str1,str2;
	int ans = 0;
	//input 
	cin >> str1 >> str2;
	//operator
	for(int i = 0; i < str1.size()-1; i++){
		string tem = str1.substr(i, 2);
		reverse(tem.begin(), tem.end());
		if(str2.find(tem) != string::npos)	ans++;
	}
	
	//ouput 
	cout << (1 << ans) << endl;
	
    return 0;
}

6.2 收获

  • 前序遍历与后序遍历为什么不能确定中序遍历的原因。

7 新二叉树

7.1 问题解决

  • 使用map容器储存
#include <bits/stdc++.h>
using namespace std;

int n;
map<char, pair<char, char> > t;
char m, l, r;
char root;

void out(char m){
	if(m == '*')	return;
	
	cout << m;
	out(t[m].first);
	out(t[m].second);
}

int main() {
	
	cin >> n;
	
	for(int i = 0; i < n; i++){
		cin >> m >> l >> r;
		t[m] = make_pair(l, r);
		
//		cout << t[m].first << ' ' << t[m].second << endl;
		if(i == 0)	root = m;
	}
//	cout << "root:" << root << endl;
	out(root);
	
	
    return 0;
}

8. 二叉树问题

  • 简单想法是建树、遍历
#include <bits/stdc++.h>
using namespace std;

struct Node{
	int v, l, r, f, visited;
	int deep;
	
	Node():v(0),l(0),r(0),f(0),visited(0),deep(1){
	}
}trees[101];


void add(int f, int c){
	if(!trees[f].l)	{
		trees[f].l = c;
	}
	else {
		trees[f].r = c;	
	}
	trees[c].v = c;
	trees[c].f = f;
}

int Deep(){
	int max_deep = 0;
	
	queue<Node> q;
	q.push(trees[1]);
	while(!q.empty()){
		Node tem = q.front();
		max_deep = max(max_deep, tem.deep);
		q.pop();
		if(tem.l){
			trees[tem.l].deep += tem.deep;
			q.push(trees[tem.l]);
		}
		if(tem.r){
			trees[tem.r].deep += tem.deep;
			q.push(trees[tem.r]);
		}
	}
	
	return max_deep;
}

int Width(){
	int width[101] = {0};
	
	queue<Node> q;
	q.push(trees[1]);
	while(!q.empty()){
		Node tem = q.front();
		q.pop();
		width[tem.deep]++;
		if(tem.l)	q.push(trees[tem.l]);
		if(tem.r)	q.push(trees[tem.r]);
	}
	
	return *max_element(width, width + 101);
}

int Length(int x, int y){
	int l[101] = {1};
	l[x] = 0;
	
	queue<Node> q;
	q.push(trees[x]);
	while(!q.empty()){
		Node tem = q.front(); q.pop();
		trees[tem.v].visited = 1;
		
//		cout << "v:" << tem.v;
		
		if(tem.v == y){
//			cout << "v:" << tem.v << " y:" << y << endl;
			return l[tem.v];
		}
		
		if(tem.l && !trees[tem.l].visited){
			l[tem.l] = l[tem.v] + 1;
			q.push(trees[tem.l]);
//			cout << " l:" << tem.l << " length:" << l[tem.l];
		}
		if(tem.r && !trees[tem.r].visited){
			l[tem.r] = l[tem.v] + 1;
			q.push(trees[tem.r]);
//			cout << " r:" << tem.r << " length:" << l[tem.r];
		}
		if(tem.f && !trees[tem.f].visited){
			l[tem.f] = l[tem.v] + 2;
			q.push(trees[tem.f]);
//			cout << " f:" << tem.f << " length:" << l[tem.f];
		}
//		cout << endl;
	}
}

int main(){
	//initiate
	trees[1].v = 1;
	int n;
	cin >> n;
	n--;
	while(n--){
		
		int f, c;
		
		cin >> f >> c;
		
		add(f, c);
	}
	int x, y;
	cin >> x >> y;
	
	//operator
	int deep = Deep();
	
	int width = Width();
	
	int length = Length(x, y);
	
	cout << deep << endl << width << endl << length << endl;
	return 0;
}   
  • 参考别人算法,用图与FLOYED算法实现
#include <bits/stdc++.h>
using namespace std;

#define Max(a, b) ((a) < (b) ? (b) : (a))
#define Min(a, b) ((a) < (b) ? (a) : (b))

int a[101][101];
int b[1000]; 

int main(){
	int n, x, y;
	cin >> n;
	int size = n;
	//初始值是无穷大 
	for(int i = 1; i <= n; i++){
		for(int j = 1; j<= n; j++){
			if(i!=j)	a[i][j] = 10000;
		}
	}
	
	size--;
	while(size--){
		cin >> x >> y;
		a[x][y] = 1;
		a[y][x] = 2;
	}
	cin >> x >> y;
	
	for(int k = 1; k <= n; k++){
		for(int i = 1; i <= n; i++){
			for(int j = 1; j <= n; j++){
				a[i][j] = Min(a[i][j], a[i][k] + a[k][j]);
			}
		}
	}
	
	int deep = 0;
	for(int  i = 2; i <= n; i++){
		deep = Max(deep, a[1][i]);
		b[a[1][i]]++;
	}
	
	cout << deep + 1 << endl << *max_element(b, b + 1000) << endl << a[x][y] << endl;
	
	return 0;
}   
  • 收获

konw more about bfs(traverse),

posted @ 2024-11-11 10:21  luvmis  阅读(72)  评论(0)    收藏  举报