二叉树
二叉树是什么?
二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个节点最多只能有两棵子树,且有左右之分。
二叉树是n个有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成,是有序树。当集合为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称作一个节点。
二叉树的定义
二叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的。对于二叉树,有深度遍历和广度遍历,深度遍历有前序、中序以及后序三种遍历方法,广度遍历即我们平常所说的层次遍历。因为树的定义本身就是递归定义,因此采用递归的方法去实现树的三种遍历不仅容易理解而且代码很简洁,而对于广度遍历来说,需要其他数据结构的支撑,比如堆了。所以,对于一段代码来说,可读性有时候要比代码本身的效率要重要的多。
二叉树的遍历
四种主要的遍历思想为:
前序遍历:根结点 —> 左子树 —> 右子树
中序遍历:左子树—> 根结点 —> 右子树
后序遍历:左子树 —> 右子树 —> 根结点
层次遍历:只需按层次遍历即可
例如,求下面二叉树的各种遍历
前序遍历:1 2 4 5 7 8 3 6
中序遍历:4 2 7 5 8 1 3 6
后序遍历:4 7 8 5 2 6 3 1
层次遍历:1 2 3 4 5 6 7 8
二叉树的应用
【深基16.例1】淘汰赛
题目描述
有 2 n ( n ≤ 7 ) 2^n(n\le7) 2n(n≤7) 个国家参加世界杯决赛圈且进入淘汰赛环节。已经知道各个国家的能力值,且都不相等。能力值高的国家和能力值低的国家踢比赛时高者获胜。1 号国家和 2 号国家踢一场比赛,胜者晋级。3 号国家和 4 号国家也踢一场,胜者晋级……晋级后的国家用相同的方法继续完成赛程,直到决出冠军。给出各个国家的能力值,请问亚军是哪个国家?
输入格式
第一行一个整数 n n n,表示一共 2 n 2^n 2n 个国家参赛。
第二行 2 n 2^n 2n 个整数,第 i i i 个整数表示编号为 i i i 的国家的能力值( 1 ≤ i ≤ 2 n 1\leq i \leq 2^n 1≤i≤2n)。
数据保证不存在平局。
输出格式
仅一个整数,表示亚军国家的编号。
样例 #1
样例输入 #1
3
4 2 3 1 10 5 9 7
样例输出 #1
1
本题可以不使用递归的方法实现
#include<bits/stdc++.h>
using namespace std;
int b, s, g;
int main() {
int n, shu[150],jihao1=0,jihao2=0;
cin >> n;
int he = pow(2, n);
int max1=0, max2=0;
for (int i = 1; i <= he/2 ; i++) {
cin >> shu[i];
if (max1 < shu[i]) {
jihao1 = i;
}
max1 = max(max1, shu[i]);
}
for (int i = he/2+1; i <= he; i++) {
cin >> shu[i];
if (max2 < shu[i]) {
jihao2 = i;
}
max2 = max(max2, shu[i]);
}
if (max1 > max2) {
cout << jihao2;
}
else {
cout << jihao1;
}
return 0;
}
使用二叉树递归
#include<bits/stdc++.h>
using namespace std;
struct jiegouti{ //结构体
int power,id;
};
jiegouti maxt(jiegouti a,jiegouti b){ //返回两个结构体里能力值更大的那个
return a.power>b.power?a:b;
}
jiegouti mint(jiegouti a,jiegouti b){ //返回两个结构体里能力值更大的那个
return a.power<b.power?a:b;
}
jiegouti a[150],tree[600]; //a——数据,tree——线段树(一般为了防爆,线段树都是开数组的4倍空间)
void build(int node,int start,int end){ //建树函数
if(start==end){ //叶节点,返回
tree[node]=a[start];
return;
}
int lnode=node*2; //左右子树、中点
int rnode=node*2+1;
int mid=(start+end)/2;
build(lnode,start,mid); //两边递归建树
build(rnode,mid+1,end);
tree[node]=maxt(tree[lnode],tree[rnode]) //父节点是左右子节点里更大的;
}
int main(){
int n; //输入
cin>>n;
for(int i=1;i<=(1<<n);i++){ //1<<n就是2的n次方啦!(这样比pow函数更快哦!)
cin>>a[i].power; //输入,赋值,很简单
a[i].id=i;
}
build(1,1,(1<<n)); //建树(根节点是1,整棵树从1到2的n次方)
cout<<mint(tree[2],tree[3]).id; //从tree[2],tree[3]里找个小的就是亚军,输出它的序号
return 0;
}