二叉树非递归遍历

xiaoxiao2021-02-28  71

1、前序遍历的非递归实现

 

 

根据先序遍历的顺序,先访问根节点,再访问左子树,后访问右子树,而对于每个子树来说,又按照同样的访问顺序进行遍历,非递归的实现思路如下:

对于任一节点P,

1)输出节点P,然后将其入栈,再看P的左孩子是否为空;

2)若P的左孩子不为空,则置P的左孩子为当前节点,重复1)的操作;

3)若P的左孩子为空,则将栈顶节点出栈,但不输出,并将出栈节点的右孩子置为当前节点,看其是否为空;

4)若不为空,则循环至1)操作;

5)如果为空,则继续出栈,但不输出,同时将出栈节点的右孩子置为当前节点,看其是否为空,重复4)和5)操作;

6)直到当前节点P为NULL并且栈空,遍历结束。

 

2、中序遍历的非递归实现

根据中序遍历的顺序,先访问左子树,再访问根节点,后访问右子树,而对于每个子树来说,又按照同样的访问顺序进行遍历,非递归的实现思路如下:

对于任一节点P,

1)若P的左孩子不为空,则将P入栈并将P的左孩子置为当前节点,然后再对当前节点进行相同的处理;

2)若P的左孩子为空,则输出P节点,而后将P的右孩子置为当前节点,看其是否为空;

3)若不为空,则重复1)和2)的操作;

4)若为空,则执行出栈操作,输出栈顶节点,并将出栈的节点的右孩子置为当前节点,看起是否为空,重复3)和4)的操作;

5)直到当前节点P为NULL并且栈为空,则遍历结束。

 

3、后序遍历的非递归实现

根据后序遍历的顺序,先访问左子树,再访问右子树,后访问根节点,而对于每个子树来说,又按照同样的访问顺序进行遍历。后序遍历的非递归的实现相对来说要难一些,要保证根节点在左子树和右子树被访问后才能访问,思路如下:

对于任一节点P,

1)先将节点P入栈;

2)若P不存在左孩子和右孩子,或者P存在左孩子或右孩子,但左右孩子已经被输出,则可以直接输出节点P,并将其出栈,将出栈节点P标记为上一个输出的节点,再将此时的栈顶结点设为当前节点;

3)若不满足2)中的条件,则将P的右孩子和左孩子依次入栈,当前节点重新置为栈顶结点,之后重复操作2);

4)直到栈空,遍历结束。

//非递归前序遍历1 void pre_order (BTreeNode *node) { if (node == NULL) { errno = ERROR; return; } LinkStack *Stack = Create_Stack (); BTreeNode *tmp = node;   //指向当前节点 while (tmp) { printf("L",tmp->data); Push (Stack,tmp); if (tmp->lchild) { tmp = tmp->lchild; continue; } while(StackEmpty(Stack) != TRUE) { Pop (Stack,&tmp); if(tmp = tmp->rchild) { break; } } } } } //非递归前序遍历2 void pre2_order (BTreeNode *node) { if (node == NULL) { errno = ERROR; return; } LinkStack *Stack = Create_Stack (); BTreeNode *tmp = node;   //指向当前节点 while (tmp) { printf("L",tmp->data); Push (Stack,tmp); if (tmp->lchild) { tmp = tmp->lchild; continue; } while(Pop (Stack,&tmp) && (tmp = tmp->rchild) == NULL); } } //前序遍历(老师的) void pre1(BTreeNode *root) { if(root == NULL) return; LinkStack *stack =  CreateStack(); BTreeNode* p = root; while (p != NULL || !StackEmpty(stack)) { while(p) { printf ("L", p->data); Push(stack, p); p = p->lchild; } if (!StackEmpty(stack)) { Pop (stack, &p); p = p->rchild; } } } //非递归中序遍历1 void mid_order (BTreeNode *node) { if (node == NULL) { errno = ERROR; return; } LinkStack *Stack = Create_Stack (); BTreeNode *tmp = node;   //指向当前节点 while (tmp) { Push (Stack,tmp); if (tmp->lchild) { tmp = tmp->lchild; continue; } tmp = tmp->rchild; while(StackEmpty(Stack) != TRUE && tmp == NULL) { Pop (Stack,&tmp); printf("L",tmp->data); tmp = tmp->rchild; } } } //非递归中序遍历2 void mid2_order (BTreeNode *node) { if (node == NULL) { errno = ERROR; return; } LinkStack *Stack = Create_Stack (); BTreeNode *tmp = node;   //指向当前节点 while (tmp) { Push (Stack,tmp); if (tmp->lchild) { tmp = tmp->lchild; continue; } tmp = tmp->rchild; while(tmp == NULL && Pop (Stack,&tmp)) { printf("L",tmp->data); tmp = tmp->rchild; } } } //中序遍历(老师的) void mid1(BTreeNode *root) { if(root == NULL) return; LinkStack *stack =  CreateStack(); BTreeNode* p = root; while (p != NULL || !StackEmpty(stack)) { while(p) { Push(stack, p); p = p->lchild; } if (!StackEmpty(stack)) { Pop (stack, &p); printf ("L", p->data); p = p->rchild; } } } //非递归后序遍历 void last2_order (BTreeNode *node) { if (node == NULL) { errno = ERROR; return; } LinkStack *Stack = Create_Stack (); BTreeNode *tmp = node;   //指向当前节点 BTreeNode *pre = NULL;  //指向被输出的节点 Push (Stack,tmp); while (StackEmpty (Stack) != TRUE) { GetTop (Stack,&tmp); //若P不存在左孩子和右孩子,或者P存在左孩子或右孩子,但左右孩子已经被输出 if(tmp->lchild == NULL && tmp->rchild == NULL  || pre != NULL &&(tmp->lchild == pre || tmp->rchild == pre)) { Pop (Stack,&tmp); printf("L",tmp->data); pre = tmp;//指向被输出的节点 continue; } if(tmp->rchild) { Push (Stack,tmp->rchild); } if(tmp->lchild) { Push (Stack,tmp->lchild); } } } //层次遍历(用栈代替队列) void level_order(BTreeNode *node) { if (node == NULL) return; LinkStack *s1 = Create_Stack (); LinkStack *s2 = Create_Stack (); Push (s1,node);  // 根节点进队 while (StackEmpty (s1) != TRUE) { // 队头元素出队 BTreeNode* tmp = NULL; if (StackEmpty (s2) != TRUE)      //栈2不空,就出栈2 { Pop (s2,&tmp); } else { Pop (s1,&tmp); while(StackEmpty (s1) != TRUE)  //把栈1的元素导入到栈2,最后一个不用,直接输出 { Push (s2,tmp); Pop (s1,&tmp); } } printf ("L", tmp->data); if (tmp->lchild != NULL) Push (s1,tmp->lchild);  // 左节点入队 if (tmp->rchild != NULL) Push (s1,tmp->rchild);  // 右节点入队 } free(s1); free(s2); } //层次遍历(队列实现)(老师的) void level_order(BTreeNode *root) { if (root == NULL) return; LinkQueue * queue = CreateQueue(); EnQueue (queue, root);  // 根节点进队 while (!QueueEmpty(queue)) { // 队头元素出队 BTreeNode* p = NULL; DeQueue(queue, &p); printf ("L", p->data); if (p->lchild != NULL) EnQueue(queue, p->lchild);  // 左节点入队 if (p->rchild != NULL) EnQueue(queue, p->rchild);  // 右节点入队 } free(queue); }

转载请注明原文地址: https://www.6miu.com/read-37260.html

最新回复(0)