二叉树 概念+代码

 树


空树和非空树

树是一个递归的定义,根结点除外剩余的部分都可以看作为一棵树。

子树之间是互不相交的

内部节点:除了树根和子叶节点

树根是第一层(不统一,不同书的描述不同。)

 

树的存储

  • 顺序存储
  1. 双亲表示法           优点:找双亲方便                缺点:找孩子不容易
  2. 孩子表示法           优点:找孩子方便                缺点:树的节点最大度 为开辟的空间,很浪费空间。  找双亲不方便
  3. 双亲孩子表示法     优点:找孩子和双亲方便       缺点:耗费空间
  • 链式存储
  1. 孩子链表表示法      把孩子放在头节点后面  类似于链式前向星表示
  2. 孩子兄弟表示法      左指针长子 右指针兄弟        根据孩子兄弟表示法把任何树都可以转化为二叉树(相互转化)

 森林把每颗树树根看成兄弟

 

二叉树 


 

用处比较多

每一层是上一层的2倍

任何一颗二叉树,叶子节点数为n0,度数为2的节点为n2,n0=n2+1

n=n0+n1+n2总节点数,节点数等于分支数加一;n=1*n1+2*n2+1;

1*n1+2*n2+1 = n0+n1+n2  故,得到n0=n2+1

 

二叉树存储

  • 顺序存储:
  1. 补零补成完全二叉树,然后句可以按顺序存储。        缺点   补零可能太多。
  2. 完全二叉树  可以 顺序存储
  3. l[]数组 和 r[]数组    必须指明根root节点   经常用
  • 链式存储:
  1. lchild  data  rchild 

 

二叉树遍历

先序遍历:左右         递归

中序遍历:左右         递归

后序遍历:左右根         递归

层次遍历:一层一层访问(同一层从左向右)     方法:队列         出队的同时孩子进去

 

已知先序和中序、后序和中序要得到另外一个序列其实拆解都是中序序列。

空就结束,不操作。

 

 

 

题目一:补空创建二叉树

输入:补空序列 创建二叉树

 1 #include <iostream>
 2 #include <queue>
 3 
 4 using namespace std;
 5 
 6 // 定义二叉树存储结构
 7 struct Bonde{
 8     char data;
 9     struct Bonde *lchild, *rchild;
10 };
11 typedef struct Bonde *Btree;
12 typedef struct Bonde Bonde;  // 给看结构体起的别名
13 
14 // 创建二叉树函数
15 void Createtree(Btree &T)
16 {
17     // 按先序次序输入二叉树中结点的值(一个字符,创建二叉链表表示的二叉树T)
18     char ch;
19     cin >> ch;
20     if(ch == '#')
21         T = NULL;    //递归结束,建空树
22     else{
23         T = new Bonde;
24         T->data = ch;     // 生成根结点
25         Createtree(T->lchild);   //  递归创建做子树
26         Createtree(T->rchild);   //  递归创建右子树
27     }
28 }
29 
30 int Depth(Btree T){  // 求二叉树的深度
31     int m, n;
32     if(T == NULL)  // 如果为空树,c深度为0
33         return 0;
34     else{
35         m = Depth(T->lchild);  // 递归计算左子树深度
36         n = Depth(T->rchild);  // 递归计算右子树深度
37         if(m>n)
38             return m+1;  // 返回左右子树最大值加1
39         else
40             return n+1;
41     }
42 }
43 
44 int main(){
45     Btree mytree;
46     cout << "按先序次序输入二叉树中国结点的值(孩子为空是输入#),创建一颗二叉树" << endl;
47     // ABD##E##CF#G###
48     Createtree(mytree);  // 创建二叉树
49     cout << endl;
50     cout << "二叉树的深度为:" << Depth(mytree) << endl;
51     return 0;
52 }
View Code

 

