(有任何问题欢迎留言或私聊
本文目的旨在给初学二叉树的朋友提供一个借鉴的模板:一个是指针版本,一个非指针版本。
在文末推荐几道经典例题、我的题解和经典博客,供大家学习。
已经了解二叉树的同学可以直接去看最下面的一些经典题目。点击左侧目录即可。
二叉树的很多相关定义在百度百科或者他人CSDN博客上都有,建议先看一下。
引入:
一个二叉树如下:
前序遍历: ABDHIEJCFG
中序遍历: HDIBJEAFCG
后序遍历: HIDJEBFGCA
层序遍历: ABCDEFGHIJ
特点:
1. 前序遍历中,根节点在第一位;后序遍历中,根节点在最后一位;
2. 中序遍历中,根节点的左右子树分别在根节点位置两边;
非指针版本:
//DFS遍历二叉树
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1005;
const int INF = 0x3f3f3f3f;
const LL mod = 1000000007;
const double eps = 1e-8;
struct BinaryTree{
int val;
int l;
int r;
BinaryTree(){val=0;l=r=-1;}
}tree[N];
int ar[N],ans[N],n,tot,t;
int pre[N],jing[N];
//递归建树,k为当前建树已经跑到了输入序列数组的第几号元素
void build(int k){
if(k>n)return;
tree[++tot].val=ar[k];
tree[tot].l=tree[tot].r=-1;
int i=1;//从根节点往下分析此节点的位置情况
while(1){
if(ar[k]<tree[i].val){//比此节点的值小,就往左跑
if(tree[i].l!=-1){
i=tree[i].l;
}else{//如果此节点没有左儿子,就让k号元素当它左儿子,break
tree[i].l=tot;
break;
}
}else {//反之往右跑
if(tree[i].r!=-1){
i=tree[i].r;
}else{
tree[i].r=tot;
break;
}
}
}
build(k+1);
return;
}
//二叉搜索树前序遍历的序列
void get_pre(int k){
pre[++t]=tree[k].val;
if(tree[k].l!=-1)get_pre(tree[k].l);
if(tree[k].r!=-1)get_pre(tree[k].r);
return;
}
//镜像二叉搜索树前序遍历的序列
void get_jing(int k){
jing[++t]=tree[k].val;
if(tree[k].r!=-1)get_jing(tree[k].r);
if(tree[k].l!=-1)get_jing(tree[k].l);
return;
}
//二叉搜索树中序遍历的结果
void get_mid(int k){
if(tree[k].l!=-1)get_mid(tree[k].l);
ans[++t]=tree[k].val;
if(tree[k].r!=-1)get_mid(tree[k].r);
}
//镜像二叉搜索树中序遍历的结果
void get_mid2(int k){
if(tree[k].r!=-1)get_mid2(tree[k].r);
ans[++t]=tree[k].val;
if(tree[k].l!=-1)get_mid2(tree[k].l);
}
//二叉搜索树后序遍历的结果
void get_la(int k){
if(tree[k].l!=-1)get_la(tree[k].l);
if(tree[k].r!=-1)get_la(tree[k].r);
ans[++t]=tree[k].val;
}
//镜像二叉树后序遍历的结果
void get_la2(int k){
if(tree[k].r!=-1)get_la2(tree[k].r);
if(tree[k].l!=-1)get_la2(tree[k].l);
ans[++t]=tree[k].val;
}
void output(){
for(int i=1;i<=n;++i){
if(i==n)printf("%d\n",ans[i]);
else printf("%d ",ans[i]);
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d",&ar[i]);
}
tot=1;
tree[1].val=ar[1];
tree[1].l=tree[1].r=-1;
build(2);
t=0;
get_pre(1);
t=0;
get_jing(1);
return 0;
}
指针版本:
//由后序遍历和中序遍历获取层序遍历-BFS
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1005;
const int INF = 0x3f3f3f3f;
const LL mod = 1000000007;
const double eps = 1e-8;
typedef struct BinaryTree {
int val;
BinaryTree* left;
BinaryTree* right;
BinaryTree(){}
BinaryTree(int data)
: val(data), left(nullptr), right(nullptr) {}
}*tree;
int n;
int post[N],mid[N],pre[N];
tree build(int k,int *mid,int *post,int inl,int inr){
int i,j;
if(k<=0)return nullptr;
if(inl>inr)return nullptr;
tree p;
p=new BinaryTree;
p->left=p->right=nullptr;
p->val=post[k-1];
for(i=0;i<n;++i){
if(mid[i]==post[k-1])break;
}
for(j=0;j<n;++j){
//printf("j=%d\n",j);
//j=0;
if(*mid==mid[j])break;
}
int l=i-j;
p->left=build(l,mid,post,inl,inl+l-1);
p->right=build(k-l-1,mid+l+1,post+l,inl+l+1,inr);
return p;
}
void bfs(tree head){
queue<tree>Q;
while(!Q.empty())Q.pop();
Q.push(head);
int s=0;
while(!Q.empty()){
tree u=Q.front();Q.pop();
pre[s++]=u->val;
if(u->left!=nullptr)Q.push(u->left);
if(u->right!=nullptr)Q.push(u->right);
}
for(int i=0;i<s;++i){
if(i==s-1)printf("%d\n",pre[i]);
else printf("%d ",pre[i]);
}
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;++i){
scanf("%d",&post[i]);
}
for(int i=0;i<n;++i){
scanf("%d",&mid[i]);
}
tree root=new BinaryTree;
root->left=root->right=nullptr;
root=build(n,mid,post,0,n-1);
bfs(root);
return 0;
}
例题:
二叉树:PATL2-004. 这是二叉搜索树吗?
树的遍历:PATL2-006. 树的遍历
二叉树:PATL2-011. 玩转二叉树
完全二叉树:PATL3-010. 是否完全二叉搜索树
层序遍历例题:数据结构实验之二叉树五:层序遍历