数据结构二叉树遍历

实现二叉树的遍历及其动画演示

什么是二叉树

二叉树是一种常见的数据结构,它由节点和边组成,每个节点最多有两个子节点。在二叉树中,有三种常见的遍历方式:前序遍历、中序遍历和后序遍历。此外,还有一种层次遍历方式。下面分别介绍这些遍历方式:

给大家推荐一个国内免费使用的chatGpt:Sider -- ChatGPT Sidebar, GPT-4, Draw & Web access

1.前序遍历
前序遍历是指从根节点开始,先遍历根节点,然后遍历左子树,最后遍历右子树。具体步骤如下:
(1)访问根节点;
(2)递归遍历左子树;
(3)递归遍历右子树。

2.中序遍历
中序遍历是指从根节点开始,先遍历左子树,然后遍历根节点,最后遍历右子树。具体步骤如下:
(1)递归遍历左子树;
(2)访问根节点;
(3)递归遍历右子树。

3.后序遍历
后序遍历是指从根节点开始,先遍历左子树,然后遍历右子树,最后遍历根节点。具体步骤如下:
(1)递归遍历左子树;
(2)递归遍历右子树;
(3)访问根节点。

4.层次遍历
层次遍历是指从根节点开始,按照层次顺序依次遍历每个节点。具体步骤如下:
(1)将根节点入队;
(2)从队列中取出一个节点,访问它;
(3)将该节点的左子节点和右子节点入队;
(4)重复步骤2和3,直到队列为空。

以上是四种常见的二叉树遍历方式。在实际应用中,根据不同的问题和需求,可以选择不同的遍历方式。例如,前序遍历可以用于复制二叉树,中序遍历可以用于排序,后序遍历可以用于计算表达式的值,层次遍历可以用于搜索最短路径等。

使用easy-X实现动画的演示。

Easy-X是一款基于C++的图形库,可以用来实现简单的图形绘制和动画效果。使用Easy-X可以方便地创建窗口、绘制图形、播放音频等。下面是使用Easy-X实现动画的基本步骤:

  1. 创建窗口 使用initgraph函数创建一个窗口,设置窗口的大小和标题等参数。

  2. 绘制图形 使用各种绘图函数(如line、circle、rectangle等)绘制图形,可以设置颜色、线条粗细等参数。

  3. 实现动画效果 使用循环结构(如while或for)控制动画的帧数和时间间隔,每帧更新图形的位置、大小等参数,实现动画效果。

  4. 清除图形 在每次更新图形之前,使用cleardevice函数清除上一帧的图形,避免图形叠加。

  5. 关闭窗口 使用closegraph函数关闭窗口,释放资源。

以上是使用Easy-X实现动画的基本步骤,具体实现方式可以参考Easy-X的官方文档和示例代码。

全部代码如下

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<Stdlib.h>
#include<String.h>
#include<graphics.h>
#include<easyx.h>

#define ERROR 0
#define OK 1
#define Stack_Init_size 100

//二叉树
typedef int status;
typedef char BTrElemType;
typedef struct BiNode {
	//数据
	BTrElemType data;
	//左右孩子
	struct BiNode* lchild;
	struct BiNode* rchild;
}BiNode, * BiTree;



//创建二叉树
BiTree createLinkTree();
//菜单
void menu();

//一:递归 - 前 - 中 - 后 - 层序 - 遍历
//1.1递归前序遍历
void PreOrderTraverse(BiTree T) {
	if (T != NULL) {
		printf("%3c", T->data);
		PreOrderTraverse(T->lchild);
		PreOrderTraverse(T->rchild);
	}
}
//1.2·中序递归遍历
void MidOrderTraverse(BiTree  T) {
	if (T != NULL) {
		MidOrderTraverse(T->lchild);
		printf("%3c", T->data);
		MidOrderTraverse(T->rchild);
	}
}
//1.3·后序递归遍历
void PostOrderTraverse(BiTree T) {
	if (T != NULL) {
		PostOrderTraverse(T->lchild);
		PostOrderTraverse(T->rchild);
		printf("%3c", T->data);
	}
}
//1.4.递归层序遍历
//层序递归遍历需要先求出二叉树的高度,也就是二叉树的深度
//目的是为了进行递归遍历时判断何时才应该打印输出该节点。 

