二叉树的先序、中序、后序、层次四种遍历(递归和非递归)

二叉树的遍历

我这里写了二叉树的四种遍历算法:
二叉树的先序、中序、后序 —— 递归和非递归
二叉树的层次遍历 —— 非递归遍历

OK 开始我们的正文!要看完整代码直接滑动到最后!

在进行各种遍历算法前,先创建我们的二叉树:下图是随便画的一个二叉树,我们就创建这个二叉树

二叉树的先序、中序、后序、层次四种遍历(递归和非递归)_第1张图片

定义结点 并且 创建二叉树 (这里是将有关的代码从源代码中摘出来放在一起)

//定义节点
typedef struct Node
{
	char date;               //存储结点数据
	struct Node *left_child; //指向左孩子的指针域
	struct Node *right_child;//指向右孩子的指针域
}Tnode, *Pnode;
//创建树
void Creat_tree(Pnode root, Pnode left_child, Pnode right_child, char date)
{
	root->date = date;      //将数据放入结点的数据域
	root->left_child = left_child; //让左指针指向左孩子
	root->right_child = right_child; //让右指针指向右孩子
}

Tnode A, B, C, D, E, F, G;  //定义结点变量
//创建树
Creat_tree(&A, &C, &D, 'A');
Creat_tree(&C, &B, &E, 'C');
Creat_tree(&E, NULL, NULL, 'E');
Creat_tree(&B, &F, NULL, 'B');
Creat_tree(&F, NULL, NULL, 'F');
Creat_tree(&D, NULL, &G, 'D');
Creat_tree(&G, NULL, NULL, 'G');

二叉树创建完毕!
//---------------------------以下是先序、中序、后序递归遍历---------------------

//----递归先序遍历----
void PreorderR(Pnode root)
{
	if (NULL == root)  //如果结点为空直接返回
		return;
	printf("%c ", root->date);
	PreorderR(root->left_child); //递归先序遍历左子树
	PreorderR(root->right_child);//递归先序遍历右子数
}
//----递归中序遍历----
void InorderR(Pnode root)
{
	if (NULL == root)
		return;
	InorderR(root->left_child); //递归中序遍历左子树
	printf("%c ", root->date);
	InorderR(root->right_child);//递归中序遍历右子树
}
//----递归后续遍历----
void postorderR(Pnode root)
{
	if (NULL == root)
		return;
	postorderR(root->left_child);  //递归后序遍历左子树
	postorderR(root->right_child); //递归后序遍历右子树
	printf("%c ", root->date);
}
//递归先序遍历
printf("************递归先序遍历***************\n");
PreorderR(&A);  //传入根结点
printf("\n");

//递归中序遍历
printf("************递归中序遍历***************\n");
InorderR(&A);   //传入根结点
printf("\n");

//递归后续遍历
printf("************递归后续遍历***************\n");
postorderR(&A); //传入根结点
printf("\n");

//---------------------------以下是先序、中序、后序非递归遍历(非递归层次遍历在最后)---------------------

//初始化栈
void stack_init(Pstack pstack)
{
	pstack->top = -1;  //将栈指针设定为-1
}
//判断栈空
int stack_empty(Pstack pstack)
{
	return (-1 == pstack->top);
}
//判断栈满
int stack_full(Pstack pstack)
{
	return (MAX - 1 == pstack->top);
}
//入栈
void push(Pnode root, Pstack pstack)
{
    //第一种
	pstack->top++;
	pstack->stack[pstack->top] = root;
	//第二种
	//pstack->stack[++pstack->top] = root;
	//两种写法都行
}
//出栈
Pnode pop(Pnode root, Pstack pstack)
{
	return pstack->stack[pstack->top--];
}
//----非递归先序遍历----
void PreorderI(Pnode root, Pstack pstack)
{
	//初始化栈
	stack_init(pstack);
	while (root || !stack_empty(pstack))
	{
		if (root)
		{
			if (!stack_full(pstack))
			{
				printf("%c ", root->date);
				push(root, pstack);      //将结点入栈
				root = root->left_child;
			}
			else
			{
				printf("栈满,无法入栈!\n");
				return;
			}
		}
		else
		{
			root = pop(root, pstack);
			root = root->right_child;
		}
	}
}
//----非递归中序遍历----
void InorderI(Pnode root, Pstack pstack)
{
	stack_init(pstack);   //初始化栈
	while (root || !stack_empty(pstack))
	{
		if (root)
		{
			if (!stack_full(pstack))
			{
				push(root, pstack);
				root = root->left_child;
			}
			else
			{
				printf("栈满,无法入栈!\n");
				return;
			}
		}
		else
		{
			root = pop(root, pstack);
			printf("%c ", root->date);
			root = root->right_child;
		}
	}
}
//----非递归后序遍历----
void postorderI(Pnode root, Pstack pstack)
{
	stack_init(pstack); //初始化栈
	int arr[MAX];   //存放结点的标志位(0:右子树没有被访问,1:右子树被访问)
	int p = -1;       
	while (root || !stack_empty(pstack))
	{
		if (root)
		{
			if (!stack_full(pstack))
			{
				push(root, pstack);
				p++;
				arr[p] = 0;
				root = root->left_child;
			}
			else
			{
				printf("栈满,无法入栈!\n");
				return;
			}
		}
		else
		{
			root = pop(root, pstack);
			if (0 == arr[p])
			{
				arr[p] = 1;
				push(root, pstack);
				root = root->right_child;
			}
			else
			{
				p--;
				printf("%c ", root->date);
				root = NULL;
			}
		}
	}
}
//非递归先序遍历
printf("************非递归先序遍历***************\n");
PreorderI(&A, &stack); //传入根结点
printf("\n");

