C语言对前序创建的二叉树进行前序、中序、后序的非递归遍历

首先介绍二叉树的前序、中序、后序遍历:
二叉树的前序遍历:
1)首先访问根节点
2)然后按照前序遍历的方式访问根节点的左子树
3)最后按照前序遍历的方式访问根节点的右子树
二叉树的中序遍历:
1)首先按照中序遍历的方式访问根节点的左子树
2)然后访问根节点
3)最后按照中序遍历的方式访问根节点的右子树
二叉树的后序遍历:
1)首先按照后序遍历的方式访问根节点的左子树
2)然后按照后序遍历的方式访问根节点的右子树
3)最后访问根节点


来看这样一棵二叉树:
在这里插入图片描述
根据以上二叉树遍历的定义,得到该二叉树的遍历结果:
前序:abdefgc
中序:debgfac
后序:edgfbca
为了更直观一点,我们将二叉树补全:
在这里插入图片描述
这样得到的结果就变成了:
前序:abd#e##fg###c##
中序:#d#e#b#g#f#a#c#
后序:##e#d#g##fb##ca

这里我们采取链式存储方式来建立二叉树。因为顺序存储必须预先给出数组的大小,但是在某些情况下数组大小是难以确定的。链式存储则可以避免这个问题。

链式存储方式下二叉树的节点构如图:
在这里插入图片描述
其中lchild是指向该节点左子树的指针,rchild是指向该节点右子树的指针。
那么开头那棵二叉树的链式存储就可以表示为:
在这里插入图片描述

二叉树的前序创建:

可以用递归方法实现:

typedef struct node{
	char chars;
	struct node *lchild, *rchild; 
}bintnode;

typedef bintnode* bintree;

bintree createbintree() {   
	char ch;
	bintree t=NULL;
	if ((ch = getchar())== '#')
		t = NULL;
	else {
		t = (bintnode*)malloc(sizeof(bintnode));
		t->chars = ch;
		t->lchild = createbintree();
		t->rchild = createbintree();
	}
	return t;
}

二叉树遍历的非递归实现:

在采用非递归方式实现二叉树遍历时,需要用栈来记录回溯点:

typedef struct stack {
	bintree data[100];
	int tag[100];  //后序遍历标记
	int top;   //栈顶指针
}seqstack;

void push(seqstack* s,bintree t) {
	s->data[s->top] = t;
	s->top++;                                  
}

bintree pop(seqstack* s) {
	if (s->top != 0) {
		s->top--;
		return(s->data[s->top]);
	}
	else
		return NULL;
}

前序:
在这里插入图片描述

void preorder(bintree t) { 
	seqstack s;
	s.top = 0;
	while ((t) || (s.top != 0)) {  
		if (t) {
			printf("%c", t->chars);
			push(&s, t);
			t = t->lchild;
		}
		else {
			t = pop(&s);
			t = t->rchild;
		}
	}
}

中序:
在这里插入图片描述

void inorder(bintree t) {  //中非
	seqstack s;
	s.top = 0;
	while ((t) || (s.top != 0)) {
		if (t) {
			push(&s, t);
			t = t->lchild;
		}
		else {
			t = pop(&s);
			printf("%c", t->chars);
			t = t->rchild;
		}
	}
}

后序:
后序遍历的特别之处:
后序遍历时,当一个元素位于栈顶即将出栈时,说明该元素的左子一定以经遍历完成,如果其右子树不为空,此时应进入其右子树进行访问,该元素不能出栈。但是这就违背了栈“后进先出”的概念。所以我们需要一个标记,来记录某个元素是否可以出栈:当标记为0时,说明该元素右子还未被访问,应先去访问右子;当右子访问完时,标记变为1,说明该元素可以出栈了。
在这里插入图片描述

void postorder(bintree t) {   //后非
	seqstack s;
	s.top = 0;
	while ((t) || (s.top != 0)) {
		if (t) {
			s.data[s.top] = t;
			s.tag[s.top] = 0;
			s.top++;
			t = t->lchild;
		}
		else {
			if (s.tag[s.top - 1] == 1) {
				s.top--;
				t = s.data[s.top];
				printf("%c", t->chars);
				t = NULL;
			}
			else {
				t = s.data[s.top - 1];
				s.tag[s.top - 1] = 1;
				t = t->rchild;
			}
		}
	}
}

最后是完整的代码:

#include<stdlib.h>
#include<stdio.h>
#define MAXSIZE 20
typedef struct node{
	char chars;
	struct node *lchild, *rchild; 
}bintnode;

typedef bintnode* bintree;

typedef struct stack {
	bintree data[100];
	int tag[100];  //后序遍历标记
	int top;   //栈顶指针
}seqstack;

void push(seqstack* s,bintree t) {
	s->data[s->top] = t;
	s->top++;
}

bintree pop(seqstack* s) {
	if (s->top != 0) {
		s->top--;
		return(s->data[s->top]);
	}
	else
		return NULL;
}

bintree createbintree() {   //前建
	char ch;
	bintree t=NULL;
	if ((ch = getchar())== '#')
		t = NULL;
	else {
		t = (bintnode*)malloc(sizeof(bintnode));
		t->chars = ch;
		t->lchild = createbintree();
		t->rchild = createbintree();
	}
	return t;
}

void preorder(bintree t) {  //前非
	seqstack s;
	s.top = 0;
	while ((t) || (s.top != 0)) {  //树不为空或栈不为空
		if (t) {
			printf("%c", t->chars);
			push(&s, t);
			t = t->lchild;
		}
		else {
			t = pop(&s);
			t = t->rchild;
		}
	}
}

void inorder(bintree t) {  //中非
	seqstack s;
	s.top = 0;
	while ((t) || (s.top != 0)) {
		if (t) {
			push(&s, t);
			t = t->lchild;
		}
		else {
			t = pop(&s);
			printf("%c", t->chars);
			t = t->rchild;
		}
	}
}

void postorder(bintree t) {   //后非
	seqstack s;
	s.top = 0;
	while ((t) || (s.top != 0)) {
		if (t) {
			s.data[s.top] = t;
			s.tag[s.top] = 0;
			s.top++;
			t = t->lchild;
		}
		else {
			if (s.tag[s.top - 1] == 1) {
				s.top--;
				t = s.data[s.top];
				printf("%c", t->chars);
				t = NULL;
			}
			else {
				t = s.data[s.top - 1];
				s.tag[s.top - 1] = 1;
				t = t->rchild;
			}
		}
	}
}

int main() {
	bintree root;
	root = createbintree();
	preorder(root);
	printf("\n");
	inorder(root);
	printf("\n");
	postorder(root);
	printf("\n");
	return 0;
}

程序运行结果(以文章中的例子为例):在这里插入图片描述
注意:
按照前序建立(输入)时,应按照如图所示顺序输入:
在这里插入图片描述

发布了20 篇原创文章 · 获赞 10 · 访问量 1229

猜你喜欢

转载自blog.csdn.net/qq_43613793/article/details/103112004