// 求二叉树深度,(求二叉树高度)
//递归遍历求二叉树深度,本质就是求得每个结点的深度然后再返回给上一个结点
//直到返回到树的根结点
int treeHigh(BiTree T) {
	if (T == NULL) {
		return 0;
	}
	else {
		int lhigh = treeHigh(T->lchild);//左子树高度
		int rhigh = treeHigh(T->rchild);//右子树高度
		int maxhigh = lhigh > rhigh ? lhigh + 1 : rhigh + 1;//计算该结点处的深度
		return  maxhigh; //返回该结点处的高度
	}
}
//递归层序打印输出
void levelPrint(BiTree T, int level) {
	if (T != NULL) {
		if (level == 1) {
			//到达本层即打印输出
			printf("%3c", T->data);
		}
		else {
			//递归直到本层
			levelPrint(T->lchild, level - 1);
			levelPrint(T->rchild, level - 1);
		}
	}
}
//递归层序遍历
void levelOrderTravel(BiTree T) {
	int i = 0;
	if (T != NULL) {
		int h = treeHigh(T);
		for (i = 1; i <= h; i++) {
			levelPrint(T, i);
		}
	}
}

//二:非递归-前-中-后-层序-遍历
//非递归主要涉及栈的操作,就是元素入栈出栈

//栈的结构类型定义:
typedef struct SqStack {
	BiTree* base;//栈底指针
	BiTree* top;//栈顶指针
	int stacksize;//栈空间大小
}SqStack;

//2.1栈的初始化
void InitStack(SqStack* s) {
	s->base = (BiTree*)malloc(Stack_Init_size * sizeof(BiNode));
	if (s->base == NULL) {
		exit(0);
	}
	else {
		s->top = s->base;
		s->stacksize = Stack_Init_size;
	}
}
//2.2弹栈,栈尾元素出栈
void Pop(SqStack* s, BiTree* q) {
	if (s->base == s->top) {
		printf("栈空,无法进行出栈操作\n");
	}
	else {
		s->top--;
		*q = *s->top;
	}
}
//2.3入栈
#define StackIncrement 2
void Push(SqStack* s, BiTree p) {
	//满栈就再为其增加空间
	if (s->top - s->base == s->stacksize) {
		s->base = (BiTree*)realloc(s->base, (s->stacksize + StackIncrement) * sizeof(BiNode));
		if (!s->base) {
			printf("内存增加失败\n");
			exit(0);
		}
		else {
			s->top = s->base + s->stacksize;
			s->stacksize += StackIncrement;
		}
	}
	*s->top++ = p;//入栈
}
//2.4判断栈是否为空
status StackEmpty(SqStack* s) {
	if (s->top == s->base) {
		return OK;
	}
	else {
		return ERROR;
	}
}
//2.5取栈顶元素
void GetTop(SqStack* s, BiTree* q) {
	if (s->base == s->top) {
		printf("栈为空,无法进行取栈顶元素的操作\n");
	}
	else {
		BiTree* temp = s->top;
		*q = *(--s->top);
		s->top = temp;
		//取出栈顶元素,但不可改变原本栈顶指针指向的位置
	}
}

//2.6前序非递归遍历
void PreTrave(BiTree T) {
	SqStack* s = (SqStack*)malloc(sizeof(SqStack));
	InitStack(s);
	BiTree p = T, q = NULL;
	while (p || !StackEmpty(s)) {
		if (p != NULL) {
			Push(s, p);
			printf("%3c", p->data);
			p = p->lchild;
		}
		else {
			Pop(s, &q);
			p = q->rchild;
		}
	}
}