//非递归中序遍历
printf("************非递归中序遍历***************\n");
InorderI(&A, &stack); //传入根结点
printf("\n");

//非递归后续遍历
printf("************非递归后续遍历***************\n");
postorderI(&A, &stack);  //传入根结点
printf("\n");

//------------------非递归层次遍历-----------------

//定义队(用于非递归层次遍历)
typedef struct queue
{
	Pnode arr[MAX + 1];     //存放指向结点的指针
	int front;
	int rear;
}Queue, *Pqueue;

Queue queue;                //声明队
//初始化队列
void queue_init(Pqueue pqueue)
{
	pqueue->front = 0;
	pqueue->rear = 0;
}
//判断队空
int queue_empty(Pqueue pqueue)
{
	return (pqueue->rear == pqueue->front);
}
//判断队满
int queue_full(Pqueue pqueue)
{
	return ((pqueue->rear + 1) % (MAX + 1) == pqueue->front);
}
//入队
void push_queue(Pnode root, Pqueue pqueue)
{
	pqueue->arr[pqueue->rear++] = root;
}
//出队
Pnode pop_queue(Pnode root, Pqueue pqueue)
{
	return pqueue->arr[pqueue->front++];
}
//----非递归层次遍历----
void LevelorderI(Pnode root, Pqueue pqueue)
{
	if (root == NULL)
		return;
	push_queue(root, pqueue);
	while (!queue_empty(pqueue))
	{
		if (!queue_empty(pqueue))
		{
			root = pop_queue(root, pqueue);
			printf("%c ", root->date);
		}
		if (!queue_full(pqueue))
		{
			if (root->left_child != NULL)
				push_queue(root->left_child, pqueue);
			if (root->right_child != NULL)
				push_queue(root->right_child, pqueue);
		}
		else
		{
			printf("队满,无法入队!\n");
			return;
		}		
	}
}

完整代码:

#include 
#define MAX 7 //栈空和队的空间的大小
//定义节点
typedef struct Node
{
	char date;               //存储结点数据
	struct Node *left_child; //左孩子域
	struct Node *right_child;//右孩子域
}Tnode, *Pnode;
//定义栈(用于非递归先、中、后三种遍历)
typedef struct stack
{
	Pnode stack[MAX];       //存放指向结点的指针
	int top;                //栈指针
}Stack, *Pstack;
//定义队(用于非递归层次遍历)
typedef struct queue
{
	Pnode arr[MAX + 1];     //存放指向结点的指针
	int front;
	int rear;
}Queue, *Pqueue;
//创建树
void Creat_tree(Pnode root, Pnode left_child, Pnode right_child, char date)
{
	root->date = date;
	root->left_child = left_child;
	root->right_child = right_child;
}

//----------三种递归遍历-------------
//递归先序遍历
void PreorderR(Pnode root)
{
	if (NULL == root)  //如果结点为空直接返回
		return;
	printf("%c ", root->date);
	PreorderR(root->left_child); //递归先序遍历左子树
	PreorderR(root->right_child);//递归先序遍历右子数
}
//递归中序遍历
void InorderR(Pnode root)
{
	if (NULL == root)
		return;
	InorderR(root->left_child); //递归中序遍历左子树
	printf("%c ", root->date);
	InorderR(root->right_child);//递归中序遍历右子树
}
//递归后续遍历
void postorderR(Pnode root)
{
	if (NULL == root)
		return;
	postorderR(root->left_child);  //递归后序遍历左子树
	postorderR(root->right_child); //递归后序遍历右子树
	printf("%c ", root->date);
}

//------------四种非递归遍历---------------

//初始化栈
void stack_init(Pstack pstack)
{
	pstack->top = -1;
}
//判断栈空
int stack_empty(Pstack pstack)
{
	return (-1 == pstack->top);
}
//判断栈满
int stack_full(Pstack pstack)
{
	return (MAX - 1 == pstack->top);
}
//入栈
void push(Pnode root, Pstack pstack)
{
	//pstack->top++;
	pstack->stack[++pstack->top] = root;
}
//出栈
Pnode pop(Pnode root, Pstack pstack)
{
	return pstack->stack[pstack->top--];
}

