1.Wikioi 1501 二叉树的最大高度和宽度
给出一个二叉树,输出它的最大宽度和高度。
第一行一个整数n。
下面n行每行有两个数,对于第i行的两个数,代表编号为i的节点所连接的两个左右儿子的编号。如果没有某个儿子为空,则为0。
输出共一行,输出二叉树的最大宽度和高度,用一个空格隔开。
5
2 3
4 5
0 0
0 0
0 0
2 3
n<16
默认第一个是根节点
以输入的次序为编号
2-N+1行指的是这个节点的左孩子和右孩子
注意:第二题有极端数据!
1
0 0
这题你们别想投机取巧了,给我老老实实搜索!
#include <stdio.h> #define MAXN 20 int width[MAXN]; //width[i]=第i层的宽度 struct Node { int v; Node *left; Node *right; }; void addTreeLeft(Node *root,int val) //addTreeLeft(树根指针,该节点的值) 创建新的左子树 { Node *newnode; newnode=new Node; newnode->v=val; newnode->left=NULL; newnode->right=NULL; root->left=newnode; return; } void addTreeRight(Node *root,int val) //addTreeRight(树根指针,该节点的值) 创建新的右子树 { Node *newnode; newnode=new Node; newnode->v=val; newnode->left=NULL; newnode->right=NULL; root->right=newnode; } Node *search(Node *root,int val) //在父节点root下寻找值为val的结点 { Node *result; result=NULL; if(root->v==val) return root; if(root->left!=NULL) { result=search(root->left,val); if(result!=NULL) return result; } if(root->right!=NULL) result=search(root->right,val); return result; } void getWidth(Node *root,int deep) //getWidth(父节点指针,该父节点深度) 获得该父节点向下的最大宽度 { width[deep]++; if(root->left!=NULL) getWidth(root->left,deep+1); if(root->right!=NULL) getWidth(root->right,deep+1); } int getHigh(Node *root) //获得父节点root下的最大高度 { int lHigh=0,rHigh=0,maxHigh=0; if(root->left!=NULL) maxHigh=getHigh(root->left); if(root->right!=NULL) rHigh=getHigh(root->right); if(rHigh>maxHigh) maxHigh=rHigh; return maxHigh+1; } void delTree(Node *root) //delTree(父节点指针) 删除该父节点及其左右儿子节点 { if(root->left!=NULL) delTree(root->left); if(root->right!=NULL) delTree(root->right); delete root; } int main() { int i,n,l,r,max=0; Node *root,*node; //创建树的根结点、输入数据时需要用的父节点 node=new Node; root=new Node; root->v=1; root->left=NULL; root->right=NULL; scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d%d",&l,&r); node=search(root,i); //查找编号为i的结点 if(l>0) addTreeLeft(node,l); //左子树不为空,就给编号为i的结点接上编号为l的儿子左结点 if(r>0) addTreeRight(node,r); //右子树不为空,就给编号为i的结点接上编号为r的儿子右结点 } getWidth(root,1); //获得各层最大宽度 int h=getHigh(root); //获得最大高度 for(i=1;i<=MAXN;i++) if(width[i]>max) max=width[i]; printf("%d %d\n",max,h); delTree(root); return 0; }
2.Wikioi 3143 二叉树的序遍历
求一棵二叉树的前序遍历,中序遍历和后序遍历
第一行一个整数n,表示这棵树的节点个数。
接下来n行每行2个整数L和R。第i行的两个整数Li和Ri代表编号为i的节点的左儿子编号和右儿子编号。
输出一共三行,分别为前序遍历,中序遍历和后序遍历。编号之间用空格隔开。
5
2 3
4 5
0 0
0 0
0 0
1 2 4 5 3
4 2 5 1 3
4 5 2 3 1
n <= 16
#include <stdio.h> struct Node { int v; Node *left; Node *right; }; void addTreeLeft(Node *root,int val) //创建父节点为root的值为val的左子树 { Node *newnode; newnode=new Node; newnode->right=NULL; newnode->left=NULL; newnode->v=val; root->left=newnode; } void addTreeRight(Node *root,int val) //创建父节点为root的值为val的左子树 { Node *newnode; newnode=new Node; newnode->right=NULL; newnode->left=NULL; newnode->v=val; root->right=newnode; } Node *search(Node *root,int val) { Node *result; result=NULL; if(root->v==val) return root; if(root->left!=NULL) //先搜索左子树 { result=search(root->left,val); if(result!=NULL) return result; } if(root->right!=NULL) //再搜索右子树 result=search(root->right,val); return result; } void delTree(Node *root) //删除根结点为root的子树,先删它的左右儿子子树,再删父节点 { if(root->left!=NULL) delTree(root->left); if(root->right!=NULL) delTree(root->right); delete root; } void firstPrint(Node *root)//前序遍历打印 { printf("%d ",root->v); if(root->left!=NULL) firstPrint(root->left); if(root->right!=NULL) firstPrint(root->right); } void midPrint(Node *root)//中序遍历打印 { if(root->left!=NULL) midPrint(root->left); printf("%d ",root->v); if(root->right!=NULL) midPrint(root->right); } void lastPrint(Node *root)//后序遍历打印 { if(root->left!=NULL) lastPrint(root->left); if(root->right!=NULL) lastPrint(root->right); printf("%d ",root->v); } int main() { int n,i,j,l,r; Node *root,*node; //创建树的根结点、输入数据时用到的结点 root=new Node; //树根初始化 root->v=1; root->left=NULL; root->right=NULL; scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d%d",&l,&r); node=search(root,i); //找到根结点下编号为i的结点 if(l>0) addTreeLeft(node,l); if(r>0) addTreeRight(node,r); } //先序、中序、后序遍历 firstPrint(root); printf("\n"); midPrint(root); printf("\n"); lastPrint(root); printf("\n"); return 0; }
下面是二叉树的几个重要模块接口:
1、二叉树的数据结构
struct Node { int v; //结点编号 Node *left; //左子树指针 Node *right; //右子树指针 };
2、二叉树结点的左子树创建
void addTreeLeft(Node *root,int val) //创建父节点为root的值为val的左子树 { Node *newnode; newnode=new Node; newnode->right=NULL; newnode->left=NULL; newnode->v=val; root->left=newnode; }
3、二叉树结点的右子树创建
void addTreeRight(Node *root,int val) //创建父节点为root的值为val的左子树 { Node *newnode; newnode=new Node; newnode->right=NULL; newnode->left=NULL; newnode->v=val; root->right=newnode; }
4、二叉树结点的查找
Node *search(Node *root,int val) { Node *result; result=NULL; if(root->v==val) return root; if(root->left!=NULL) //先搜索左子树 { result=search(root->left,val); if(result!=NULL) return result; } if(root->right!=NULL) //再搜索右子树 result=search(root->right,val); return result; }
5、二叉树的删除
void delTree(Node *root) //删除根结点为root的子树,先删它的左右儿子子树,再删父节点 { if(root->left!=NULL) delTree(root->left); if(root->right!=NULL) delTree(root->right); delete root; }
6、二叉树的先序、中序、后序遍历
void firstPrint(Node *root)//前序遍历打印 { printf("%d ",root->v); if(root->left!=NULL) firstPrint(root->left); if(root->right!=NULL) firstPrint(root->right); } void midPrint(Node *root)//中序遍历打印 { if(root->left!=NULL) midPrint(root->left); printf("%d ",root->v); if(root->right!=NULL) midPrint(root->right); } void lastPrint(Node *root)//后序遍历打印 { if(root->left!=NULL) lastPrint(root->left); if(root->right!=NULL) lastPrint(root->right); printf("%d ",root->v); }
二叉树的内容很多,应用灵活,是各类计算机竞赛中的重要考点,需要引起我们的重视