//2.7中序非递归遍历
void MidTrave(BiTree T) {
	SqStack* s = (SqStack*)malloc(sizeof(SqStack));
	InitStack(s);
	BiTree p = T, q = NULL;
	while (p || !StackEmpty(s)) {
		if (p != NULL) {
			Push(s, p);
			p = p->lchild;
		}
		else {
			Pop(s, &q);
			printf("%3c", q->data);
			p = q->rchild;
		}
	}
}

//2.8后序非递归
void PostTrave(BiTree T) {
	SqStack* s = (SqStack*)malloc(sizeof(SqStack));
	InitStack(s);
	BiTree p = T, q = NULL;
	BiTree flagNode = NULL;//标志位结点
	BiTree top = NULL;//栈顶元素结点
	while (p || !StackEmpty(s)) {
		if (p != NULL) {
			Push(s, p);//左子树入栈
			p = p->lchild;
		}
		else {
			GetTop(s, &top);
			//进入这个else即可知该结点左孩子为空,若右孩子也为空,则该结点为一个叶子结点,可直接访问
			//若右孩子结点为已访问过的,则该节点为一可访问的父节点
			if (top->rchild == NULL || top->rchild == flagNode) {
				printf("%3c", top->data);
				Pop(s, &q);//弹栈
				flagNode = top;
				p = NULL;
			}
			else {
				//存在未访问的右节点,右节点入栈
				p = top->rchild;
			}
		}
	}
}



//2.9层序非递归
//主要涉及到队列的操作,结点的出队,入队.

//链式队列,存放二叉树结点
typedef struct QNode {
	BiNode* data;
	struct QNode* next;
}Qnode, * QueuePtr;

//队列头指针、尾指针
typedef struct LinkQueue {
	QueuePtr front;
	QueuePtr rear;
}LinkQueue;

//2.9队列初始化,创建一个空队列
void initQueue(LinkQueue& Q) {
	Q.front = (QueuePtr)malloc(sizeof(Qnode));
	Q.rear = Q.front;
	Q.front->next = NULL;
}

//2.10入队
void EnQueue(LinkQueue& Q, BiTree e) {
	QNode* p;
	p = (QueuePtr)malloc(sizeof(Qnode));
	p->data = e;
	p->next = NULL;
	Q.rear->next = p;
	Q.rear = p;
}

//2.11出队
BiTree DeQueue(LinkQueue& Q, BiTree* e) {
	if (Q.front == Q.rear) {
		printf("队列为空,无法进行出队操作\n");
		return NULL;
	}
	else {
		QueuePtr p = Q.front->next;
		*e = p->data;
		Q.front->next = p->next;
		if (p == Q.rear) {
			Q.front = Q.rear;
		}
		return *e;
	}

}
//2.12判断队列是否为空
status QueueEmpty(LinkQueue Q) {
	if (Q.front == Q.rear) {
		return OK;
	}
	else {
		return ERROR;
	}
}
//2.13非递归层序遍历
void LevelTrave(BiTree T) {
	BiTree p = T, temp = NULL;
	LinkQueue Q;
	initQueue(Q);
	EnQueue(Q, p);//根节点入队
	while (!QueueEmpty(Q)) {
		temp = DeQueue(Q, &p);
		printf("%3c", temp->data);
		if (temp->lchild != NULL) {
			EnQueue(Q, temp->lchild);
		}
		if (temp->rchild != NULL) {
			EnQueue(Q, temp->rchild);
		}
	}
}

//三.线索二叉树
typedef char BThrElemType;

typedef struct BiThrNode {
	BThrElemType data;//数据
	struct BiThrNode* lchild;//左孩子
	struct BiThrNode* rchild;//右孩子
	int ltag, rtag;//左右标志域
} BiThrNode, * BiThrTree;

BiThrNode* preNode; // 当前访问节点的前驱(前继结点)

//3.1先序创建线索二叉树
BiThrTree createBiThreadTree() {
	BiThrNode* T;
	char Thdata;
	scanf("%c", &Thdata);
	if (Thdata == '#') {
		return NULL;
	}
	else {
		T = (BiThrNode*)malloc(sizeof(BiThrNode));
		T->data = Thdata;
		//左子树
		T->lchild = createBiThreadTree();
		//右子树
		T->rchild = createBiThreadTree();
		return T;
	}
}

