堆栈实现二叉树的先序、中序及后序遍历

堆栈实现二叉树的遍历

该方式主要通过使用栈这一数据结构实现二叉树的遍历。

中序遍历

对于中序遍历而言,采用该方式的详细过程如下:

  • 遇到一个结点,就把它压栈,并遍历它的左子树
  • 当左子树遍历结束后,从栈顶弹出这个结点并访问它
  • 然后按其右指针再去中序遍历该节点
void PreOrder(BinTree BT)
{
     BinTree t = BT;
     Stack s = CreateStack();
     while(t || !IsEmpty(s))
     {
          while(t){
               Push(s, t);
               t = t->left;
          }
          if(!IsEmpty(s))
          {
               t = Pop(s);
               printf("%c", t->Data);
               t = t->right;
          }
     }
}

先序遍历

  • 遇到一个结点,就输出,然后把它压栈,并遍历它的左子树
  • 当左子树遍历结束后,从栈顶弹出这个结点
  • 然后按其右指针再去先序遍历该节点的左子树
// 先序非递归 
void PreOrderTraversal(BinTree BT){
	BinTree T = BT;
	Stack S = CreateStack();  // 创建并初始化堆栈 S
	while(T || !IsEmpty(S)){  // 当树不为空或堆栈不空 
		while(T){     
			Push(S,T);    // 压栈,第一次遇到该结点 
			printf("%d",T->Data);  // 访问结点
			T = T->Left;   // 遍历左子树 
		}
		if(!IsEmpty(S)){  // 当堆栈不空 
			T = Pop(S);    // 出栈,第二次遇到该结点 
			T = T->Right;  // 访问右结点 
		}
	} 
} 

后序遍历

对于后序遍历,可以使用反序进行输出。先序的访问顺序是root,left,right,我们可以先将左右对调,则顺序变为root,right,left,然后用栈来存储,最后输出栈中的内容, 此时顺序就变为了left,right,root。

具体实现的步骤:
建立两个栈,一个用作存储root,right,left顺序的结果栈,一个用作临时栈进行先序遍历。

  • 遇到一个结点,就把它压栈,同时将该节点存到结果栈中,遍历它的右子树
  • 当右子树遍历结束后,从栈顶弹出这个结点
  • 然后按其左指针再去先序遍历该节点的左子树
  • 最后输出结果栈中的内容即可。
void PostOrder( BinTree BT )
{
   BinTree t = BT;
   Stack s = CreateStack();  //创建并初始化堆栈S
   Stack q = CreateStack();  //创建并初始化堆栈Q,用于输出反向
   while( t || !IsEmpty(s) ){
       while(t){  //一直向右并将沿途结点压入堆栈
           Push(s,t);
           Push(q,t);//  将遍历到的结点压栈,用于反向
           t = t->right;
       }
       if(!IsEmpty(s)){
       t = Pop(s);  //结点弹出堆栈
       t = t->left; //转向左子树
       }
   }
   while( !IsEmpty(q) ){
       t = Pop(q);
       printf("%c", t->Data); //(访问)打印结点
   }
}

例子

针对如下二叉树的三种遍历方式进行实现:
在这里插入图片描述

#include<stdio.h>
#include<malloc.h>

typedef struct TreeNode *BinTree;
struct TreeNode{
     char Data;
     BinTree left;
     BinTree right;
};

//创建堆栈用于实现堆栈方式遍历二叉树
typedef struct Snode *Stack;
struct Snode{
     BinTree Data;
     Stack next;
};
Stack CreateStack();
int IsEmpty(Stack s);
void Push(Stack s, BinTree item);
BinTree Pop(Stack s);

Stack CreateStack()
{
     Stack s;
     s = (Stack)malloc(sizeof(struct Snode));
     s->next = NULL;
     return s;
}
int IsEmpty(Stack s)
{
     return s->next == NULL;
}
void Push(Stack s, BinTree item)
{
     Stack tmp = (Stack)malloc(sizeof(struct Snode));
     tmp->Data = item;
     //栈顶元素是链表头结点,新入栈的链表在栈顶元素后面
     tmp->next = s->next;
     s->next = tmp;
}
BinTree Pop(Stack s)
{
     BinTree val;
     Stack tmp = s->next;
     val = tmp->Data;
     s->next = tmp->next;
     free(tmp);
     return val;
}

//创建二叉树
BinTree CreateBinTree();
//插入节点
BinTree Insert(char Data);
//堆栈实现先序遍历
void PreOrder(BinTree BT);
//堆栈实现中序遍历
void InOrder(BinTree BT);
//堆栈实现后序遍历
void PostOrder(BinTree BT);

BinTree Insert(char Data)
{
     BinTree bt = (BinTree)malloc(sizeof(struct TreeNode));
     bt->Data = Data;
     bt->left = NULL;
     bt->right = NULL;
     return bt;
}

BinTree CreateBinTree()
{
     BinTree bt;
     bt = (BinTree)malloc(sizeof(struct TreeNode));
     bt->Data = 'a';
     bt->left = Insert('b');
     bt->right = Insert('c');
     bt->left->left = Insert('d');
     bt->left->right = Insert('f');
     bt->right->left = Insert('g');
     bt->right->right = Insert('i');
     bt->left->right->left = Insert('e');
     bt->right->left->right =Insert('h');
     return bt;
}

//堆栈实现先序遍历
void PreOrder(BinTree BT)
{
     BinTree t = BT;
     Stack s = CreateStack();
     while(t || !IsEmpty(s))
     {
          while(t){
               Push(s, t);
               printf("%c", t->Data);
               t = t->left;
          }
          if(!IsEmpty(s))
          {
               t = Pop(s);
               t = t->right;
          }
     }
}

void InOrder(BinTree BT)
{
     BinTree t = BT;
     Stack s = CreateStack();
     while(t || !IsEmpty(s))
     {
          while(t){
               Push(s, t);
               t = t->left;
          }
          if(!IsEmpty(s))
          {
               t = Pop(s);
               printf("%c", t->Data);
               t = t->right;
          }
     }
}

void PostOrder( BinTree BT )
{
   BinTree t = BT;
   Stack s = CreateStack();  //创建并初始化堆栈S
   Stack q = CreateStack();  //创建并初始化堆栈Q,用于输出反向
   while( t || !IsEmpty(s) ){
       while(t){  //一直向右并将沿途结点压入堆栈
           Push(s,t);
           Push(q,t);//  将遍历到的结点压栈,用于反向
           t = t->right;
       }
       if(!IsEmpty(s)){
       t = Pop(s);  //结点弹出堆栈
       t = t->left; //转向左子树
       }
   }
   while( !IsEmpty(q) ){
       t = Pop(q);
       printf("%c", t->Data); //(访问)打印结点
   }
}

int main()
{
     BinTree bt = CreateBinTree();
     PreOrder(bt);
     printf("\n");
     InOrder(bt);
     printf("\n");
     PostOrder(bt);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱学习的贝塔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值