ABD##E##CF#G###
按先序次序输入二叉树中国结点的值(孩子为空是输入#),创建一颗二叉树

二叉树的深度为:4
Program ended with exit code: 0

 

 题目二:二叉树遍历     前序、中序、后序、层次遍历

 1 #include <iostream>
 2 #include <queue>
 3 using namespace std;
 4 
 5 struct Bonde{
 6     char data;
 7     struct Bonde *lchild, *rchild;
 8 };
 9 
10 typedef struct Bonde Bonde;
11 typedef struct Bonde *Btree;
12 
13 void Createtree(Btree &T){
14     char ch;
15     cin >> ch;
16     if(ch == '#')
17         T = NULL;
18     else{
19         T = new Bonde;
20         T->data = ch;
21         Createtree(T->lchild);
22         Createtree(T->rchild);
23     }
24 }
25 
26 void preorder(Btree T){  // 先序遍历
27     if(T){
28         cout << T->data << " ";
29         preorder(T->lchild);
30         preorder(T->rchild);
31     }
32 }
33 
34 void inorder(Btree T){  // 中序遍历
35     if (T) {
36         inorder(T->lchild);
37         cout << T->data << " ";
38         inorder(T->rchild);
39     }
40 }
41 
42 void posorder(Btree T){  // 后序遍历
43     if (T) {
44         posorder(T->lchild);
45         posorder(T->rchild);
46         cout << T->data << " ";
47     }
48 }
49 
50 // 只有通过指针才能调用左右孩子
51 bool Leveltraverse(Btree T){  // 层次遍历
52     Btree p;
53     if(!T)
54         return false;
55     queue<Btree> Q;  // 创建一个普通队列(先进先出),里面存放指针类型
56     Q.push(T);  // 根指针入队
57     while (!Q.empty()) {
58         p = Q.front();  // 取出对头元素作为当前扩展节点livenode
59         Q.pop();  // 队头元素出队
60         cout << p->data << " ";
61         if(p->lchild)
62             Q.push(p->lchild);   // 左孩子入队
63         if(p->rchild)
64             Q.push(p->rchild);   // 右孩子入队
65     }
66     return true;
67 }
68 
69 
70 int main(){
71     Btree mytree;
72     cout << "按先序层次输入二叉树中结点的值(孩子为空时输入#),创建一颗二叉树" << endl;
73     Createtree(mytree);  // 创建二叉树
74     cout << endl;
75     cout << "二叉树的先序遍历结果:" << endl;
76     preorder(mytree); // 先序遍历二叉树
77     cout << endl;
78     cout << "二叉树的中序遍历结果:" << endl;
79     inorder(mytree);  // 中序遍历二叉树
80     cout << endl;
81     cout << "二叉树的后序遍历结果:" << endl;
82     posorder(mytree); // 后序遍历二叉树
83     cout << endl;
84     cout << "二叉树的层次遍历结果:" << endl;
85     Leveltraverse(mytree); // 层次遍历二叉树
86     return 0;
87 }
View Code

 

按先序层次输入二叉树中结点的值(孩子为空时输入#),创建一颗二叉树
ABD##E##CF#G###

二叉树的先序遍历结果:
A B D E C F G 
二叉树的中序遍历结果:
D B E A F G C 
二叉树的后序遍历结果:
D E B G F C A 
二叉树的层次遍历结果:
A B C D E F G 
Program ended with exit code:
0

 

 

 题目三:二叉树还原  先序和中序得二叉树     后序和中序得二叉树

思路:

  1. 先序找根
  2. 中序分左右

 函数(先序序列开始位置, 中序序列开始位置, 序列长度)

  1 #include <iostream>
  2 using namespace std;
  3 
  4 typedef struct node{
  5     char data;
  6     struct node *lchild, *rchild;
  7 }BiTNode, *BiTree;
  8 
  9 // 也就是说BitNode是struct的别名,BiTree是struct的指针,指针只是指向地址对象的,不能用来创建对象,而BitNode是可以用来创建对象实体的
 10 
 11 BiTree pre_mid_createBiTree(char *pre, char *mid, int len){   // 前序中序还原建立二叉树
 12     if(len == 0)
 13         return NULL;
 14     char ch = pre[0];  // 找打先序序列中的第一个结点
 15     int index = 0;
 16     while(mid[index]!=ch){  // 在中序中
 17         index++;
 18     }
 19     BiTree T = new BiTNode; // 创建根节点
 20     T->data = ch;
 21     T->lchild = pre_mid_createBiTree(pre+1, mid, index);  // 建立右子树
 22     T->rchild = pre_mid_createBiTree(pre+index+1, mid+index+1, len-index-1);   // 建立右子树
 23     return T;
 24 }
 25 
 26 BiTree pro_mid_createBiTree(char *last, char *mid, int len){   // 后序中序还原二叉树
 27     if(len==0)
 28         return 0;
 29     char ch = last[len-1];  // 取到后序遍历顺序中最后一个结点
 30     int index = 0;  // 在中序序列中找根节点,并用index记录长度
 31     while (mid[index]!=ch)// 在中序序列中找根节点,左边边为该节点的左子树,右边为右子树
 32         index++;
 33     BiTree T = new BiTNode;  // 创建根结点
 34     T->data= ch;
 35     T->lchild = pro_mid_createBiTree(last, mid, index);  // 建立左子树
 36     T->rchild = pro_mid_createBiTree(last+index, mid+index+1, len-index-1);  // 建立右子树
 37     return T;
 38 }
 39 
 40 void pre_order(BiTree T){
 41     if(T){
 42         cout << T->data;
 43         pre_order(T->lchild);
 44         pre_order(T->rchild);
 45     }
 46 }
 47 
 48 void pro_order(BiTree T){
 49     if(T){
 50         pro_order(T->lchild);
 51         pro_order(T->rchild);
 52         cout << T->data;
 53     }
 54 }
 55 /*
 56  7
 57  A B D E C F G
 58  D B E A F G C
 59  D E B G F C A
 60  */
 61 int main(){
 62     BiTree T;
 63     int n;
 64     char pre[100], mid[100], last[100];
 65     cout << "1.前序中序还原二叉树\n";
 66     cout << "2.后序中序b还原二叉树\n";
 67     int choose = -1;
 68     while (choose!=0) {
 69         cout << "请选择:";
 70         cin >> choose;
 71         
 72         switch (choose) {
 73             case 1:
 74                 cout << "请输入节点的个数:" << endl;
 75                 cin >> n;
 76                 cout << "请输入前序序列:" << endl;
 77                 for(int i=0; i<n; i++)
 78                     cin >> pre[i];
 79                 cout << "请输入中序序列:" << endl;
 80                 for(int i=0; i<n; i++)
 81                     cin >> mid[i];
 82                 T = pre_mid_createBiTree(pre, mid, n);
 83                 cout << endl;
 84                 cout << "二叉树还原成功,输出其后序序列:" << endl;
 85                 pro_order(T);
 86                 cout << endl << endl;
 87                 break;
 88             case 2:
 89                 cout << "请输入节点的个数:" << endl;
 90                 cin >> n;
 91                 cout << "请输入后序序列:" << endl;
 92                 for(int i=0; i<n; i++)
 93                     cin >> last[i];
 94                 cout << "请输入中序序列:" << endl;
 95                 for(int i=0; i<n; i++)
 96                     cin >> mid[i];
 97                 T = pro_mid_createBiTree(last, mid, n);
 98                 cout << endl;
 99                 cout << "二叉树还原成功,输出其先序序列:" << endl;
100                 pre_order(T);
101                 cout << endl << endl;
102                 break;
103         }
104     }
105     return 0;
106 }
View Code

 

1.前序中序还原二叉树
2.后序中序b还原二叉树
请选择:1
请输入节点的个数:
7
请输入前序序列:
 A B D E C F G
请输入中序序列:
D B E A F G C

二叉树还原成功,输出其后序序列:
DEBGFCA

 

 

 题目四:二叉树的  叶子数  结点数

 

 1 #include <iostream>
 2 using namespace std;
 3 
 4 typedef struct Bnode{
 5     char data;
 6     struct Bnode *lchild, * rchild;
 7 }Bnode, *Btree;
 8 
 9 void Createtree(Btree &T){  // 引用传递 需要对T的进行修改的时候使用Btree &T, 不需要修改时候使用Btree T
10     char ch;
11     cin >> ch;
12     if(ch == '#')
13         T = NULL;
14     else
15     {
16         T = new Bnode;
17         T->data = ch;
18         Createtree(T->lchild);
19         Createtree(T->rchild);
20     }
21 }
22 
23 int NodeCount(Btree T){
24     // 求二叉树的结点个数
25     if(T == NULL)
26         return 0;
27     else
28         return NodeCount(T->lchild)+NodeCount(T->rchild)+1;  // 递归计算左右子树结点数之和
29 }
30 
31 int LeafCount(Btree T){
32     if(T == NULL)
33         return 0;
34     else
35         if(T->lchild==NULL && T->rchild==NULL)  // 左右子树均为空为子叶节点,则叶子数为1
36             return 1;
37         else
38             return LeafCount(T->lchild)+LeafCount(T->rchild); // 递归计算左右子树叶子节点之和
39 }
40 
41 int main(){
42     Btree mytree;
43     cout << "按先序输入二叉树结点的值(孩子为空时输入#),创建一颗二叉树" << endl;
44     // AB##E##CF#G###
45     Createtree(mytree);
46     cout << endl;
47     cout << "二叉树结点是为:" << NodeCount(mytree) << endl;
48     cout << "二叉树叶子数为:" << LeafCount(mytree) << endl;
49     return 0;
50 }
View Code

 

posted @ 2019-08-25 15:57  JCcodeblogs  阅读(677)  评论(0编辑  收藏  举报