// 3.2中序遍历二叉树线索化
void MakingMidThrTree(BiThrTree T) {
	if (T != NULL) {
		MakingMidThrTree(T->lchild);//线索化左子树

		if (T->lchild != NULL) {
			T->ltag = 0;//存在左孩子
		}
		else {
			T->ltag = 1;//不存在左孩子
			T->lchild = preNode;//左孩子指针域指向前驱结点
		}
		if (preNode->rchild != NULL) {
			preNode->rtag = 0;//存在右孩子
		}
		else {
			preNode->rtag = 1;//不存在右孩子
			preNode->rchild = T;//右孩子指针域指向后继结点
		}
		preNode = T;
		MakingMidThrTree(T->rchild);//线索化右子树
	}
}

// 3.3中序线索二叉树处理
BiThrTree CreateMidThrTree(BiThrTree T) {
	//中序线索二叉树头结点非二叉树的根结点
	BiThrNode* Thead;
	Thead = (BiThrNode*)malloc(sizeof(BiThrNode));

	//头结点
	Thead->ltag = 0;
	Thead->rtag = 1;
	Thead->rchild = Thead;//右孩子指针域暂时指向自身
	Thead->lchild = T;
	preNode = Thead;

	MakingMidThrTree(T);将该二叉树线索化

	//中序遍历尾结点处理 
	preNode->rchild = Thead;
	preNode->rtag = 1;
	Thead->rchild = preNode;
	return Thead;
}
// 3.4遍历中序线索二叉树
void midThrOrderTrave(BiThrTree ThrHead) {
	//线索二叉树头节点非根节点,头节点左孩子指向二叉树的根节点
	BiThrNode* p = ThrHead->lchild;
	while (p != ThrHead) {
		while (p->ltag == 0) {
			p = p->lchild;//找到根节点的最左子树的最左的结点
		}
		printf("%3c", p->data);
		while (p->rtag == 1 && p->rchild != ThrHead) {
			p = p->rchild;
			printf("%3c", p->data);
		}
		p = p->rchild;
	}
}

//四.二叉树遍历动画演示(EasyX)

//4.1 绘制二叉树
void drawTree(FILE* fp1, BiTree t, int x, int y, int r, int x_Extend, int y_Extend) {
	//printf("%4d%4d%4d%4d\n", x, y, x_Extend, y_Extend);
	if (t->lchild != NULL) {//直到左子树的左叶子结点
		line(x, y, x - x_Extend, y + y_Extend);
		drawTree(fp1, t->lchild, x - x_Extend, y + y_Extend, r, x_Extend / 2, y_Extend * 1.2);
	}
	circle(x, y, r);
	outtextxy(x, y, t->data);
	fprintf(fp1, "%d %d %c\n", x, y, t->data);//记录每个结点的坐标信息
	if (t->rchild != NULL) {
		line(x, y, x + x_Extend, y + y_Extend);
		drawTree(fp1, t->rchild, x + x_Extend, y + y_Extend, r, x_Extend / 2, y_Extend * 1.2);
	}
}

//4.2 前序遍历动画演示
void PreEasyXTrave(BiTree T, int x, int y, int r) {
	SqStack* s = (SqStack*)malloc(sizeof(SqStack));
	InitStack(s);
	BiTree p = T, q = NULL;
	char ch, tc;
	int i = 1;
	FILE* fp = fopen("test.txt", "r");
	int x2 = 20, y2 = 800;

	while (p || !StackEmpty(s)) {
		if (p != NULL) {
			Push(s, p);
			//printf("%3c", p->data);
			while (fscanf(fp, "%d %d %c", &x, &y, &ch) == 3) {
				if (ch == p->data) {
					circle(x, y + 60, 20);
					if (i < 10) {
						tc = i + '0';
						outtextxy(x, y + 60, tc);
					}
					else {
						tc = i / 10 + '0';
						outtextxy(x, y + 60, tc);
						tc = i % 10 + '0';
						outtextxy(x + 5, y + 60, tc);
					}
					i++;
					circle(x2, y2, 20);
					outtextxy(x2, y2, p->data);
					x2 += 60;
					_gettch();
					break;
				}
			}
			rewind(fp);
			p = p->lchild;
		}
		else {
			Pop(s, &q);
			p = q->rchild;
		}
	}
	fclose(fp);
}

