二叉树-四序遍历 前序遍历 中序遍历 后序遍历 层序遍历(C语言)(图解+详细注释)(附代码)(多种方法实现)

废话不多说,先看看目录,了解本博客个大概,然后直接起飞、上干货!!!

一、图解四序遍历

在这里,不过多赘述,有前人写的非常优秀的博客,值得一看(链接如下)

http://t.csdnimg.cn/YlDf6

这是我看过的最形象、简单、易懂、通彻的图解四序遍历,没有之一,博主动图做得非常好,别忘了给他收藏、点赞!(由于这博主没有给出层序遍历的代码,所以我稍作补充)

 二、先前准备

1. 定义二叉树结点结构体

// 定义二叉树节点结构体
typedef struct TreeNode {
    int val;
    struct TreeNode* left;
    struct TreeNode* right;
}TreeNode, * BiTree;

2. 通过键盘录入创建二叉树

输入案例:

8 7 5 1 -1 -1 -1 4 -1 -1 6 3 -1 -1 2 -1 -1
// 创建新的二叉树节点
void CreateBiTree(BiTree* T)
{ // 形参是 结点指针的指针 因为结点指针需要改变 所以使用指针
	int x;
	scanf("%d", &x);  // 键盘录入
	*T = (BiTree)malloc(sizeof(TreeNode));
	if (x == -1)
		*T = NULL;	// 空结点
	else if (x == '\n')
		return;	 // 回车-创建结束-函数返回结束执行
	else
	{
		if (!(*T))
			exit(0);
		(*T)->val = x;  // 前序,输入
		CreateBiTree(&(*T)->left); // 左结点指针的地址
		CreateBiTree(&(*T)->right); // 右结点指针的地址
	}
}

三、前序遍历

1. 递归式

// 前序遍历二叉树(递归)
void PreOrderTraverse(BiTree T)
{
	if (T == NULL)
		return;
	printf("%d ", T->val);
	PreOrderTraverse(T->left);
	PreOrderTraverse(T->right);
}

2. 非递归式

// 前序遍历二叉树(非递归)
void PreorderTraversalIterative(BiTree T)
{ // 需要利用栈的知识
	if (T == NULL)
		return;

	BiTree stack[1000]; // 创建 树-栈
	int top = -1;
	stack[++top] = T;

	while (top >= 0) {
		BiTree node = stack[top--];
		printf("%d ", node->val);

		if (node->right != NULL)  // 先右后左
			stack[++top] = node->right;

		if (node->left != NULL) // @ 之所以 左结点后进栈,是因为,左结点必须先出栈,才能符合遍历的条件
			stack[++top] = node->left;
	}
}

四、中序遍历

1. 递归式

// 中序遍历二叉树(递归)
void InOrderTraverse(BiTree T)
{
	if (T == NULL)
		return;
	InOrderTraverse(T->left);
	printf("%d ", T->val);
	InOrderTraverse(T->right);
}

2. 非递归式

// 中序遍历二叉树(非递归)
void InorderTraversalIterative(BiTree T) {
	if (T == NULL)
		return;

	BiTree stack[1000];
	int top = -1;

	BiTree curr = T;
	while (curr != NULL || top >= 0) {
		while (curr != NULL) {
			stack[++top] = curr;
			curr = curr->left;
		}

		curr = stack[top--];
		printf("%d ", curr->val);

		curr = curr->right;
	}
}

五、后序遍历

1. 递归式

// 后序遍历二叉树(递归)
void PostOrderTraverse(BiTree T)
{
	if (T == NULL)
		return;
	PostOrderTraverse(T->left);
	PostOrderTraverse(T->right);
	printf("%d ", T->val);
}

2. 非递归式

 // 后序遍历二叉树(非递归)
