二叉树的操作

        先使用先序的方法建立一棵二叉树,然后分别使用递归与非递归的方法实现前序、中序、后序遍历二叉树,并使用了两种方法来进行层次遍历二叉树,一种方法就是使用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. }  
posted @ 2012-08-19 10:26  张兰云  阅读(301)  评论(0编辑  收藏  举报