//4.3中序遍历
void MidEasyXTrave(BiTree T) {
	SqStack* s = (SqStack*)malloc(sizeof(SqStack));
	InitStack(s);
	BiTree p = T, q = NULL;

	char ch, tc;
	int x = 0, y = 0;
	int x2 = 20, y2 = 800;
	int i = 1;
	FILE* fp = fopen("test.txt", "r");

	while (p || !StackEmpty(s)) {
		if (p != NULL) {
			Push(s, p);
			p = p->lchild;
		}
		else {
			Pop(s, &q);
			//printf("%3c", q->data);
			while (fscanf(fp, "%d %d %c", &x, &y, &ch) == 3) {
				if (ch == q->data) {
					circle(x, y + 60, 20);
					if (i < 10) {
						tc = i + '0';
						outtextxy(x, y + 60, tc);
					}
					else {
						tc = i / 10 + '0';
						outtextxy(x, y + 60, tc);
						tc = i % 10 + '0';
						outtextxy(x + 5, y + 60, tc);
					}
					i++;
					circle(x2, y2, 20);
					outtextxy(x2, y2, q->data);
					x2 += 60;
					_gettch();
					break;
				}
			}
			rewind(fp);
			p = q->rchild;
		}
	}
	fclose(fp);
}

//4.4后序遍历
void PostEasyXTrave(BiTree T) {
	SqStack* s = (SqStack*)malloc(sizeof(SqStack));
	InitStack(s);
	BiTree p = T, q = NULL;
	BiTree flagNode = NULL;//标志位结点
	BiTree top = NULL;//栈顶元素结点

	char ch, tc;
	int x = 0, y = 0;
	int x2 = 20, y2 = 800;
	int i = 1;
	FILE* fp = fopen("test.txt", "r");

	while (p || !StackEmpty(s)) {
		if (p != NULL) {
			Push(s, p);//左子树入栈
			p = p->lchild;
		}
		else {
			GetTop(s, &top);
			//进入这个else即可知该结点左孩子为空,若右孩子也为空,则该结点为一个叶子结点,可直接访问
			//若右孩子结点为已访问过的,则该节点为一可访问的父节点
			if (top->rchild == NULL || top->rchild == flagNode) {
				//printf("%3c", top->data);

				while (fscanf(fp, "%d %d %c", &x, &y, &ch) == 3) {
					if (ch == top->data) {
						circle(x, y + 60, 20);
						if (i < 10) {
							tc = i + '0';
							outtextxy(x, y + 60, tc);
						}
						else {
							tc = i / 10 + '0';
							outtextxy(x, y + 60, tc);
							tc = i % 10 + '0';
							outtextxy(x + 5, y + 60, tc);
						}
						i++;
						circle(x2, y2, 20);
						outtextxy(x2, y2, top->data);
						x2 += 60;
						_gettch();
						break;
					}
				}
				rewind(fp);

				Pop(s, &q);//弹栈
				flagNode = top;
				p = NULL;
			}
			else {
				//存在未访问的右节点,右节点入栈
				p = top->rchild;
			}
		}
	}
	fclose(fp);
}

