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

    二叉树的定义:

      是一颗空树或者具有以下性质

      1.结点最多只有两个孩子,且有左右之分。不能交换左右孩子

      2.结点点的左子树和右子树也是二叉树。

    例图

            

    二叉树的基本形态:

    二叉树中的术语:

      1).结点度:节点所拥有的字数的个数成为该节点的度,在二叉树中度的取值只能是0,1,2.

      2).叶节点:度为0的节点成为叶结点或终端结点。

      3).左孩子、右孩子、双亲:树中一个结点的子树的根结点称为这个结点的孩子。这个结点称为它孩子结点的双亲。具有同一个双亲的孩子结点互称为兄弟。

      4).路径、路径长度:如果一棵树的一串结点n1,n2,…,nk有如下关系:结点ni是ni+1的父结点(1≤i<k),就把n1,n2,…,nk称为一条由n1至nk的路径。这条路径的长度是k-1。

      5).结点的层数:规定树的根结点的层数为1,其余结点的层数等于它的双亲结点的层数加1。

      6).树的深度:树中所有结点的最大层数称为树的深度。

      7).满二叉树。 在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子结点都在同一层上,这样的一棵二叉树称作满二叉树。

      8).完全二叉树。一棵深度为k的有n个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为i(1≤i≤n)的结点与满二叉树中编号为 i的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。完全二叉树的特点是:叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左 部。

    二叉树的性质:

      1).非空二叉树叶子结点数等于度为2的结点数加1,即N0=N2+1.(其中N0和N2分别是叶结点和度为2结点的个数)。

      2).非空二叉树第K层上最多有 2^(k - 1)个结点(K>= 1).

      3).高度为H的节点,最多有2^H - 1个节点(H >= 1).

    二叉树的基本操作:

      /*以下为二叉树的常用操作(如有错误之处还望之处)

      采用二叉链表的存储结构*/

    1 typedef struct BiTNode    //二叉树的节点
    2 {
    3     DataType m_Value;
    4     BiTNode *m_pLeft;
    5     BiTNode *m_pRight;
    6 }BiTNode;

      //创建二叉树(先序)

     1 //创建二叉树(先序)
     2 void createBiTree(BiTNode * &pCurrent)
     3 {
     4     cout << "先序输入节点:";
     5     DataType value;
     6     cin >> value ;
     7     if(value == '#')
     8         pCurrent = NULL;
     9     else
    10     {
    11         pCurrent = (BiTNode *)malloc(sizeof(BiTNode));
    12         pCurrent->m_Value = value;
    13         createBiTree(pCurrent->m_pLeft);
    14         createBiTree(pCurrent->m_pRight);
    15     }
    16 }

      //递归实现前序遍历二叉树

    1 void preOrderVisitUseRecur(const BiTNode * pCurrent)
    2 {
    3     if(pCurrent)
    4     {
    5         cout << pCurrent->m_Value << " ";
    6         preOrderVisitUseRecur(pCurrent->m_pLeft);
    7         preOrderVisitUseRecur(pCurrent->m_pRight);
    8     }
    9 }

      //用栈,不用递归实现前序排列

     1 void preOrderVisitUseStack(const BiTNode * pCurrent)
     2 {
     3     stack<const BiTNode *> pNodeStack;
     4     const BiTNode *p = pCurrent;
     5     while(p||!pNodeStack.empty())
     6     {
     7         if(p)                                        //如果该节点不是NULL
     8         {
     9             cout << pCurrent->m_Value << " ";        //访问节点的值
    10             pNodeStack.push(p);                        //将节点压栈
    11             p = p->m_pLeft;
    12         }
    13         else
    14         {
    15             //如果该节点是NULL
    16             p = pNodeStack.top();    //获取栈顶元素
    17             pNodeStack.pop();        //删除栈顶元素
    18             p = p->m_pRight;        //访问右节点
    19         }
    20 
    21     }
    22 }

      //递归实现中序遍历

    1 void inOrderVisitUseRecur(const BiTNode * pCurrent)
    2 {
    3     if(pCurrent)
    4     {
    5         inOrderVisitUseRecur(pCurrent->m_pLeft);
    6         cout << pCurrent->m_Value << " ";
    7         inOrderVisitUseRecur(pCurrent->m_pRight);
    8     }
    9 }

      //用栈实现中序遍历

     1 void inOrderVisitUseStack(const BiTNode * pCurrent)
     2 {
     3     stack<const BiTNode *> pNodeStack;
     4     const BiTNode * p = pCurrent;
     5     while(p||!pNodeStack.empty())
     6     {
     7         if(p)                        //如果该节点不是NULL
     8         {
     9             pNodeStack.push(p);        //将节点压栈
    10             p = p->m_pLeft;
    11         }
    12         else
    13         {
    14             //如果该节点是NULL
    15             p = pNodeStack.top();                    //获取栈顶元素
    16             pNodeStack.pop();                        //删除栈顶元素
    17             cout << pCurrent->m_Value << " ";        //访问节点的值
    18             p = p->m_pRight;                        //访问右节点
    19         }
    20     }
    21 }

      //递归实现后序遍历

    1 void afterOrderVisitUseRecur(const BiTNode * pCurrent)
    2 {
    3     if(pCurrent)
    4     {
    5         afterOrderVisitUseRecur(pCurrent->m_pLeft);
    6         afterOrderVisitUseRecur(pCurrent->m_pRight);
    7         cout << pCurrent->m_Value << " ";
    8     }
    9 }

      //用栈实现后序遍历

     1 void afterOrderVisitUseStack(const BiTNode * pCurrent)
     2 {
     3     stack<const BiTNode *> pNodeStack1;
     4     stack<const BiTNode *> pNodeStack2;
     5     const BiTNode * p =pCurrent;
     6     while(p||!pNodeStack1.empty())
     7     {
     8         if(p)                        //如果该节点不是NULL
     9         {
    10             pNodeStack1.push(p);        //将节点压栈
    11             pNodeStack2.push(p);        //将节点压栈
    12             p = p->m_pRight;
    13         }
    14         else
    15         {
    16             //如果该节点是NULL
    17             p = pNodeStack1.top();    //获取栈顶元素
    18             pNodeStack1.pop();        //删除栈顶元素
    19             p = p->m_pLeft;            //访问左节点
    20         }
    21     }
    22     p = NULL;
    23     while(!pNodeStack2.empty())
    24     {
    25         p = pNodeStack2.top();    //获取栈顶元素
    26         pNodeStack2.pop();        //删除栈顶元素
    27         cout << pCurrent->m_Value << " ";
    28     }
    29 }

      //按层次进行遍历(有点小问题)

     1 /*
     2 void levelOrderVisit(const BiTNode *pCurrent)
     3 {
     4     deque<const BiTNode *> pNodedeue;
     5     const BiTNode * p = NULL;
     6     if(pCurrent)
     7     {
     8         pNodedeue.push_back(pCurrent);    //第一次将节点放到队列
     9     }
    10     while(!pNodedeue.empty()||p)
    11     {
    12         p = *pNodedeue.begin();        //返回队列首元素,但不删除
    13         pNodedeue.pop_front();        //删除队首元素
    14         if(p)
    15         {
    16             cout << p->m_Value;
    17             if(p->m_pLeft)
    18                 pNodedeue.push_back(p);        //左孩子不空则进入队列
    19             if(p->m_pRight)
    20                 pNodedeue.push_back(p);        //右孩子不空则进入队列
    21         }
    22     }
    23 }
    24 */

      //计算树的深度

     1 int getTreeDepth(const BiTNode * pCurrent)
     2 {
     3     int leftDepth = 0,rightDepth = 0;
     4     if(!pCurrent)
     5     {
     6         //空的话返回0
     7         return 0;
     8     }
     9     else
    10     {
    11         leftDepth =  getTreeDepth(pCurrent->m_pLeft);    //获得左子树的高度
    12         rightDepth =  getTreeDepth(pCurrent->m_pRight);    //获得右子树的高度
    13         return (leftDepth>rightDepth?leftDepth:rightDepth) + 1;
    14     }
    15 }

      //计算树节点的个数

     1 int coutTreeNodeNums(const BiTNode *pCurrent)
     2 {
     3     int leftNums,rightNums;
     4     if(!pCurrent)
     5     {
     6         return 0;
     7     }
     8     else
     9     {
    10         leftNums  =  coutTreeNodeNums(pCurrent->m_pLeft);
    11         rightNums =  coutTreeNodeNums(pCurrent->m_pRight);
    12     }
    13     return leftNums + rightNums + 1;
    14 }

      //以下是各操作的实例

     1 int main()
     2  {
     3      BiTNode * root = NULL;
     4      cout << "start to create a tree:" << endl;
     5      createBiTree(root);
     6      cout << "visit a tree use 递归先序:" << endl;
     7      preOrderVisitUseRecur(root);
     8      cout << endl;
     9      cout << "visit a tree use 栈先序:" << endl;
    10      preOrderVisitUseStack(root);
    11      cout << endl;
    12      cout << "visit a tree use 递归中序:" << endl;
    13      inOrderVisitUseRecur(root);
    14      cout << endl;
    15      cout << "visit a tree use 栈中序:" << endl;
    16      inOrderVisitUseStack(root);
    17      cout << endl;
    18      cout << "visit a tree use 递归后序:" << endl;
    19      afterOrderVisitUseRecur(root);
    20      cout << endl;
    21      cout << "visit a tree use 栈后序:" << endl;
    22      afterOrderVisitUseStack(root);
    23      cout << endl;
    24      //cout << "层次遍历:" << endl;
    25      //levelOrderVisit(root);
    26      cout << "树中节点的个数:" << coutTreeNodeNums(root)  << endl;
    27      cout << "树的深度为:"   << getTreeDepth(root) << endl;
    28      return 0;
    29 }
  • 相关阅读:
    bootstrap 新手入门(一)【我是新手,请指正】
    zend studio 安装+汉化
    tp总结
    tp论坛 第三节 板块模板的建立和完善(二)
    tp论坛 分页(三)
    tp写一个微型论坛 (一)
    thinkphp第四节 模型与CURD
    thinkphp 第二节
    angular5中的自定义指令(属性指令)
    列表生成式和生成器生成式
  • 原文地址:https://www.cnblogs.com/zhuwbox/p/3632802.html
Copyright © 2011-2022 走看看