zoukankan      html  css  js  c++  java
  • 数据结构——二叉树

    树的一些基本术语(针对我个人觉得要必要列出来的

    • 结点的度:结点拥有的子树数。
    • 树的度:树内各结点度的最大值。
    • 非终端结点:度不为0的结点称为非终端结点或分支结点。除根结点外,非终端结点也称为内部结点。
    • 层次:根为第一层,不是第零层。
    • 树的深度:树中结点的最大层次,深度也称为高度。
    • 森林:是m(m>=0)棵互不相交的树的集合。对树中每个结点而言,其子树的集合即为森林。对森林加上一个根,森林即成为树;删去根,树即成为森林。

    二叉树的一些性质:

    1. 在二叉树的第i层上至多有2i-1个结点(i>=1)。
    2. 深度为k的二叉树至多有2k-1个结点(k>=1)。
    3. 在任意一棵二叉树中,若终端结点(叶子结点)的个数为n0,度为2的结点数为n2,则n0=n2+1
    4. 包含n个结点的二叉树的高度至少为log2 (n+1)
    5. 具有n个结点的完全二叉树的深度为
        
      (注:[ ]表示向下取整)

    二叉树的一些概念:

    • 满二叉树:深度为k且含有2k-1个结点的二叉树。(即除叶子结点外,所有结点都有左儿子和右儿子。
    • 完全二叉树:若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。

                          

          满二叉树     

     

              

          完全二叉树   

          

        非完全二叉树

     


    补充:

    根据遍历序列确定一棵二叉树:

      先序序列+中序序列   >>>

        先:根左右 → 第一个一定是根

        中:左根右 → 根据先序找到一个根后,把序列由根划分成左子树和右子树

        对左子树和右子树进行同样的操作,直到子树为空。(可见也是一种递归思想。

      中序序列+后序序列   >>>

        后:左右根 → 序列的最后一个为根

        中:左根右 → 根据后序找到一个根后,把序列由根划分成左子树和右子树

        对左子树和右子树进行同样的操作,直到子树为空。(递归

      先序加后序是无法确定一颗二叉树的,因为由上可见,中序由先序或后序提供的根来确定左右子树,没有中序是无法完成这个递归过程的,也就无法确定一颗二叉树。


    接下来就是二叉树的代码了,它实现了二叉树的基本存储结构和一些基本的操作:

      ps:这里注意一下先序遍历建立二叉树时的数据输入,要按根左右的顺序注意-1结束符的输入。

      例:1 2 3 -1 -1 4 5 -1 6 -1 -1 7 -1 -1 -1

      1 #include<iostream>
      2 #include<stdlib.h>
      3 #include<queue>        //层次遍历时要用到队列
      4 using namespace std;
      5 
      6 #define MAXSIZE 100
      7 typedef int ElemType;
      8 typedef int Status;
      9 
     10 //二叉链表存储表示
     11 typedef struct BiTNode
     12 {
     13     ElemType data;                        //结点数据域
     14     struct BiTNode *lchild, *rchild;    //左右孩子指针
     15 }BiTNode, *BiTree;
     16 
     17 //初始化,构造一个空树
     18 void InitBT(BiTree &T)
     19 {
     20     T = NULL;
     21 }
     22 
     23 //先序遍历建立二叉树
     24 void CreateBT(BiTree &T)
     25 {
     26     ElemType ch;
     27     cin >> ch;
     28     if (ch == -1)        //输入元素,以-1结束
     29         T = NULL;
     30     else
     31     {
     32         T = (BiTNode *)malloc(sizeof(BiTNode));        //分配内存空间
     33         T->data = ch;
     34         CreateBT(T->lchild);                        //递归建立其左子树
     35         CreateBT(T->rchild);                        //递归建立其右子树
     36     }
     37 }
     38 
     39 //检查二叉树是否为空,空返回1,非空返回0
     40 int EmptyBT(BiTree T)
     41 {
     42     if (T == NULL)
     43         return 1;
     44     else
     45         return 0;
     46 }
     47 
     48 //二叉树的深度
     49 int DepthBT(BiTree T)
     50 {
     51     if (T == NULL)    //空树深度为0
     52         return 0;
     53     else
     54     {
     55         int a = DepthBT(T->lchild);                //递归求左子树深度
     56         int b = DepthBT(T->rchild);                //递归求右子树深度
     57         return (a > b ? (a + 1) : (b + 1));        //取最大的即为树的深度,注意加1
     58     }
     59 }
     60 
     61 //查找二叉树BT中值为x的结点,若查找成功返回1,否则返回0
     62 int FindBT(BiTree T, ElemType x)
     63 {
     64     if (T == NULL)
     65         return 0;
     66     if (T->data == x)
     67         return 1;
     68     if (FindBT(T->lchild, x) || FindBT(T->rchild, x))    //递归在它的左子树和右子树里面找
     69         return 1;
     70     else
     71         return 0;
     72 }
     73 
     74 //先序遍历,根左右
     75 void  PreOrder(BiTree T)
     76 {
     77     if (T)    //树非空
     78     {
     79         cout << T->data << " ";
     80         PreOrder(T->lchild);
     81         PreOrder(T->rchild);
     82     }
     83 }
     84 
     85 //中序遍历,左根右
     86 void InOrder(BiTree T)
     87 {
     88     if (T)
     89     {
     90         InOrder(T->lchild);
     91         cout << T->data << " ";
     92         InOrder(T->rchild);
     93     }
     94 }
     95 
     96 //后序遍历,左右根
     97 void  PostOrder(BiTree T)
     98 {
     99     if (T)
    100     {
    101         InOrder(T->lchild);
    102         InOrder(T->rchild);
    103         cout << T->data << " ";
    104     }
    105 }
    106 
    107 //层次遍历
    108 void  LevelOrder(BiTree T)
    109 {
    110     BiTree p;
    111     if (T)
    112     {
    113         queue<BiTree>Q;        //创建一个队列Q
    114         Q.push(T);            //将树入队
    115         while (!Q.empty())    //队列非空
    116         {
    117             p = Q.front();
    118             Q.pop();
    119             cout << p->data << " ";
    120             if (p->lchild)        //先左子树出队
    121                 Q.push(p->lchild);
    122             if (p->rchild)        //后右子树出队
    123                 Q.push(p->rchild);
    124         }
    125     }
    126 }
    127 
    128 //叶子结点个数
    129 int  LeafCount(BiTree T)
    130 {
    131     if (!T)
    132         return 0;
    133     int count = 0;        //计数器
    134     if (!T->lchild && !T->rchild)        //左右子树都为空,则为一个叶子结点
    135     {
    136         count++;
    137     }
    138     int a = LeafCount(T->lchild);        //递归求其左子树叶子结点数
    139     int b = LeafCount(T->rchild);        //递归求其右子树叶子结点数
    140     count += (a + b);
    141     return count;
    142 }
    143 
    144 //总结点数
    145 int  NodeCount(BiTree T)
    146 {
    147     if (!T)
    148         return 0;
    149     else
    150         return NodeCount(T->lchild) + NodeCount(T->rchild) + 1;    //加一个根节点
    151 }
    152 
    153 //清除二叉树
    154 void ClearBTree(BiTree &T)
    155 {
    156     if (T)
    157     {
    158         ClearBTree(T->lchild);
    159         ClearBTree(T->rchild);
    160         delete T;
    161         T = NULL;
    162     }
    163 }
    164 
    165 int main()
    166 {
    167     BiTree T;
    168     int x;
    169 
    170     T = NULL;
    171 
    172     cout << "1.建立二叉树
    ";
    173 
    174     cout << "2.先序遍历二叉树
    ";
    175 
    176     cout << "3.中序遍历二叉树
    ";
    177 
    178     cout << "4.后序遍历二叉树
    ";
    179 
    180     cout << "5.层次遍历二叉树
    ";
    181 
    182     cout << "6.查找二叉树中元素
    ";
    183 
    184     cout << "7.计算二叉树的深度
    ";
    185 
    186     cout << "8.计算二叉树的叶子结点个数
    ";
    187 
    188     cout << "9.计算二叉树的结点总个数
    ";
    189 
    190     cout << "10.清除二叉树
    ";
    191 
    192     cout << "0.退出
    ";
    193 
    194     int choose = 0;
    195 
    196     while (choose != -1)
    197     {
    198         cout << "请选择你要执行的操作:";
    199         cin >> choose;
    200         switch (choose)
    201         {
    202         case 1:    //先序遍历建立二叉树
    203             cout << "请输入二叉树中元素,以-1结束:";
    204             CreateBT(T);
    205             cout << "二叉树建立成功!" << endl;
    206             break;
    207         case 2:    //先序遍历输出二叉树
    208             PreOrder(T);
    209             cout << endl;
    210             break;
    211         case 3:    //中序遍历输出二叉树
    212             InOrder(T);
    213             cout << endl;
    214             break;
    215         case 4:    //后序遍历输出二叉树
    216             PostOrder(T);
    217             cout << endl;
    218             break;
    219         case 5:    //层次遍历输出二叉树
    220             LevelOrder(T);
    221             cout << endl;
    222             break;
    223         case 6:    //查找二叉树中是否存在元素x
    224             cout << "请输入要查找的元素x:";
    225             cin >> x;
    226             if (FindBT(T, x))
    227                 cout << "查找成功!" << endl;
    228             else
    229                 cout << "查找失败!" << endl;
    230             break;
    231         case 7:    //二叉树深度
    232             cout << DepthBT(T) << endl;
    233             break;
    234         case 8:    //叶子结点数
    235             cout << LeafCount(T) << endl;
    236             break;
    237         case 9:    //总结点数
    238             cout << NodeCount(T) << endl;
    239             break;
    240         case 10://清除二叉树
    241             ClearBTree(T);
    242             cout << "清除成功!" << endl;
    243             break;
    244         case 0:    //退出
    245             exit(0);
    246             break;
    247         }
    248     }
    249     system("pause");
    250     return 0;
    251 }
  • 相关阅读:
    存储过程中执行动态Sql语句
    模拟alert和confirm
    SignalR
    Html5实践之EventSource
    Java路径操作具体解释
    HDU 1330 Nearest Common Ancestors(求两个点的近期公共祖先)
    Graph(2014辽宁ACM省赛)
    基于注解的Spring MVC整合Hibernate(所需jar包,spring和Hibernate整合配置,springMVC配置,重定向,批量删除)
    W5500问题集锦(二)
    Android Fragment 简单实例
  • 原文地址:https://www.cnblogs.com/friend-A/p/9110240.html
Copyright © 2011-2022 走看看