//4.5层序遍历
void LevelEasyXTrave(BiTree T) {
	BiTree p = T, temp = NULL;
	LinkQueue Q;
	initQueue(Q);
	EnQueue(Q, p);//根节点入队

	char ch, tc;
	int x = 0, y = 0;
	int x2 = 20, y2 = 800;
	int i = 1;
	FILE* fp = fopen("test.txt", "r");

	while (!QueueEmpty(Q)) {
		temp = DeQueue(Q, &p);
		//printf("%3c", temp->data);

		while (fscanf(fp, "%d %d %c", &x, &y, &ch) == 3) {
			if (ch == temp->data) {
				circle(x, y + 60, 20);
				if (i < 10) {
					tc = i + '0';
					outtextxy(x, y + 60, tc);
				}
				else {
					tc = i / 10 + '0';
					outtextxy(x, y + 60, tc);
					tc = i % 10 + '0';
					outtextxy(x + 5, y + 60, tc);
				}
				i++;
				circle(x2, y2, 20);
				outtextxy(x2, y2, temp->data);
				x2 += 60;
				_gettch();
				break;
			}
		}
		rewind(fp);

		if (temp->lchild != NULL) {
			EnQueue(Q, temp->lchild);
		}
		if (temp->rchild != NULL) {
			EnQueue(Q, temp->rchild);
		}
	}
	fclose(fp);
}

void settree(BiTree t3) {
	FILE* fp = fopen("test.txt", "w");
	if (fp == NULL) {
		printf("文件打开失败,请重新打开\n");
		exit(0);
	}

	initgraph(1000, 1000, SHOWCONSOLE);	//初始化窗口
	setbkcolor(LIGHTBLUE);	cleardevice();//设置背景颜色
	drawTree(fp, t3, 500, 30, 30, 150, 150);
	fclose(fp);

}

int main() {
	BiTree t1 = NULL;
	BiThrTree t2 = NULL;
	BiThrNode* BiThrHead = NULL;
	BiTree t3 = NULL;
	FILE* fp;
	int choose = 0;
	while (1) {
		menu();
		scanf("%d", &choose);
		getchar();
		if (choose == 20) break;
		switch (choose) {
		case 1:
			printf("前序递归遍历 : ");
			PreOrderTraverse(t1);//前序递归遍历
			printf("\n\n\n");
			break;
		case 2:
			printf("\n中序递归遍历 : ");
			MidOrderTraverse(t1);//中序递归遍历
			printf("\n\n\n");
			break;
		case 3:
			printf("\n后序递归遍历 : ");
			PostOrderTraverse(t1);//后序递归遍历
			printf("\n\n\n");
			break;
		case 4:
			printf("递归层序遍历:");
			levelOrderTravel(t1);
			printf("\n\n\n");
			break;
		case 5:
			printf("\n前序非递归遍历:");
			PreTrave(t1);
			printf("\n\n\n");
			break;
		case 6:
			printf("\n中序非递归遍历:");
			MidTrave(t1);
			printf("\n\n\n");
			break;
		case 7:
			printf("\n后序非递归遍历:");
			PostTrave(t1);
			printf("\n\n\n");
			break;
		case 8:
			printf("\n非递归层序遍历:");
			LevelTrave(t1);
			printf("\n\n\n");
			break;
		case 9:
			printf("\n中序线索化二叉树遍历:");
			midThrOrderTrave(BiThrHead);//中序遍历线索二叉树
			printf("\n\n\n");
			break;
		case 10:
			printf("请输入创建树的结点");
			printf("\t(备注:输入“#”表示结束当前子树的创建)\n输入:");
			t1 = createLinkTree();
			getchar();
			printf("二叉树创建成功,请继续选择操作\n\n\n");
			break;
		case 11:
			printf("为创建的线索化二叉树输入的结点");
			printf("\t(备注:输入“#”表示结束当前子树的创建)\n输入:");
			t2 = createBiThreadTree();//二叉树创建
			getchar();
			BiThrHead = CreateMidThrTree(t2);//创建中序线索二叉树
			printf("线索二叉树创建成功,请继续选择操作\n\n\n");
			break;
		case 13:
			printf("EasyX创建二叉树\n输入:");
			t3 = createLinkTree();
			printf("创建成功!\n");
			break;
		case 14:
			printf("前序遍历动画演示\n");
			settree(t3);
			PreEasyXTrave(t3, 30, 500, 30);
			printf("任意键完成动画演示\n");
			getchar();//防止程序闪退
			closegraph();//关闭窗口
			printf("前序遍历动画演示完成\n");
			break;
		case 15:
			printf("中序遍历动画演示\n");
			settree(t3);
			MidEasyXTrave(t3);
			printf("任意键完成动画演示\n");
			getchar();//防止程序闪退
			closegraph();//关闭窗口
			printf("前序遍历动画演示完成\n");
			break;
		case 16:
			printf("后序遍历动画演示\n");
			settree(t3);
			PostEasyXTrave(t3);
			printf("任意键完成动画演示\n");
			getchar();//防止程序闪退
			closegraph();//关闭窗口
			printf("后序遍历动画演示完成\n");
			break;
		case 17:
			printf("层序遍历动画演示\n");
			settree(t3);
			LevelEasyXTrave(t3);
			printf("任意键完成动画演示\n");
			getchar();//防止程序闪退
			closegraph();//关闭窗口
			printf("层序遍历动画演示完成\n");
			break;
		case 20:
			break;
		default:
			printf("\n\n*************需要退出请输入:20 *************\n\n");
			break;
		}
	}
}

