zoukankan      html  css  js  c++  java
  • 二叉树的操作

            先使用先序的方法建立一棵二叉树,然后分别使用递归与非递归的方法实现前序、中序、后序遍历二叉树,并使用了两种方法来进行层次遍历二叉树,一种方法就是使用STL中的queue,另外一种方法就是定义了一个数组队列,分别使用了front和rear两个数组的下标来表示入队与出队,还有两个操作就是求二叉树的深度、结点数。。。

    1. #include "iostream"  
    2. #include "queue"  
    3. #include "stack"  
    4. using namespace std;  
    5.   
    6. //二叉树结点的描述  
    7. typedef struct BiTNode  
    8. {  
    9.     char data;  
    10.     struct BiTNode *lchild, *rchild;      //左右孩子  
    11. }BiTNode,*BiTree;  
    12.   
    13. //按先序遍历创建二叉树  
    14. //BiTree *CreateBiTree()     //返回结点指针类型  
    15. //void CreateBiTree(BiTree &root)      //引用类型的参数  
    16. void CreateBiTree(BiTNode **root)    //二级指针作为函数参数  
    17. {  
    18.     char ch; //要插入的数据  
    19.     scanf("\n%c", &ch);  
    20.     //cin>>ch;  
    21.     if(ch=='#')  
    22.         *root = NULL;  
    23.     else  
    24.     {  
    25.         *root = (BiTNode *)malloc(sizeof(BiTNode));  
    26.         (*root)->data = ch;  
    27.         printf("请输入%c的左孩子:",ch);  
    28.         CreateBiTree(&((*root)->lchild));  
    29.         printf("请输入%c的右孩子:",ch);  
    30.         CreateBiTree(&((*root)->rchild));  
    31.     }  
    32. }  
    33.   
    34. //前序遍历的算法程序  
    35. void PreOrder(BiTNode *root)  
    36. {  
    37.     if(root==NULL)  
    38.         return ;  
    39.     printf("%c ", root->data); //输出数据  
    40.     PreOrder(root->lchild); //递归调用,前序遍历左子树  
    41.     PreOrder(root->rchild); //递归调用,前序遍历右子树  
    42. }  
    43.   
    44. //中序遍历的算法程序  
    45. void InOrder(BiTNode *root)  
    46. {  
    47.     if(root==NULL)  
    48.         return ;  
    49.     InOrder(root->lchild); //递归调用,前序遍历左子树  
    50.     printf("%c ", root->data); //输出数据  
    51.     InOrder(root->rchild); //递归调用,前序遍历右子树  
    52. }  
    53.   
    54. //后序遍历的算法程序  
    55. void PostOrder(BiTNode *root)  
    56. {  
    57.     if(root==NULL)  
    58.         return ;  
    59.     PostOrder(root->lchild); //递归调用,前序遍历左子树  
    60.     PostOrder(root->rchild); //递归调用,前序遍历右子树  
    61.     printf("%c ", root->data); //输出数据    
    62. }  
    63.   
    64. void PreOrder_Nonrecursive(BiTree T)  //先序遍历的非递归  
    65. {  
    66.     stack<BiTree> S;  
    67.     BiTree p;  
    68.     S.push(T);  //根指针进栈  
    69.     while(!S.empty())  //栈空时结束  
    70.     {  
    71.         while((p=S.top()) && p)  
    72.         {  
    73.             cout<<p->data<<"  ";  
    74.             S.push(p->lchild);  
    75.         }   //向左走到尽头  
    76.         S.pop();  //弹出堆栈  
    77.         if(!S.empty())  
    78.         {  
    79.             p=S.top();  
    80.             S.pop();  
    81.             S.push(p->rchild);    //向右走一步  
    82.         }  
    83.     }  
    84. }  
    85. void InOrderTraverse(BiTree T)   //中序遍历的非递归  
    86. {  
    87.     stack<BiTree> S;  
    88.     BiTree p;  
    89.     S.push(T);   //根指针进栈  
    90.     while(!S.empty())  
    91.     {  
    92.         while((p=S.top()) && p)  
    93.             S.push(p->lchild);    //向左走到尽头  
    94.         S.pop();    //空指针退栈  
    95.         if(!S.empty())  
    96.         {  
    97.             p=S.top();  
    98.             S.pop();  
    99.             cout<<p->data<<"  ";  
    100.             S.push(p->rchild);  
    101.         }  
    102.     }  
    103. }  
    104.   
    105. void PostOrder_Nonrecursive(BiTree T)  //后序遍历的非递归  
    106. {  
    107.     stack<BiTree> S;  
    108.     BiTree p=T,q=NULL;  
    109.     while(p!=NULL || !S.empty())  //栈空时结束  
    110.     {  
    111.         while(p!=NULL)  
    112.         {  
    113.             S.push(p);  
    114.             p=p->lchild;  
    115.         }  
    116.         p=S.top();  
    117.         if(p->rchild==NULL || p->rchild==q)  
    118.         {  
    119.             cout<<p->data<<"  ";  
    120.             q=S.top();  
    121.             S.pop();  
    122.             p=NULL;  
    123.         }  
    124.         else   
    125.             p=p->rchild;  
    126.     }  
    127. }  
    128. int visit(BiTree T)  
    129. {  
    130.     if(T)  
    131.     {  
    132.         printf("%c ",T->data);  
    133.         return 1;  
    134.     }  
    135.     else  
    136.         return 0;  
    137. }  
    138.   
    139. void LeverTraverse(BiTree T)   //方法一、非递归层次遍历二叉树   
    140. {  
    141.     queue <BiTree> Q;  
    142.     BiTree p;  
    143.     p = T;  
    144.     if(visit(p)==1)  
    145.         Q.push(p);  
    146.     while(!Q.empty())  
    147.     {  
    148.         p = Q.front();  
    149.         Q.pop();  
    150.         if(visit(p->lchild) == 1)   
    151.             Q.push(p->lchild);  
    152.         if(visit(p->rchild) == 1)  
    153.             Q.push(p->rchild);  
    154.     }  
    155. }  
    156. void LevelOrder(BiTree BT)     //方法二、非递归层次遍历二叉树   
    157. {  
    158.     BiTNode *queue[10];//定义队列有十个空间  
    159.     if (BT==NULL)  
    160.         return;  
    161.     int front,rear;  
    162.     front=rear=0;  
    163.     queue[rear++]=BT;  
    164.     while(front!=rear)//如果队尾指针不等于对头指针时  
    165.     {  
    166.         cout<<queue[front]->data<<"  ";  //输出遍历结果  
    167.         if(queue[front]->lchild!=NULL)  //将队首结点的左孩子指针入队列  
    168.         {  
    169.             queue[rear]=queue[front]->lchild;  
    170.             rear++;    //队尾指针后移一位  
    171.         }  
    172.         if(queue[front]->rchild!=NULL)  
    173.         {  
    174.             queue[rear]=queue[front]->rchild;    //将队首结点的右孩子指针入队列  
    175.             rear++;   //队尾指针后移一位  
    176.         }  
    177.         front++;    //对头指针后移一位  
    178.     }  
    179. }  
    180.   
    181. int depth(BiTNode *T)   //树的深度  
    182. {  
    183.     if(!T)  
    184.         return 0;  
    185.     int d1,d2;  
    186.     d1=depth(T->lchild);  
    187.     d2=depth(T->rchild);  
    188.     return (d1>d2?d1:d2)+1;  
    189.     //return (depth(T->lchild)>depth(T->rchild)?depth(T->lchild):depth(T->rchild))+1;  
    190. }  
    191. int CountNode(BiTNode *T)  
    192. {  
    193.     if(T == NULL)  
    194.         return 0;  
    195.     return 1+CountNode(T->lchild)+CountNode(T->rchild);  
    196. }  
    197.   
    198. int main(void)  
    199. {  
    200.     BiTNode *root=NULL; //定义一个根结点  
    201.     int flag=1,k;  
    202.     printf("                     本程序实现二叉树的基本操作。\n");  
    203.     printf("可以进行建立二叉树,递归先序、中序、后序遍历,非递归先序、中序遍历及非递归层序遍历等操作。\n");  
    204.   
    205.     while(flag)  
    206.     {  
    207.         printf("\n");  
    208.         printf("|--------------------------------------------------------------|\n");  
    209.         printf("|                    二叉树的基本操作如下:                     |\n");  
    210.         printf("|                        0.创建二叉树                          |\n");  
    211.         printf("|                        1.递归先序遍历                        |\n");  
    212.         printf("|                        2.递归中序遍历                        |\n");  
    213.         printf("|                        3.递归后序遍历                        |\n");  
    214.         printf("|                        4.非递归先序遍历                      |\n");  
    215.         printf("|                        5.非递归中序遍历                      |\n");  
    216.         printf("|                        6.非递归后序遍历                      |\n");  
    217.         printf("|                        7.非递归层序遍历                      |\n");  
    218.         printf("|                        8.二叉树的深度                        |\n");  
    219.         printf("|                        9.二叉树的结点个数                    |\n");  
    220.         printf("|                        10.退出程序                            |\n");  
    221.         printf("|--------------------------------------------------------------|\n");  
    222.         printf("                        请选择功能:");  
    223.         scanf("%d",&k);  
    224.         switch(k)  
    225.         {  
    226.         case 0:  
    227.             printf("请建立二叉树并输入二叉树的根节点:");  
    228.             CreateBiTree(&root);  
    229.             break;  
    230.         case 1:  
    231.             if(root)  
    232.             {  
    233.                 printf("递归先序遍历二叉树的结果为:");  
    234.                 PreOrder(root);  
    235.                 printf("\n");  
    236.             }  
    237.             else  
    238.                 printf("          二叉树为空!\n");  
    239.             break;  
    240.         case 2:  
    241.             if(root)  
    242.             {  
    243.                 printf("递归中序遍历二叉树的结果为:");  
    244.                 InOrder(root);  
    245.                 printf("\n");  
    246.             }  
    247.             else  
    248.                 printf("          二叉树为空!\n");  
    249.             break;  
    250.         case 3:  
    251.             if(root)  
    252.             {  
    253.                 printf("递归后序遍历二叉树的结果为:");  
    254.                 PostOrder(root);  
    255.                 printf("\n");  
    256.             }  
    257.             else  
    258.                 printf("          二叉树为空!\n");  
    259.             break;  
    260.         case 4:  
    261.             if(root)  
    262.             {  
    263.                 printf("非递归先序遍历二叉树:");  
    264.                 PreOrder_Nonrecursive(root);  
    265.                 printf("\n");  
    266.             }  
    267.             else  
    268.                 printf("          二叉树为空!\n");  
    269.             break;  
    270.         case 5:  
    271.             if(root)  
    272.             {  
    273.                 printf("非递归中序遍历二叉树:");  
    274.                 InOrderTraverse(root);  
    275.                 printf("\n");  
    276.             }  
    277.             else  
    278.                 printf("          二叉树为空!\n");  
    279.             break;  
    280.         case 6:  
    281.             if(root)  
    282.             {  
    283.                 printf("非递归后序遍历二叉树:");  
    284.                 PostOrder_Nonrecursive(root);  
    285.                 printf("\n");  
    286.             }  
    287.             else  
    288.                 printf("          二叉树为空!\n");  
    289.             break;  
    290.         case 7:  
    291.             if(root)  
    292.             {  
    293.                 printf("非递归层序遍历二叉树:");  
    294.                 //LeverTraverse(root);  
    295.                 LevelOrder(root);  
    296.                 printf("\n");  
    297.             }  
    298.             else  
    299.                 printf("          二叉树为空!\n");  
    300.             break;  
    301.         case 8:  
    302.             if(root)  
    303.                 printf("这棵二叉树的深度为:%d\n",depth(root));  
    304.             else  
    305.                 printf("          二叉树为空!\n");  
    306.             break;  
    307.         case 9:  
    308.             if(root)  
    309.                 printf("这棵二叉树的结点个数为:%d\n",CountNode(root));  
    310.             else  
    311.                 printf("          二叉树为空!\n");  
    312.             break;  
    313.         default:  
    314.             flag=0;  
    315.             printf("程序运行结束,按任意键退出!\n");  
    316.         }  
    317.     }  
    318.     system("pause");  
    319.     return 0;  
    320. }  

    运行效果图如下:

    分别输入:

    1

    2

    4

    #

    #

    5

    #

    #

    3

    6

    #

    #

    7

    #

    就可以构造如下图所示的二叉树了。。

    后序遍历非递归的另外一种写法:

    1. /* 
    2. 后序遍历由于遍历父节点是在遍历子节点之后,而且左节点和右节点遍历后的行为不一样, 
    3. 所以需要用变量来记录前一次访问的节点,根据前一次节点和现在的节点的关系来确定具体执行什么操作 
    4. */  
    5. void Postorder(BiTree T)  
    6. {  
    7.     if(T == NULL)  
    8.         return ;  
    9.     stack<BiTree> s;  
    10.     BiTree prev = NULL , curr = NULL;  
    11.     s.push(T);  
    12.     while(!s.empty())  
    13.     {  
    14.         curr = s.top();  
    15.         if(prev == NULL  || prev->lchild == curr || prev->rchild == curr)  
    16.         {  
    17.             if(curr->lchild != NULL)  
    18.                 s.push(curr->lchild);  
    19.             else if(curr->rchild != NULL)  
    20.                 s.push(curr->rchild);  
    21.         }  
    22.         else if(curr->lchild == prev)  
    23.         {  
    24.             if(curr->rchild != NULL)  
    25.                 s.push(curr->rchild);  
    26.         }  
    27.         else  
    28.         {  
    29.             cout<<curr->data;  
    30.             s.pop();  
    31.         }  
    32.         prev = curr;  
    33.     }  
    34. }  

    输入二叉树中的两个节点,输出这两个结点在数中最低的共同父节点。
    思路:遍历二叉树,找到一条从根节点开始到目的节点的路径,然后在两条路径上查找共同的父节点。

      1. // 得到一条从根节点开始到目的节点的路径  
      2. bool GetNodePath(TreeNode *pRoot , TreeNode *pNode , vector<TreeNode *> &path)  
      3. {  
      4.     if(pRoot == NULL)  
      5.         return false;  
      6.     if(pRoot == pNode)  
      7.         return true;  
      8.     else if(GetNodePath(pRoot->lchild , pNode , path) )  
      9.     {  
      10.         path.push_back(pRoot->lchild);  
      11.         return true;  
      12.     }  
      13.     else if(GetNodePath(pRoot->rchild , pNode , path) )  
      14.     {  
      15.         path.push_back(pRoot->rchild);  
      16.         return true;  
      17.     }  
      18.     return false;  
      19. }  
      20. TreeNode *GetLastCommonNode(const vector<TreeNode *> &path1 , const vector<TreeNode *> &path2)  
      21. {  
      22.     vector<TreeNode *>::const_iterator iter1 = path1.begin();  
      23.     vector<TreeNode *>::const_iterator iter2 = path2.begin();  
      24.     TreeNode *pLast;  
      25.     while(iter1 != path1.end() && iter2 != path2.end() )  
      26.     {  
      27.         if(*iter1 == *iter2)  
      28.             pLast = *iter1;  
      29.         else  
      30.             break;  
      31.         iter1++;  
      32.         iter2++;  
      33.     }  
      34.     return pLast;  
      35. }  
      36. TreeNode *GetLastCommonParent(TreeNode *pRoot , TreeNode *pNode1 , TreeNode *pNode2)  
      37. {  
      38.     if(pRoot == NULL || pNode1 == NULL || pNode2 == NULL)  
      39.         return  NULL;  
      40.     vector<TreeNode *> path1;  
      41.     GetNodePath(pRoot , pNode1 , path1);  
      42.   
      43.     vector<TreeNode *> path2;  
      44.     GetNodePath(pRoot , pNode2 , path2);  
      45.     return GetLastCommonNode(path1 , path2);  
      46. }  
  • 相关阅读:
    PAT顶级 1015 Letter-moving Game (35分)
    PAT顶级 1008 Airline Routes (35分)(有向图的强连通分量)
    PAT顶级 1025 Keep at Most 100 Characters (35分)
    PAT顶级 1027 Larry and Inversions (35分)(树状数组)
    PAT 顶级 1026 String of Colorful Beads (35分)(尺取法)
    PAT顶级 1009 Triple Inversions (35分)(树状数组)
    Codeforces 1283F DIY Garland
    Codeforces Round #438 A. Bark to Unlock
    Codeforces Round #437 E. Buy Low Sell High
    Codeforces Round #437 C. Ordering Pizza
  • 原文地址:https://www.cnblogs.com/zhanglanyun/p/2646199.html
Copyright © 2011-2022 走看看