您的位置:首页 > 理论基础 > 数据结构算法

数据结构树之二叉树

2014-04-02 21:34 302 查看
本文转载于水目沾的博客,博客地址:http://www.cnblogs.com/zhuwbox/p/3632802.html

转载请注明原作者的博客地址

二叉树的定义:

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

  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).

4).具有n个节点的完全二叉树的深度为floor(log2(n))+1.

5).如果对一棵有n个节点的完全二叉树的节点按层序编号,则对任一结点i(1<=i<=n),有

(1)如果i=1,则结点i是二叉树的根,无双亲;如果i>1,则其双亲PARENT(i)是结点floor(i/2)。

(2)如果2i>n,则结点i无左孩子(结点i为叶子结点);否则其左孩子LCHILD(I)是结点2i。

(3)如果2i+1>n,则结点i无右孩子;否则其右孩子RCHILD(I)是结点2i+1。

二叉树的基本操作:

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

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

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


  //创建二叉树(先序)

1 //创建二叉树(先序)如果结点没有左右孩子,则用#标出
2 void createBiTree(BiTree &pCurrent)
3 {
4     cout << "先序输入节点:";
5     DataType value;
6     cin >> value ;
7     if(value == '#')
8         pCurrent = NULL;
9     else
10     {
11         pCurrent = new BiTree;
12         pCurrent->m_Value = value;
13         createBiTree(pCurrent->m_pLeft);
14         createBiTree(pCurrent->m_pRight);
15     }
16 }


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

1 void preOrderVisitUseRecur(const BiTree 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 BiTree pCurrent)
2 {
3     stack<const BiTNode *> pNodeStack;
4     BiTree 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 BiTree 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 BiTree pCurrent)
2 {
3     stack<const BiTNode *> pNodeStack;
4     BiTree 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 BiTree 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 BiTree pCurrent)
2 {
3     stack<const BiTree> pNodeStack1;
4     stack<const BiTree> pNodeStack2;
5     BiTree 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 BiTree pCurrent)
3 {
4     deque<const BiTree> pNodedeue;
5     BiTree 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 BiTree 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 BiTree 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      BiTree 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 }


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息