//----非递归先序遍历----
void PreorderI(Pnode root, Pstack pstack)
{
	//初始化栈
	stack_init(pstack);
	while (root || !stack_empty(pstack))
	{
		if (root)
		{
			if (!stack_full(pstack))
			{
				printf("%c ", root->date);
				push(root, pstack);      //将结点入栈
				root = root->left_child;
			}
			else
			{
				printf("栈满,无法入栈!\n");
				return;
			}
		}
		else
		{
			root = pop(root, pstack);
			root = root->right_child;
		}
	}
}
//----非递归中序遍历----
void InorderI(Pnode root, Pstack pstack)
{
	stack_init(pstack);   //初始化栈
	while (root || !stack_empty(pstack))
	{
		if (root)
		{
			if (!stack_full(pstack))
			{
				push(root, pstack);
				root = root->left_child;
			}
			else
			{
				printf("栈满,无法入栈!\n");
				return;
			}
		}
		else
		{
			root = pop(root, pstack);
			printf("%c ", root->date);
			root = root->right_child;
		}
	}
}
//----非递归后序遍历----
void postorderI(Pnode root, Pstack pstack)
{
	stack_init(pstack); //初始化栈
	int arr[MAX];   //存放结点的标志位(0:右子树没有被访问,1:右子树被访问)
	int p = -1;       
	while (root || !stack_empty(pstack))
	{
		if (root)
		{
			if (!stack_full(pstack))
			{
				push(root, pstack);
				p++;
				arr[p] = 0;
				root = root->left_child;
			}
			else
			{
				printf("栈满,无法入栈!\n");
				return;
			}
		}
		else
		{
			root = pop(root, pstack);
			if (0 == arr[p])
			{
				arr[p] = 1;
				push(root, pstack);
				root = root->right_child;
			}
			else
			{
				p--;
				printf("%c ", root->date);
				root = NULL;
			}
		}
	}
}

//初始化队列
void queue_init(Pqueue pqueue)
{
	pqueue->front = 0;
	pqueue->rear = 0;
}
//判断队空
int queue_empty(Pqueue pqueue)
{
	return (pqueue->rear == pqueue->front);
}
//判断队满
int queue_full(Pqueue pqueue)
{
	return ((pqueue->rear + 1) % (MAX + 1) == pqueue->front);
}
//入队
void push_queue(Pnode root, Pqueue pqueue)
{
	pqueue->arr[pqueue->rear++] = root;
}
//出队
Pnode pop_queue(Pnode root, Pqueue pqueue)
{
	return pqueue->arr[pqueue->front++];
}
//----非递归层次遍历----
void LevelorderI(Pnode root, Pqueue pqueue)
{
	if (root == NULL)
		return;
	push_queue(root, pqueue);
	while (!queue_empty(pqueue))
	{
		if (!queue_empty(pqueue))
		{
			root = pop_queue(root, pqueue);
			printf("%c ", root->date);
		}
		if (!queue_full(pqueue))
		{
			if (root->left_child != NULL)
				push_queue(root->left_child, pqueue);
			if (root->right_child != NULL)
				push_queue(root->right_child, pqueue);
		}
		else
		{
			printf("队满,无法入队!\n");
			return;
		}		
	}
}

int main()
{
	Tnode A, B, C, D, E, F, G;  //定义结点变量
	Stack stack;                //定义栈
	Queue queue;                //定义队
	//创建树
	Creat_tree(&A, &C, &D, 'A');
	Creat_tree(&C, &B, &E, 'C');
	Creat_tree(&E, NULL, NULL, 'E');
	Creat_tree(&B, &F, NULL, 'B');
	Creat_tree(&F, NULL, NULL, 'F');
	Creat_tree(&D, NULL, &G, 'D');
	Creat_tree(&G, NULL, NULL, 'G');

	//递归先序遍历
	printf("************递归先序遍历***************\n");
	PreorderR(&A);  //传入根结点
	printf("\n");

	//递归中序遍历
	printf("************递归中序遍历***************\n");
	InorderR(&A);   //传入根结点
	printf("\n");

	//递归后续遍历
	printf("************递归后续遍历***************\n");
	postorderR(&A); //传入根结点
	printf("\n");

	//非递归先序遍历
	printf("************非递归先序遍历***************\n");
	PreorderI(&A, &stack); //传入根结点
	printf("\n");

	//非递归中序遍历
	printf("************非递归中序遍历***************\n");
	InorderI(&A, &stack); //传入根结点
	printf("\n");

	//非递归后续遍历
	printf("************非递归后续遍历***************\n");
	postorderI(&A, &stack);  //传入根结点
	printf("\n");

	//非递归层次遍历
	printf("*************非递归层次遍历***************\n");
	queue_init(&queue);//初始化队
	LevelorderI(&A, &queue);  //传入根结点
	printf("\n");

	return 0;
}

你可能感兴趣的:(算法与数据结构,二叉树,数据结构)