void PostorderTraversalIterative(BiTree T) {
	if (T == NULL) {
		return;
	}

	BiTree stack1[1000];
	int top1 = -1;
	BiTree stack2[1000];
	int top2 = -1;

	stack1[++top1] = T;
	while (top1 >= 0) {
		BiTree curr = stack1[top1--];
		stack2[++top2] = curr;

		if (curr->left != NULL) {
			stack1[++top1] = curr->left;
		}

		if (curr->right != NULL) {
			stack1[++top1] = curr->right;
		}
	}

	while (top2 >= 0) {
		BiTree node = stack2[top2--];
		printf("%d ", node->val);
	}
}

六、层序遍历

// 使用队列 层序遍历二叉树
void QueueLevelOrderTraversal(BiTree root) {
    if (root == NULL) {
        return;
    }

    // 创建一个队列来保存待访问的节点
    // @ 其实并不是让结点入队列,本质上来说,是让每个结点的地址入队列
    // @ 不然一个结点又有数据域,又有指针域,占这么大内存,怎么入队列呀
    // @ 所以队列要开辟的空间,其实就是为 很多个 结点指针变量 开辟空间,所以这里是**,俩*
    BiTree* queue = (BiTree*)malloc(sizeof(BiTree) * 1000);
    int front = 0;  // 队列的前指针,为什么初始化0,因为queue是指针数组,索引从0开始。
    int rear = 0;   // 队列的后指针

    // 将根节点入队列
    queue[rear++] = root;

    while (front < rear) {
        // 出队列并访问节点
        BiTree node = queue[front++];
        printf("%d ", node->val);

        // 将左右子节点入队列
        if (node->left) {
            queue[rear++] = node->left; // @ 倒像是 “双指针”!!!
        }
        if (node->right) {
            queue[rear++] = node->right;
        }
    }

    // 释放队列内存
    free(queue);
}

七、完整代码

#include <stdio.h>
#include <stdlib.h>

// 定义二叉树节点结构
typedef struct TreeNode {
    int val;
    struct TreeNode* left;
    struct TreeNode* right;
}TreeNode, * BiTree;

// 创建新的二叉树节点
void CreateBiTree(BiTree* T)
{ // 形参是 结点指针的指针 因为结点指针需要改变 所以使用指针
	int x;
	scanf("%d", &x);  // 键盘录入
	*T = (BiTree)malloc(sizeof(TreeNode));
	if (x == -1)
		*T = NULL;	// 空结点
	else if (x == '\n')
		return;	 // 回车-创建结束-函数返回结束执行
	else
	{
		if (!(*T))
			exit(0);
		(*T)->val = x;  // 前序,输入
		CreateBiTree(&(*T)->left); // 左结点指针的地址
		CreateBiTree(&(*T)->right); // 右结点指针的地址
	}
}


// 使用队列 层序遍历二叉树
void LevelOrderTraversal(BiTree root) {
    if (root == NULL) {
        return;
    }

    // 创建一个队列来保存待访问的节点
    // @ 其实并不是让结点入队列,本质上来说,是让每个结点的地址入队列
    // @ 不然一个结点又有数据域,又有指针域,占这么大内存,怎么入队列呀
    // @ 所以队列要开辟的空间,其实就是为 很多个 结点指针变量 开辟空间,所以这里是**,俩*
    BiTree* queue = (BiTree*)malloc(sizeof(BiTree) * 1000);
    int front = 0;  // 队列的前指针,为什么初始化0,因为queue是指针数组,索引从0开始。
    int rear = 0;   // 队列的后指针

    // 将根节点入队列
    queue[rear++] = root;

    while (front < rear) {
        // 出队列并访问节点
        BiTree node = queue[front++];
        printf("%d ", node->val);

        // 将左右子节点入队列
        if (node->left) {
            queue[rear++] = node->left; // @ 倒像是 “双指针”!!!
        }
        if (node->right) {
            queue[rear++] = node->right;
        }
    }

    // 释放队列内存
    free(queue);
}


