数据结构 ---- 二叉树的相关操作(2)

在上一篇文章中完成了二叉树的递归版本的先序、中序、后序遍历,现在来介绍非递归版本的三种遍历方法;
三种遍历均借助顺序栈来完成
先序遍历:
思路:先将根结点入栈,然后循环的进行取栈顶元素,同时出栈,并且将栈顶元素的左右子树入栈,当取栈顶元素失败说明,已经遍历完了,跳出循环;
代码实现:

 void TreePreOrderByLoop(TreeNode* root){
     if(root == NULL){
         return;
     }                                                                                              
     //1.先把根结点入栈
     SeqStack stack;
     SeqStackInit(&stack);
     SeqStackPush(&stack,root);
     //2.循环取栈顶元素,访问,并且出栈,在将根结点的左右子树入栈
     TreeNode* top = NULL;
     while(1){
         int ret = SeqStackTop(&stack,&top);
         if(ret == 0){
             printf("\n");
             //取栈顶元素失败,遍历结束
             break;
         }
         SeqStackPop(&stack);
         printf("%c ",top->data);
         if(top->rchild != NULL){
             SeqStackPush(&stack,top->rchild);
         }
         if(top->lchild != NULL){
             SeqStackPush(&stack,top->lchild);
         }
     }
     return;
 }                

中序遍历
思路:这里与先序遍历不同的是入栈之后不能立刻访问,需要先找到最左边的一个结点,所以定义一个cur指向root循环的入栈并且让cur指向cur的左子树,当cur为空时,进行出栈,并且同时进行访问,在将cur调整指向此时栈顶元素的右子树即可;
代码实现:

 void TreeInOrderByLoop(TreeNode* root){
    if(root == NULL){
         return;
     }
    //定义cur指针指向根结点
     SeqStack stack;
     SeqStackInit(&stack);
     TreeNode* cur = root;
     while(1){
         //1.循环判定cur是否为空,如果不为空,将cur入栈,并且cur指向cur->lchild
         while(cur != NULL){
             SeqStackPush(&stack,cur);
             cur = cur->lchild;
         }
         //2.如果cur为空,取栈顶元素,访问,出栈
         TreeNode* top = NULL;
         int ret = SeqStackTop(&stack,&top);                                                        
         if(ret == 0){
             printf("\n");
             //此时说明已经没有栈顶元素,遍历完了
             return;
         }
         printf("%c ",top->data);
         SeqStackPop(&stack);
         //3.让cur指向栈顶元素的右子树,重复循环刚才判空的过程
         cur = top->rchild;
     }
 }

后序遍历:
思路:这里与中序遍历思路相似,不同的是在进行访问之前应该先对栈顶元素进行判断,判断是否能够进行访问;
代码实现如下:

 void TreePostOrderByLoop(TreeNode* root){
     if(root == NULL){
         return;                                                                                    
     }
     //1.定义一个cur指针指向root
     SeqStack stack;
     SeqStackInit(&stack);
     TreeNode* cur = root;
     TreeNode* pre = NULL;//保存上一个访问过的节点
     //2.循环判定cur是否为空,如果cur不为空,就将cur入栈,并且cur指向cur->lchild
     while(1){
         while(cur != NULL){
             SeqStackPush(&stack,cur);
             cur = cur->lchild;
         }
         //3.如果cur为空,循环取栈顶元素
         TreeNode* top = NULL;
         int ret = SeqStackTop(&stack,&top);
         if(ret == 0){
             printf("\n");
             //取栈顶元素失败,遍历结束                                                             
             return;
         }
         //4.对栈顶元素进行判定
         //  a)如果栈顶元素的右子树和上一个访问过的元素相等
         //  b)或者栈顶元素的右子树为空
         //  此时访问栈顶元素,同时进行出栈
         //5.如果不满足刚才的条件,就让cur指向栈顶元素的右子树,重复循环
         if(top->rchild == pre || top->rchild == NULL){
             printf("%c ",top->data);
             SeqStackPop(&stack);
             pre = top;
         }else{
             cur = top->rchild;
         }
     }
 }

猜你喜欢

转载自blog.csdn.net/liru_1996/article/details/80351630