1. 程式人生 > >資料結構樹之二叉樹

資料結構樹之二叉樹

二叉樹的定義:

  是一顆空樹或者具有以下性質

  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 }