// 前序遍历二叉树(递归)
void PreOrderTraverse(BiTree T)
{
	if (T == NULL)
		return;
	printf("%d ", T->val);
	PreOrderTraverse(T->left);
	PreOrderTraverse(T->right);
}


// 中序遍历二叉树(递归)
void InOrderTraverse(BiTree T)
{
	if (!T)
		return;
	InOrderTraverse(T->left);
	printf("%d ", T->val);
	InOrderTraverse(T->right);
}

// 后序遍历二叉树(递归)
void PostOrderTraverse(BiTree T)
{
	if (T == NULL)
		return;
	PostOrderTraverse(T->left);
	PostOrderTraverse(T->right);
	printf("%d ", T->val);
}


// 先序遍历二叉树(非递归)
void PreorderTraversalIterative(BiTree T)
{ // @ 利用栈的知识,重要,必须掌握!!!
	if (T == NULL)
		return;

	BiTree stack[1000]; // 创建 树-栈
	int top = -1;
	stack[++top] = T;

	while (top >= 0) {
		BiTree node = stack[top--];
		printf("%d ", node->val);

		if (node->right != NULL)  // 先右后左
			stack[++top] = node->right;

		if (node->left != NULL) // @ 之所以 左结点后进栈,是因为,左结点必须先出栈,才能符合遍历的条件
			stack[++top] = node->left;
	}
}

// 中序遍历二叉树(非递归)
void InorderTraversalIterative(BiTree T) {
	if (T == NULL)
		return;

	BiTree stack[1000];
	int top = -1;

	BiTree curr = T;
	while (curr != NULL || top >= 0) {
		while (curr != NULL) {
			stack[++top] = curr;
			curr = curr->left;
		}

		curr = stack[top--];
		printf("%d ", curr->val);

		curr = curr->right;
	}
}

// 后序遍历二叉树(非递归)
void PostorderTraversalIterative(BiTree T) {
	if (T == NULL) {
		return;
	}

	BiTree stack1[1000];
	int top1 = -1;
	BiTree stack2[1000];
	int top2 = -1;

	stack1[++top1] = T;
	while (top1 >= 0) {
		BiTree curr = stack1[top1--];
		stack2[++top2] = curr;

		if (curr->left != NULL) {
			stack1[++top1] = curr->left;
		}

		if (curr->right != NULL) {
			stack1[++top1] = curr->right;
		}
	}

	while (top2 >= 0) {
		BiTree node = stack2[top2--];
		printf("%d ", node->val);
	}
}



int main() {
    // 构建一个二叉树
	BiTree T;
	CreateBiTree(&T); // 实参为 根结点指针的地址

    // 层序遍历二叉树
    printf("层序遍历结果:");
    LevelOrderTraversal(T);
	printf("\n");

	for (int i = 0; i < 10; i++)
		printf("**");
	printf("递归式 前中后 三序遍历");
	for (int i = 0; i < 10; i++)
		printf("**");
	printf("\n");

	printf("递归式前序遍历二叉树:");
	PreOrderTraverse(T);
	printf("\n");

	printf("递归式中序遍历二叉树:");
	InOrderTraverse(T);
	printf("\n");

	printf("递归式后序遍历二叉树:");
	PostOrderTraverse(T);
	printf("\n");

	for (int i = 0; i < 10; i++)
		printf("**");
	printf("非递归式 前中后 三序遍历");
	for (int i = 0; i < 10; i++)
		printf("**");
	printf("\n");

	printf("前序遍历二叉树(非递归):");
	PreorderTraversalIterative(T);
	printf("\n");

	printf("中序遍历二叉树(非递归):");
	InorderTraversalIterative(T);
	printf("\n");

	printf("后序遍历二叉树(非递归):");
	PostorderTraversalIterative(T);
	printf("\n");

    return 0;
}

制作不易,能点个赞支持一下吗,您的鼓励,是我前行的最大动力!

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值