二叉树的非递归遍历(前序中序后序非递归C语言)

前两天做数据结构实验,要求用非递归算法遍历二叉树。只知道用栈来储存数据,具体算法还不太清楚。经过两天的搜索,看到网上很多种解法,很多解法都是用C++来写的算法,一直找不到用C语言写的算法,所以就总结了一下,用C写出了一个遍历二叉树的三种非递归算法。

前序遍历

前序遍历按照“根结点-左孩子-右孩子”的顺序进行访问。
具体算法:先遍历左孩子,并输出。当左孩子遍历完后,取栈顶,找右孩子。此时循环还没有结束,再遍历它的左孩子,右孩子直至孩子全部遍历结束。

void preorder(bitree *t)//前序遍历的非递归算法
{
	bitree *temp = t;//定义一个树节点,用它来遍历
	while(temp != NULL || s.top != 0)
	{
		while(temp != NULL)//先遍历左孩子,并输出。
		{
			printf("%4d",temp->data);
			push(temp);
			temp = temp->lchild;
		}
		if(s.top != 0)//当左孩子遍历完后,取栈顶,找右孩子。此时循环还没有结束,再遍历它的左孩子,直至孩子全部遍历结束。
		{
			temp = pop();
			temp = temp->rchild;
		}
	}
	printf("\n");
}

中序遍历

中序遍历按照“左孩子-根节点-右孩子”的顺序进行访问。
具体算法:先把左孩子入栈,不着急先输出,先把所有左孩子入栈。左孩子入栈结束,取栈顶,输出栈顶元素,遍历右孩子,右孩子入栈。

void inorder(bitree *t)//中序遍历的非递归算法
{
	bitree *temp = t;
	while(temp != NULL||s.top != 0)
	{
		while(temp != NULL)//先把左孩子入栈,所有左孩子入栈结束
		{
			push(temp);
			temp = temp->lchild;
		}
		if(s.top != 0)//左孩子入栈结束,取栈顶,输出栈顶元素,遍历右孩子
		{
			temp = pop();
			printf("%4d",temp->data);
			temp = temp->rchild;
		}
	}
	printf("\n");
}

后序遍历

后序遍历按照“左孩子-右孩子-根节点”的顺序进行访问。
具体算法:对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,此时该结点出现在栈顶,但是此时不能将其出栈并访问,因此其右孩子还为被访问。所以接下来按照相同的规则对其右子树进行相同的处理,当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。这样就保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现在栈顶,只有在第二次出现在栈顶时,才能访问它。因此需要多设置一个变量标识该结点是否是第一次出现在栈顶。

void laorder(bitree *root)//后序遍历的非递归算法
{
    bitree *temp = root;
	while(temp!=NULL||s.top!=0)
    {
        while(temp!= NULL)
        {
            temp->cishu=1;       // 当前节点首次被访问
            push(temp);
            temp=temp->lchild;
        }
        if(s.top!=0)
        {
            temp=pop( );
            if(temp->cishu == 1)   // 第一次出现在栈顶
            {

                temp->cishu++;
                push(temp);
                temp=temp->rchild;
            }
            else
				if(temp->cishu==2)//第二次输出并制空,防止陷入死循环
				{
                printf("%4d",temp->data);
                temp=NULL;
				}
        }
    }
	printf("\n");
}

一个完整的程序

#include 
#include 
#define NULL 0
#define M 100 
typedef struct node  
{  
    int data;
	int cishu;
    struct node *lchild;  
    struct node *rchild;  //树节点中cishu是为了计数用。在后序遍历中,子树的根节点在第一次遍历的时候不会输出,只有在第二次遍历的时候才输出。
}bitree;
 
 
typedef struct stack 
{
	bitree *elements[M];
	int top;
}seqstack;//定义一个储存树类型地址的栈,方便遍历的时候追踪到树的地址。

bitree *root;//定义一个树根
seqstack s;//定义栈

void setnull()//初始化栈
{
	s.top =0;
}
 
void push(bitree *temp)//入栈操作
{
	s.elements[s.top++] = temp;
}
 
bitree *pop()//取栈顶并出栈顶
{
	return s.elements[--s.top];
}
 
int empty()//判断空栈
{
	return s.top == 0;
}
 
bitree *creat()   /*建立二叉树的递归算法*/
{ bitree *t;
  int x;
  scanf("%d",&x);
  if(x==0) t=NULL; /*以x=0表示输入结束*/
  else{
  t=(bitree*)malloc(sizeof(bitree));//动态生成结点t,分别给结点t的数据域、左右孩子域  
  t->data=x;                  //赋值,给左右孩子域赋值时用到了递归的思想。
  t->lchild=creat();
  t->rchild=creat();
  }
  return t;
}

void preorder(bitree *t)//前序遍历的非递归算法
{
	bitree *temp = t;//定义一个树节点,用它来遍历
	while(temp != NULL || s.top != 0)
	{
		while(temp != NULL)//先遍历左孩子,并输出。
		{
			printf("%4d",temp->data);
			push(temp);
			temp = temp->lchild;
		}
		if(s.top != 0)//当左孩子遍历完后,取栈顶,找右孩子。此时循环还没有结束,再遍历它的左孩子,直至孩子全部遍历结束。
		{
			temp = pop();
			temp = temp->rchild;
		}
	}
	printf("\n");
}
 
void inorder(bitree *t)//中序遍历的非递归算法
{
	bitree *temp = t;
	while(temp != NULL||s.top != 0)
	{
		while(temp != NULL)//先把左孩子入栈,所有左孩子入栈结束
		{
			push(temp);
			temp = temp->lchild;
		}
		if(s.top != 0)//左孩子入栈结束,取栈顶,输出栈顶元素,遍历右孩子
		{
			temp = pop();
			printf("%4d",temp->data);
			temp = temp->rchild;
		}
	}
	printf("\n");
}
 
 
void laorder(bitree *root)//后序遍历的非递归算法
{
    bitree *temp = root;
	while(temp!=NULL||s.top!=0)
    {
        while(temp!= NULL)
        {
            temp->cishu=1;       // 当前节点首次被访问
            push(temp);
            temp=temp->lchild;
        }
        if(s.top!=0)
        {
            temp=pop( );
            if(temp->cishu == 1)   // 第一次出现在栈顶
            {

                temp->cishu++;
                push(temp);
                temp=temp->rchild;
            }
            else
				if(temp->cishu==2)//第二次输出并制空,防止陷入死循环
				{
                printf("%4d",temp->data);
                temp=NULL;
				}
        }
    }
	printf("\n");
}

 
int main()
{
	bitree *root;//创建根
	setnull();//制空栈
	root=creat();//创建二叉树:尝试输入:1 2 3 0 0 4 0 0 5 6 0 0 7 0 0
	printf("前序遍历:\n");
	preorder(root);
	printf("中序遍历:\n");
	inorder(root);
	printf("后序遍历:\n");
	laorder(root);
	return 0;
}

程序验证

建立一个如下图所示的二叉树(图画的不太好看)
二叉树的非递归遍历(前序中序后序非递归C语言)_第1张图片
结果如下图:
二叉树的非递归遍历(前序中序后序非递归C语言)_第2张图片

你可能感兴趣的:(常用算法)