//测试数据
//ABDH##I##EJ##K##CFL##M##GN##O##
//ABD##E##CF###
//ABD##E##CF##G##
//AB##C##
// 
//创建二叉树
BiTree createLinkTree() {
	BiNode* t = NULL;
	BTrElemType Tdata;
	scanf("%c", &Tdata);
	if (Tdata == '#') {
		return NULL;
	}
	else {
		t = (BiNode*)malloc(sizeof(BiNode));
		t->data = Tdata;
		t->lchild = createLinkTree();//左子树
		t->rchild = createLinkTree();//右子树
		return t;
	}
}
//菜单
void menu() {
	printf("**********************菜单选项*************************************\n");
	printf("********                 一:递归                     *************\n");
	printf("*******************************************************************\n");
	printf("********1:前序递归遍历       2:中序递归遍历         *************\n");
	printf("********3:后序递归遍历       4:层序递归遍历         *************\n");
	printf("*******************************************************************\n");
	printf("********                二:非递归                    *************\n");
	printf("*******************************************************************\n");
	printf("********5:前序非递归遍历      6:中序非递归遍历      *************\n");
	printf("********7:后序非递归遍历      8:层序递非归遍历      *************\n");
	printf("*******************************************************************\n");
	printf("********               三:线索二叉树                 *************\n");
	printf("*******************************************************************\n");
	printf("********9:中序线索化二叉树的遍历                     *************\n");
	printf("*******************************************************************\n");
	printf("********               四:创建二叉树                 *************\n");
	printf("*******************************************************************\n");
	printf("********10:二叉树创建         11:线索二叉树创建     *************\n");
	printf("*******************************************************************\n");
	printf("********           五:二叉树前-中-后-层序遍历动画演示*************\n");
	printf("*******************************************************************\n");
	printf("********13:使用EasyX绘制二叉树                       *************\n");
	printf("********14:前序遍历       15:中序遍历               *************\n");
	printf("********16:后序遍历       17:层序遍历               *************\n");
	printf("*******************************************************************\n");
	printf("********20:退出                                      *************\n");
	printf("*******************************************************************\n");
	printf("请输入:");
}

二叉树遍历特性主要包括三种遍历方式:先序遍历、中序遍历和后序遍历。先序遍历是指先访问根节点,然后按照先序遍历的顺序依次访问左子树和右子树。中序遍历是指先访问左子树,然后访问根节点,最后访问右子树。后序遍历是指先访问左子树,然后访问右子树,最后访问根节点。这三种遍历方式都是通过递归或者使用辅助数据结构(如栈或队列)来实现的。其中,递归是一种较为简洁的实现方式,但由于递归的栈帧消耗较大,所以使用非递归的方式来遍历二叉树也是非常有必要的。非递归遍历二叉树可以借助队列的先进先出的特性来实现。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [数据结构7:基本的二叉树遍历及题目](https://blog.csdn.net/m0_53607711/article/details/128331361)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [数据结构实验 二叉树遍历方法](https://download.csdn.net/download/yuan7376313/3174711)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值