数据结构--二叉树--洛谷
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()函数对数对排序
- 对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);
- 对结构体元素排序
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),

浙公网安备 33010602011771号