zoukankan      html  css  js  c++  java
  • 二叉树 概念+代码

     树


    空树和非空树

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

    子树之间是互不相交的

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

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

    树的存储

    • 顺序存储
    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.前序中序还原二叉树
    ";
     66     cout << "2.后序中序b还原二叉树
    ";
     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
  • 相关阅读:
    关于螺旋矩阵的问题
    JDK 1.5 for 循环的新写法
    Java基础视频笔记(三)
    关于接口的理解
    常用的DOS命令
    Java基础视频笔记(二)
    Eclipse的常用快捷键备忘
    Java基础视频笔记(四):泛型
    异常设计准则
    多重继承和虚继承的内存布局(转)
  • 原文地址:https://www.cnblogs.com/JCcodeblgos/p/11401423.html
Copyright © 2011-2022 走看看