1.树:
a.简介:树是由结点及连结结点的边组成。有根树的节点之间有父子关系。
2.二叉树:
a.简介:如果一颗树有1个根结点及所有结点的子结点数都不超过2,那么此树被称为有根二叉树。
b.二叉树可以递归地进行定义。
2.普通二叉树:
a.表达:
3.树的遍历:
a.三种遍历方式
前序遍历:根 左 右
中序遍历:左 根 右
后序遍历:左 右 根
是以根的位置定的顺序
b.注意的点:当用递归实现遍历算法时,如果树的结点数量大并且分布不均,很可能导致递归深度过深
c.代码:
a.题目:根据树的先序遍历和中序遍历的结果,生成此树按后序遍历得到的结果
b.分析:可以在遍历先序遍历结果的同时,依次根据中序遍历得到树的左右子树
c.代码:
a.简介:树是由结点及连结结点的边组成。有根树的节点之间有父子关系。
2.二叉树:
a.简介:如果一颗树有1个根结点及所有结点的子结点数都不超过2,那么此树被称为有根二叉树。
b.二叉树可以递归地进行定义。
c.代码:二叉树的表达
//
// Created by 叶子 on 2018/2/2.
// 有根树的表达
//
#include "iostream"
using namespace std;
struct Node { int p ,l,r;};
const int NIL= -1;
Node T[100005],D[100005];
int n;
void print (int u){
int i,c;
cout << "node" << u << ":";
cout << "parent = " << T[u].p << ",";
cout << "depth = "<<D[u].p<<",";
if ( T[u].p == NIL) cout << "root,";
else if ( T[u].l == NIL) cout << "leaf,";
else cout << "internal ndoe,";
cout << "[";
for ( i = 0 , c = T[u].l ; c != NIL; i++,c = T[c].r){
if (i) cout << "," ;
cout <<c;
}
cout << "]" <<endl;
}
int rec(int u,int p){
D[u].p = p;
if ( T[u].r != NIL ) rec(T[u].r,p); //? 这一句不是很理解
if ( T[u].l != NIL ) rec(T[u].l,p+1);
}
int main(){
int i,j,d,v,c,l,r;
cin >> n;
for ( i = 0 ; i < n ; i ++) T[i].p = T[i].l = T[i].r = NIL;
for ( i = 0 ; i < n ; i ++){
cin >> v>> d;
for ( j = 0 ; j < d ; j ++){
cin >> c;
if ( j == 0 ) T[v].l = c;
else T[l].r = c;
l = c;
T[c].p = v;
}
}
for ( i = 0 ; i < n ; i ++){
if (T[i].p == NIL ) r = i ;
}
rec(r,0);
for ( i = 0 ; i < n ; i ++) print(i);
return 0 ;
}
2.普通二叉树:
a.表达:
//
// Created by 叶子 on 2018/2/2.
// 二叉树的表达
//
#include "cstdio"
const int MAX = 10000;
const int NIL = -1;
struct Node{ int parent,left,right;};
Node T[MAX];
int n,D[MAX],H[MAX];
void setDepth(int u,int d){
if ( u == NIL) return;
D[u] = d;
setDepth(T[u].left,d+1);
setDepth(T[u].right,d+1);
}
int setHeight(int u){
int h1 = 0 ,h2 = 0;
if (T[u].left != NIL){
h1 = setHeight(T[u].left ) + 1;
}
if ( T[u].right != NIL){
h2 = setHeight(T[u].right) + 1;
}
return H[u] = ( h1 > h2 ? h1 : h2);
}
int getSibling(int u){
if (T[u].parent == NIL) return NIL;
if ( T[T[u].parent].left != u && T[T[u].parent].left != NIL)
return T[T[u].parent].left;
if ( T[T[u].parent].right != u && T[T[u].parent].right != NIL)
return T[T[u].parent].right;
return NIL;
}
void print(int u){
printf("node %d:",u);
printf("parent = %d,",T[u].parent);
printf("sibling = %d,",getSibling(u));
int deg = 0;
if (T[u].left != NIL) deg ++;
if (T[u].right != NIL) deg ++;
printf ("degree = %d,",deg);
printf ("depth = %d,",D[u]);
printf ("height = %d,",H[u]);
if ( T[u].parent == NIL){
printf("root\n");
}else if ( T[u].left == NIL && T[u].right == NIL ){
printf("left\n");
}else{
printf("internal node\n");
}
}
int main(){
int v,l,r,root = 0 ;
scanf("%d",&n);
for ( int i = 0 ; i < n ; i ++ ) T[i].parent = NIL;
for ( int i = 0 ; i < n ; i ++){
scanf("%d %d %d",&v,&l,&r);
T[v].left = l;
T[v].right = r;
if ( l != NIL) T[l].parent = v;
if ( r != NIL) T[r].right = v;
}
for ( int i = 0 ; i < n ; i ++) if ( T[i].parent == NIL) root = i;
setDepth(root,0);
setHeight(root);
for ( int i = 0 ; i < n ; i ++) print(i);
return 0;
}
3.树的遍历:
a.三种遍历方式
前序遍历:根 左 右
中序遍历:左 根 右
后序遍历:左 右 根
是以根的位置定的顺序
b.注意的点:当用递归实现遍历算法时,如果树的结点数量大并且分布不均,很可能导致递归深度过深
c.代码:
//
// Created by 叶子 on 2018/2/4.
// 二叉树的遍历
//
#include "stdio.h"
const int MAX = 10000;
const int NIL = -1;
struct Node { int p,l,r;};
struct Node T[MAX];
int n;
//前序遍历
void preParse(int u){
if ( u == NIL) return;
printf(" %d",u);
preParse(T[u].l);
preParse(T[u].r);
}
//中序遍历
void inParse(int u){
if ( u== NIL) return;
inParse(T[u].l);
printf(" %d",u);
inParse(T[u].r);
}
//后序遍历
void postParse(int u){
if ( u == NIL) return;
postParse(T[u].l);
postParse(T[u].r);
printf(" %d",u);
}
int main(){
int i,v,l,r,root;
scanf("%d",&n);
for ( i = 0 ; i < n ; i ++){
T[i].p == NIL;
}
for ( i = 0 ; i < n ; i ++){
scanf("%d %d %d",&v,&l,&r);
T[v].l = l;
T[v].r = r;
if ( l != NIL) T[l].p = v;
if ( r != NIL) T[r].p = v;
}
for ( i = 0 ; i < n ; i ++) if ( T[i].p == NIL) root = i;
printf("Precorder\n");
preParse(root);
printf("\n");
printf("Inorder\n");
inParse(root);
printf("\n");
printf("Postorder\n");
postParse(root);
printf("\n");
return 0;
}
4.树的重建:
a.题目:根据树的先序遍历和中序遍历的结果,生成此树按后序遍历得到的结果
b.分析:可以在遍历先序遍历结果的同时,依次根据中序遍历得到树的左右子树
c.代码:
//
// Created by 叶子 on 2018/2/4.
// 根据树的先序遍历和中序遍历的结果得到后序遍历的结果
//
#include "iostream"
#include "vector"
using namespace std;
int n,pos;
vector<int> pre,in,post;
void rec(int l ,int r){
if ( l >= r) return;
int root = pre[pos++];
int m = distance(in.begin(),find(in.begin(),in.end(),root));
rec(l,m);
rec(m+1,r);
post.push_back(root);
}
void solve(){
pos = 0;
rec(0,pre.size());
for ( int i = 0 ; i < n ; i ++){
if ( i ) cout << " ";
cout << post[i];
}
cout << endl;
}
int main(){
int k;
cin >> n;
for ( int i = 0 ; i < n ; i ++){
cin >> k ;
pre.push_back(k);
}
for ( int i = 0 ; i < n ; i++){
cin >> k;
in.push_back(k);
}
solve();
return 0;
}