树之详解
记住:递归一定有出口,有结束条件
基操
求二叉树的高度
思路:
分析二叉树的深度(高度)和它的左、右子树深度之间的关系。从二叉树深度的定义可知,二叉树的深度应为其左、右子树深度的最大值加1。由此,需先分别求得左、右子树的深度,算法中“访问结点”的操作为:求得左、右子树深度的最大值,然后加 1
int GetHeight( BinTree BT )
{
int l=0,r=0;
if(!BT)
return 0;
else
{
l=GetHeight(BT->Left);
r=GetHeight(BT->Right);
return (l>=r?l:r)+1; //假想一下,当左子树不为NULL 右子树为NULL返回给l 接收自然是1.
}
}
二叉树的四种遍历
void InorderTraversal( BinTree BT )
{
if(BT==NULL) return ;
InorderTraversal(BT->Left);
printf(" %c",BT->Data);
InorderTraversal(BT->Right);
}
void PreorderTraversal( BinTree BT )
{
if(BT==NULL) return ;
printf(" %c",BT->Data);
PreorderTraversal(BT->Left);
PreorderTraversal(BT->Right);
}
void PostorderTraversal( BinTree BT )
{
if(BT==NULL) return ;
PostorderTraversal(BT->Left);
PostorderTraversal(BT->Right);
printf(" %c",BT->Data);
}
void LevelorderTraversal( BinTree BT )
{
BinTree a[100],temp;
int head=0,rear=0;
if(BT)
{
a[rear++]=BT;
while(head-rear)
{
temp=a[head++];
printf(" %c",temp->Data);
if(temp->Left) a[rear++]=temp->Left;
if(temp->Right) a[rear++]=temp->Right;
}
}
}
完全二叉树
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lW5lLtHX-1645454020566)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\image-20211004155456855.png)]
满二叉树
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hW1iIEsU-1645454020567)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\image-20211004155504924.png)]
7-5 完全二叉搜索树 (20 分)
一个无重复的非负整数序列,必定对应唯一的一棵形状为完全二叉树的二叉搜索树。本题就要求你输出这棵树的层序遍历序列。
输入格式:
首先第一行给出一个正整数 N(≤1000),随后第二行给出 N 个不重复的非负整数。数字间以空格分隔,所有数字不超过 2000。
输出格式:
在一行中输出这棵树的层序遍历序列。数字间以 1 个空格分隔,行首尾不得有多余空格。
输入样例:
10
1 2 3 4 5 6 7 8 9 0
输出样例:
6 3 8 1 5 7 9 0 2 4
题目分析:
1 一颗完全二叉树的中序遍历对应着从小到达的数列
2 将数组从小到大排序
3 将排序好的数组根据中序遍历构造完全二叉树
4 层序输出二叉树 即从1到N
代码:
//在完全二叉树里,一个结点i的左儿子坐标必为2*i 右儿子的坐标必为2*i+1
#include<bits/stdc++.h>
using namespace std;
int n;
const int N = 10001;
int a[N];
int pos[N];
int cnt=1;
bool cmp(int a,int b)
{
return a<b;
}
void Bulidtree(int index)
{
if(index*2<=n)Bulidtree(index*2); //遍历左子树
pos[index]=a[cnt++]; //遍历节点
if(index*2+1<=n)Bulidtree(index*2+1); //遍历右子树
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+n+1,cmp);
Bulidtree(1);
for(int i=1;i<=n;i++)
{
if(i!=1)
cout<<" "<<pos[i];
else cout<<pos[i];
}
}
二叉搜索树的建立和查找
结构体:
struct BinaryTree_Node
{
int key; // 节点的键。本例中,节点的值部分等于键 。
BinaryTree_Node* lChild; // 左子节点
BinaryTree_Node* rChild; // 右子节点
// 节点的构造函数
BinaryTree_Node(int v) : key(v), lChild(NULL), rChild(NULL)
{
}BYk
};
typedef BinaryTree_Node* BT_Node;
建立函数:
//二叉搜索树 左小右大
void Create_BinaryTree(BT_Node &node, int key)
{
if (node == NULL) // 节点为空,插入之
{
node = new BinaryTree_Node(key);
return;
}
if (key < node->key) //比节点的值小,插在左子树
Create_BinaryTree(node->lChild, key); // 插入到左子树中
else //比节点的值大 插在右子树
Create_BinaryTree(node->rChild, key); // 插入到右子树中
return;
}
7-7 建立二叉搜索树并查找父结点 (20 分)
按输入顺序建立二叉搜索树,并搜索某一结点,输出其父结点。
输入格式:
输入有三行: 第一行是n值,表示有n个结点; 第二行有n个整数,分别代表n个结点的数据值; 第三行是x,表示要搜索值为x的结点的父结点。
输出格式:
输出值为x的结点的父结点的值。 若值为x的结点不存在,则输出:It does not exist. 若值为x的结点是根结点,则输出:It doesn’t have parent.
输入样例:
2
20
30
20
输出样例:
It doesn't have parent.
代码:
#include<bits/stdc++.h>
using namespace std;
struct BinaryTree_node
{
int data;
BinaryTree_node *lchild;
BinaryTree_node *rchild;
BinaryTree_node(int key): data(key), lchild(NULL) ,rchild(NULL)
{
}
};
typedef BinaryTree_node* BT_node;
void Create_BinaryTree(BT_node &node,int data)
{
//注意这个& &可以取地址,会给改变主函数中root的值 如果不加则不改变
if(node==NULL)
{
node = new BinaryTree_node(data); //构造函数 创建新节点
return;
}
if(data<node->data)
Create_BinaryTree(node->lchild,data);
else
Create_BinaryTree(node->rchild,data);
return ;
}
void search_Root(BT_node parent,BT_node node,int data)// parent 记录父节点
{
if(node==NULL)
{
cout<<"It does not exist."<<endl;
return ;
}
if(node->data==data)
{
cout<<parent->data<<endl;
return ;
}
else if(node->data>data)
return search_Root(node,node->lchild,data);
else
return search_Root(node,node->rchild,data);
}
int main()
{
BT_node root =NULL; //创建根节点
int n,data;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>data;
Create_BinaryTree(root,data);
}
int x;
cin>>x;
if(root==NULL) //根节点为空,即根本没有数据
{
cout<<"It does not exist."<<endl;
return 0;
}
if(root->data==x)
{
cout<<"It doesn't have parent."<<endl;
return 0;
}
search_Root(NULL,root,x);
}
根据中序后序遍历建立二叉树
思路:
1 在中序中找到与后序最后一个值相同的坐标
2 根据那个坐标一分为左右子树,并确定左右子树的后序遍历界限
L2-006 树的遍历 (25 分)
给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。
输入格式:
输入第一行给出一个正整数N(≤30),是二叉树中结点的个数。第二行给出其后序遍历序列。第三行给出其中序遍历序列。数字间以空格分隔。
输出格式:
在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。
输入样例:
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
输出样例:
4 1 6 3 5 7 2
代码:
1 先根据后序遍历和中序遍历建立二叉树
2 使用BFS 层序遍历二叉树
#include<bits/stdc++.h>
using namespace std;
const int N = 10001;
int mid[N];
int final[N];
int n;
struct BitTree
{
int data;
BitTree* lchild;
BitTree* rchild;
};
typedef BitTree* Bit;
Bit Create(int l1,int r1,int l2,int r2)//l1,r1 为中序的界限,l2,r2为后序的界限,自己画一下找坐标填进去
{
if(l1>r1||l2>r2)
return NULL;
Bit root =new BitTree;
root->data=final[r2];
root->lchild=NULL;
root->rchild=NULL;
int i;
for(i=0;i<n;i++)
{
if(mid[i]==final[r2])break;
}
//num 记录根节点的左边有多少个节点
int num= i-l1;
root->lchild=Create(l1,i-1,l2,l2+num-1);//注意Create第四个参数必须是l2+num-1;
root->rchild=Create(i+1,r1,l2+num,r2-1);
return root;
}
void layershow(Bit root)
{
queue<Bit>que;
que.push(root);
cout<<root->data;
while(que.size())
{
Bit node =que.front();
que.pop();
if(node->lchild)
{
que.push(node->lchild);
cout<<" "<<node->lchild->data;
}
if(node->rchild)
{
que.push(node->rchild);
cout<<" "<<node->rchild->data;
}
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
cin>>final[i];
for(int i=0;i<n;i++)
cin>>mid[i];
Bit root = new BitTree;
root=Create(0,n-1,0,n-1);
layershow(root);
}
根据前序中序 输出后序遍历
#include<bits/stdc++.h>
using namespace std;
const int N =10001;
int first[N];
int mid[N];
int n;
struct BitTree
{
int data;
BitTree* lchild;
BitTree* rchild;
};
typedef BitTree* Bit;
Bit Create(int l1,int r1,int l2,int r2)
{
if(l1>r1||l2>r2)
return NULL;
Bit root =new BitTree;
root->data=first[l2];
root->lchild=NULL;
root->rchild=NULL;
int i;
for(i=0;i<n;i++)
{
if(first[l2]==mid[i])break;
}
int num=i-l1;
root->lchild=Create(l1,i-1,l2+1,l2+num);
root->rchild=Create(i+1,r1,l2+num+1,r2);
return root;
}
void post(Bit root)
{
if(root==NULL)return ;
post(root->lchild);
post(root->rchild);
cout<<root->data<<" ";
}
void layershow(Bit root)
{
queue<Bit>que;
que.push(root);
cout<<root->data;
while(que.size())
{
Bit node =que.front();
que.pop();
if(node->lchild)
{
que.push(node->lchild);
cout<<" "<<node->lchild->data;
}
if(node->rchild)
{
que.push(node->rchild);
cout<<" "<<node->rchild->data;
}
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
cin>>mid[i];
for(int i=0;i<n;i++)
cin>>first[i];
Bit root = new BitTree;
root=Create(0,n-1,0,n-1);
layershow(root);
cout<<endl;
post(root);
}
L2-011 玩转二叉树 (25 分)
给定一棵二叉树的中序遍历和前序遍历,请你先将树做个镜面反转,再输出反转后的层序遍历的序列。所谓镜面反转,是指将所有非叶结点的左右孩子对换。这里假设键值都是互不相等的正整数。
输入格式:
输入第一行给出一个正整数N
(≤30),是二叉树中结点的个数。第二行给出其中序遍历序列。第三行给出其前序遍历序列。数字间以空格分隔。
输出格式:
在一行中输出该树反转后的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。
输入样例:
7
1 2 3 4 5 6 7
4 1 3 2 6 5 7
输出样例:
4 6 1 7 5 3 2
反转后的层序遍历,只要把右子树的输出放在左子树前面就好了
代码:
#include<bits/stdc++.h>
using namespace std;
const int N =10001;
int first[N];
int mid[N];
int n;
struct BitTree
{
int data;
BitTree* lchild;
BitTree* rchild;
};
typedef BitTree* Bit;
Bit Create(int l1,int r1,int l2,int r2)
{
if(l1>r1||l2>r2)
return NULL;
Bit root =new BitTree;
root->data=first[l2];
root->lchild=NULL;
root->rchild=NULL;
int i;
for(i=0;i<n;i++)
{
if(first[l2]==mid[i])break;
}
int num=i-l1;
root->lchild=Create(l1,i-1,l2+1,l2+num);
root->rchild=Create(i+1,r1,l2+num+1,r2);
return root;
}
void post(Bit root)
{
if(root==NULL)return ;
post(root->lchild);
post(root->rchild);
cout<<root->data<<" ";
}
void layershow(Bit root)
{
queue<Bit>que;
que.push(root);
cout<<root->data;
while(que.size())
{
Bit node =que.front();
que.pop();
if(node->rchild)
{
que.push(node->rchild);
cout<<" "<<node->rchild->data;
}
if(node->lchild)
{
que.push(node->lchild);
cout<<" "<<node->lchild->data;
}
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
cin>>mid[i];
for(int i=0;i<n;i++)
cin>>first[i];
Bit root = new BitTree;
root=Create(0,n-1,0,n-1);
layershow(root);
}
7-23 还原二叉树 (25 分)
给定一棵二叉树的先序遍历序列和中序遍历序列,要求计算该二叉树的高度。
输入格式:
输入首先给出正整数N(≤50),为树中结点总数。下面两行先后给出先序和中序遍历序列,均是长度为N的不包含重复英文字母(区别大小写)的字符串。
输出格式:
输出为一个整数,即该二叉树的高度。
输入样例:
9
ABDFGHIEC
FDHGIBEAC
输出样例:
5
代码:
#include<bits/stdc++.h>
using namespace std;
struct BitTree
{
char data;
BitTree* lchild;
BitTree* rchild;
};
typedef BitTree* Bit;
int n;
const int N = 1001;
char pre[N];
char mid[N];
Bit BulidTree(int l1,int r1,int l2,int r2)
{
if(l1>r1||l2>r2) return NULL;
Bit root =new BitTree;
root->data=pre[l2];
root->lchild=NULL,root->rchild=NULL;
int i;
for(i=0;i<n;i++)
if(pre[l2]==mid[i])break;
int cnt = i-l1;
root->lchild=BulidTree(l1,i-1,l2+1,l2+cnt);
root->rchild=BulidTree(i+1,r1,l2+cnt+1,r2);
return root;
}
int Gethight(Bit root)
{
if(root==NULL) return 0;
int l=Gethight(root->lchild);
int r=Gethight(root->rchild);
return (l>=r?l:r)+1;
}
int main()
{
cin>>n;
getchar();
for(int i=0;i<n;i++)
cin>>pre[i];
getchar();
for(int i=0;i<n;i++)
cin>>mid[i];
Bit root =new BitTree;
root = BulidTree(0,n-1,0,n-1);
cout<<Gethight(root);
}