二叉树的非递归遍历算法

二叉树的非递归遍历算法

二叉树的遍历是指访问二叉树的每个结点,且每个结点仅被访问一次。二叉树的遍历可按二叉树的构成以及访问结点的顺序分为4种方式:先序遍历、中序遍历、后序遍历和层次遍历。请至少给出其中一种遍历方式的非递归算法的思路和代码,并举例演示算法的执行过程。

先序遍历

算法思路:采用栈来实现先序遍历的非递归算法。创建栈,并初始化。遍历结点,若结点存在,则入栈,并输出结点的值,指向其左孩子;否则出栈,访问结点,指向其右孩子。如果结点不存在或者栈为空,则遍历结束。

代码:

//先序遍历二叉树
void PreOrder(BiTree T)
{
	SqStack* S;
	S = InitStack();
	BiTreeNode* p;
	p = T;
	while (p|| !StackEmpty(*S))
	{
		if (p)
		{
			printf("%c",p->data);
			Push(S, p);
			p = p->LChild;
		}
		else
		{
			Pop(S, &p);
			p = p->RChild;
		}
	}
}

演示过程(以先序遍历输入ABD##E##CF###为例)

  1. 根节点A入栈,并打印该结点的值,P指向其左孩子
    二叉树的非递归遍历算法_第1张图片

此时输出:A

  1. 继续遍历结点,此时B结点存在并打印该结点的值,则将该结点入栈,P指向B结点的左孩子
    二叉树的非递归遍历算法_第2张图片

此时输出:AB

  1. 继续遍历结点,此时D结点存在并打印该结点的值,则将该结点入栈,P指向D结点的左孩子
    二叉树的非递归遍历算法_第3张图片

此时输出:ABD

  1. 继续遍历结点,此时D结点的左孩子不存在,则将栈顶元素出栈,P指向D结点的右孩子
    二叉树的非递归遍历算法_第4张图片

此时输出:ABD(不变)

  1. 继续遍历结点,此时D结点的右孩子不存在,则将栈顶元素出栈,P指向B结点的右孩子
    二叉树的非递归遍历算法_第5张图片

此时输出:ABD(不变)

  1. 继续遍历结点,此时E结点存在并打印该结点的值,则将该结点入栈,P指向E结点的左孩子
    二叉树的非递归遍历算法_第6张图片

此时输出:ABDE

  1. 继续遍历结点,此时E结点的左孩子为空,则将栈顶元素出栈,P指向E结点的右孩子
    二叉树的非递归遍历算法_第7张图片

此时输出:ABDE(不变)

  1. 继续遍历结点,此时E结点的右孩子为空,则将栈顶元素出栈,P指向A结点的右孩子
    二叉树的非递归遍历算法_第8张图片

此时输出:ABDE(不变)

  1. 继续遍历结点,此时C结点存在并打印该结点的值,则将该结点入栈,P指向C结点的左孩子
    二叉树的非递归遍历算法_第9张图片

此时输出:ABDEC

  1. 继续遍历结点,此时F结点存在并打印该结点的值,则将该结点入栈,P指向F结点的左孩子
    二叉树的非递归遍历算法_第10张图片

此时输出:ABDECF

  1. 继续遍历结点,此时F结点的左孩子为空,则将栈顶元素F出栈,P指向F结点的右孩子

此时F结点的右孩子也为空,继续将栈顶元素C出栈,P指向C结点的右孩子,此时P指向的结点为空,栈也为空,遍历结束。

中序遍历

算法思路:同样也是用栈,与先序遍历相同,只是输出在不同位置。创建栈,并初始化。遍历结点,若结点存在,则入栈,指向其左孩子;否则出栈,访问结点,并输出结点的值,指向其右孩子。如果结点不存在或者栈为空,则遍历结束

代码:

//中序遍历二叉树
void InOrder(BiTree T)
{
	SqStack* S;
	S = InitStack();
	BiTreeNode* p;
	p = T;
	while (p || !StackEmpty(*S))
	{
		if (p)
		{
			Push(S, p);
			p = p->LChild;
		}
		else
		{
			Pop(S, &p);
			printf("%c", p->data);
			p = p->RChild;
		}
	}
}

后序遍历

算法思路:由于后序遍历是后序遍历根节点的左子树,后序遍历根节点的右子树,最后访问根节点,那么最大问题就是判断是否该结点结束遍历左子树,所以采取以下操作来解决。同样也使用一个栈,初始化栈,遍历结点,若结点存在,结点入栈,并对该结点标志位0,表示该结点尚未被遍历其左子树,然后指向其右结点;若结点不存在,满足该结点的左子树已被遍历进入循环,遍历该结点的右子树。不满足退出循环,然后继续出栈得到子结点,并将其压入栈,指向子节点的右孩子,并对该结点标志为1。

代码:

//后序遍历
void Postorder(BiTree T)
{
	SqStack* S;
	S = InitStack();
	BiTreeNode* p;
	p = T;
	char tag[Maxsize] = {'0'};
	while (p || !StackEmpty(*S))
	{
		if (p)
		{
			Push(S, p);
			tag[S->top] = '0';//标志结点是否遍历右子树
			p = p->LChild;
		}
		else
		{
			while (tag[S->top] == '1') {
				Pop(S, &p);
				printf("%c",p->data);
			}
			if (S->top == -1) break;
			Pop(S, &p);
			Push(S, p);
			p = p->RChild;
			tag[S->top] = '1';
		}
		

	}
}

层次遍历

算法思路:采用顺序队列来实现,将根节点入队,进入循环,将队头指针所指的元素出队,并输出其结点的值,如果该结点的左孩子存在,将其左孩子入队,如果该结点的右孩子存在,将右孩子入队,直到队头指针和队尾指针相等退出循环。

代码:

//层次遍历
void Levelorder(BiTree T)
{
	BiTree Q[Maxsize];
	int front, rear;
	if (T == NULL)return;
	front = -1;
	rear = 0;
	Q[rear] = T;
	while (front != rear)
	{
		front++;
		printf("%c",Q[front]->data);
		if (Q[front]->LChild != NULL)
		{
			rear++;
			Q[rear] = Q[front]->LChild;
		}
		if (Q[front]->RChild != NULL)
		{
			rear++;
			Q[rear] = Q[front]->RChild;
		}
	}
}

代码汇总

//非递归先序遍历、中序遍历、后序遍历可用栈来实现
//层次遍历可用队列来实现
//作者:Second to none
#include
#include
#include
#include
#include
#define Maxsize 30
typedef char ElemType;
void gotoxy(int x, int y)
{
	COORD c;
	c.X = x - 1;
	c.Y = y - 1;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}
typedef struct BiTreeNode
{
	ElemType data;
	struct BiTreeNode* LChild, * RChild;
}*BiTree;
typedef struct SqStack
{
	BiTree data[Maxsize];
	int top;
}*Stack;
//创建栈
Stack InitStack()
{
	Stack S;
	S = (Stack)malloc(sizeof(SqStack));
	S->top = -1;
	return S;
}
//栈空
int StackEmpty(SqStack S)
{
	if (S.top == -1)return 1;
	else return 0;
}
//入栈
void Push (Stack S,BiTree p)
{
	S->top++;
	S->data[S->top] = p;
}
//出栈
void Pop(Stack S, BiTree* p)
{
	*p = S->data[S->top];
	S->top--;
}
BiTree CreateBiTree()
{
	char ch;
	BiTree T;
	scanf_s("%c",&ch,1);
	if (ch == '#')T = NULL;
	else {
		T = (BiTree)malloc(sizeof(BiTreeNode));
		T->data = ch;
		T->LChild = CreateBiTree();
		T->RChild = CreateBiTree();
	}
	return T;
}
//先序遍历二叉树
void PreOrder(BiTree T)
{
	SqStack* S;
	S = InitStack();
	BiTreeNode* p;
	p = T;
	while (p|| !StackEmpty(*S))
	{
		if (p)
		{
			printf("%c",p->data);
			Push(S, p);
			p = p->LChild;
		}
		else
		{
			Pop(S, &p);
			p = p->RChild;
		}
	}
}
//中序遍历二叉树
void InOrder(BiTree T)
{
	SqStack* S;
	S = InitStack();
	BiTreeNode* p;
	p = T;
	while (p || !StackEmpty(*S))
	{
		if (p)
		{
			Push(S, p);
			p = p->LChild;
		}
		else
		{
			Pop(S, &p);
			printf("%c", p->data);
			p = p->RChild;
		}
	}
}
//后序遍历
void Postorder(BiTree T)
{
	SqStack* S;
	S = InitStack();
	BiTreeNode* p;
	p = T;
	char tag[Maxsize] = {'0'};
	while (p || !StackEmpty(*S))
	{
		if (p)
		{
			Push(S, p);
			tag[S->top] = '0';//标志结点是否遍历右子树
			p = p->LChild;
		}
		else
		{
			while (tag[S->top] == '1') {
				Pop(S, &p);
				printf("%c",p->data);
			}
			if (S->top == -1) break;
			Pop(S, &p);
			Push(S, p);
			p = p->RChild;
			tag[S->top] = '1';
		}
		

	}
}
//层次遍历
void Levelorder(BiTree T)
{
	BiTree Q[Maxsize];
	int front, rear;
	if (T == NULL)return;
	front = -1;
	rear = 0;
	Q[rear] = T;
	while (front != rear)
	{
		front++;
		printf("%c",Q[front]->data);
		if (Q[front]->LChild != NULL)
		{
			rear++;
			Q[rear] = Q[front]->LChild;
		}
		if (Q[front]->RChild != NULL)
		{
			rear++;
			Q[rear] = Q[front]->RChild;
		}
	}
}
int GetHightOfTree(BiTree T)
{
	int rh = 0, lh = 0;
	if (!T)return 0;
	else
	{
		lh = GetHightOfTree(T->LChild);
		rh = GetHightOfTree(T->RChild);
		return(lh > rh ? lh : rh) + 1;
	}
}
void DisplayBinTree(BiTree T, int col, int row, int h)
{
	if (T)
	{
		gotoxy(col, row);
		printf("%c", T->data);
		DisplayBinTree(T->LChild, col - h, row + 1, h / 2);
		DisplayBinTree(T->RChild, col + h, row + 1, h / 2);
	}
}
void DisplayTree(BiTree T)
{
	int k = 0;
	k = GetHightOfTree(T);
	DisplayBinTree(T, (int)pow(2, k - 1) * 2 + 1, 4, (int)pow(2, k - 1));
	printf("\n\n\n");
}
int main()
{
	BiTree T;
	printf("请采用先序遍历输入:\n");
	T = CreateBiTree();
	printf("输出二叉树的树形结构");
	DisplayTree(T);
	printf("\n先序遍历输出\n");
	PreOrder(T);
	printf("\n中序遍历输出\n");
	InOrder(T);
	printf("\n后序遍历输出\n");
	Postorder(T);
	printf("\n层次遍历输出\n");
	Levelorder(T);
	return 1;
}

运行截图

二叉树的非递归遍历算法_第11张图片

你可能感兴趣的:(算法,数据结构,c语言)