数据结构实验7---二叉树的应用

(1)实验目的

通过该实验,使学生理解二叉树的链式存储,掌握二叉树的几种遍历算法,并通过该实验使学生理解递归的含义,掌握C语言编写递归函数的方法和注意事项。

(2)实验内容

实现教材中算法6.4描述的二叉树创建算法,在此基础上实现二叉树的先序、后序递归遍历算法、两种非递归中序遍历、层序遍历、求二叉树的深度。注意:在非递归算法中用到栈和队列时,不要调用系统的栈和队列,需要自己实现栈和队列的操作。

(3)参考界面

 

(4)验收/测试用例

  1. 创建

输入 :ABC$$DE$G$$F$$$       ($表示空格)

该输入对应的树如图所示

  1. 先序   屏幕输出  A B C D E G F
  2. 后序   屏幕输出  C G E F D B A
  3. 中序   屏幕输出  C B E G D F A     

(两种中序非递归还需看源代码)

  1. 层序   屏幕输出  A B C D E F G
  2. 深度   屏幕显示 深度为5
  3. 另外自己画出一棵树,再测试一遍
#include<iostream>
using namespace std;
#define STACK_INIT_SIZE 100  //存储空间分配初始量
#define STACKINCREMENT 10  
typedef int status;
typedef int TElement;//二叉树
typedef int QElemType;//队列
typedef int SElemType;//栈
//二叉树的结构体
typedef struct BiTNode {//定义一个结构体用来存储二叉链表
	TElement data;//数据域
	struct BiTNode* lchild, * rchild;//左右孩子指针域
}BiTNode, * BiTree;//BiTree表示这个指针,里面包含数据域,指针域
BiTree T;
//栈的结构体
typedef struct {
	BiTree* base;
	int top;
	int stacksize;
}SqStack;
SqStack S;
//队列的结构体
typedef struct QNode {
	BiTree data;
	struct QNode* next;
}QNode, * QueuePtr;
typedef struct {
	QueuePtr front;
	QueuePtr rear;
}LinkQueue;

LinkQueue Q;
BiTree CreateBiTree(BiTree& T);//1
status FirstBiTree(BiTree& T);//2
status CenterBiTreeOne(BiTree& T);//3
status CenterBiTreeTwo(BiTree& T);//4
status LastBiTree(BiTree& T);//5
status LevelBiTree(BiTree& T);//6
status Depth(BiTree& T);//7

int main() {
	cout << "~~~~~~用户选择界面~~~~~~" << endl;
	cout << "1、创建二叉树" << endl;
	cout << "2、先序遍历二叉树" << endl;
	cout << "3、中序遍历二叉树1" << endl;
	cout << "4、中序遍历二叉树2" << endl;
	cout << "5、后序遍历二叉树" << endl;
	cout << "6、层序遍历二叉树" << endl;
	cout << "7、求二叉树的深度" << endl;
	cout << "输入一个负数退出" << endl;
	int x;
	while (1) {
		cout << "-------------------------" << endl;
		cout << "请输入您的选择:" ;
		cin >> x;
		if (x < 0) {
			cout << "程序已经退出" << endl;
			break;
		}
		else {
			switch (x) {
			case 1:
				cout << "请将您想要创建的二叉树按先序输入,每个结点都必须有孩子,没有的就输入$" << endl;
				CreateBiTree(T);
				cout << "输入完毕,二叉树创建成功" << endl;
				break;
			case 2:
				if (T == NULL) {
					cout << "请先创建二叉树" << endl;
				}
				else {
					cout << "前序遍历二叉树的结果是:" << endl;
					FirstBiTree(T);
					cout << " " << endl;
				}
				break;
			case 3:
				if (T == NULL) {
					cout << "请先创建二叉树" << endl;
				}
				else {
					cout << "方法一中序遍历二叉树的结果是:" << endl;
					CenterBiTreeOne(T);
					cout << " " << endl;
				}
				break;
			case 4:
				if (T == NULL) {
					cout << "请先创建二叉树" << endl;
				}
				else {
					cout << "方法二中序遍历二叉树的结果是:" << endl;
					CenterBiTreeTwo(T);
					cout << " " << endl;
				}
				break;
			case 5:
				if (T == NULL) {
					cout << "请先创建二叉树" << endl;
				}
				else {
					cout << "后序遍历二叉树的结果是:" << endl;
					LastBiTree(T);
					cout << " " << endl;
				}
				break;
			case 6:
				if (T == NULL) {
					cout << "请先创建二叉树" << endl;
				}
				else {
					cout << "层序遍历二叉树的结果是:" << endl;
					LevelBiTree(T);
					cout << " " << endl;
				}
				break;
			case 7:
				if (T == NULL) {
					cout << "请先创建二叉树" << endl;
				}
				else {
					cout << "二叉树的深度是:" << endl;
					int depth = Depth(T);
					cout << depth << endl;
				}
				break;
			}
		}
	}
	system("pause");
	return 0;
}
//1、创建二叉树
BiTree CreateBiTree(BiTree& T) {
	char ch;
	cin >> ch;
	if (ch == '$')T = NULL;
	else {
		if (!(T = (BiTNode*)malloc(sizeof(BiTNode))))exit(OVERFLOW);
		T->data = ch;
		CreateBiTree(T->lchild);//由于不知什么时候结束,用递归比较好。输入一定的空格后发现T不存在就结束了,所以不需要额外设置标志
		CreateBiTree(T->rchild);
	}
	return T;
}
//2、先序遍历二叉树
status FirstBiTree(BiTree& T) {
	if (T) {
		cout << (char)T->data << " ";//这里必须强制转换类型,转换成char类型,否则输出的数据与插入的不一样
		FirstBiTree(T->lchild);
		FirstBiTree(T->rchild);
	}
	else {
		return 0;
	}
}
//34-1栈的初始化和入栈出栈
status InitStack(SqStack& S) {
	S.top = 0;
	S.stacksize = 0;
	S.base = (BiTree*)malloc(sizeof(BiTree));
	return true;
}
status Push(SqStack& S, BiTree t) {
	S.stacksize++;//进去一个就多加一个空间,用来存储这个指针
	S.base = (BiTree*)realloc(S.base, sizeof(BiTree) * (S.stacksize));//这是多加的空间
	S.base[S.top++] = t;//这里的top就相当于一个索引,这里是第0个,进去后再进就是第一个,二top一直在最后一个元素的后面
	return true;
}
BiTree Pop(SqStack& S, BiTree t) {
	if (S.stacksize <= 0) {
		return NULL;
	}
	t = S.base[--S.top];//top指向最后一个元素的下一个,所以先减一
	S.stacksize--;//出栈的时候把空间减一
	return t;//因为这里的返回值类型是BiTree类型,所以函数类型也必须改成BiTree
}
BiTree GetTop(SqStack& S, BiTree t) {
	t = S.base[S.top - 1];
	return t;
}
//3、中序遍历二叉树1
status CenterBiTreeOne(BiTree& T) {
	InitStack(S);
	BiTree B = T;
	while (B || S.stacksize != 0) {
		if (B) {
			Push(S, B);
			B = B->lchild;
		}
		else {
			B = Pop(S, B);
			cout << (char)B->data << " ";
			B = B->rchild;
		}
	}
	return 1;
}
//4、中序遍历二叉树2
status CenterBiTreeTwo(BiTree& T) {
	InitStack(S);
	BiTree B = T;
	Push(S, B);//根指针进
	while (S.stacksize != 0) {
		B = GetTop(S, B);//取出栈顶元素用于判断
		while (B) {
			Push(S, B->lchild);//向左走到尽头
			B = GetTop(S, B);//这里到最后一步的时候,栈顶元素为空了,就退出了
		}
		Pop(S, B);//空指针退栈,这里的空就是上面的最左边元素的左边为空
		B = Pop(S, B);//取出栈顶元素,并把它释放掉
		if (B != NULL) {
			cout << (char)B->data << " ";
			Push(S, B->rchild);//这里第一次循环时,我举得例子中这个元素的右孩子为空,
			//所以空指针入栈,下一次循环时,因为栈顶元素为空,所以不会再向左一直取,一旦这个元素的右孩子不为空
			//那么下一次循环会一直向左,直到找到最左边的指针为止,然后再进行以上操作,也就是把这个节点的右子树取完。
		}
	}
	return 0;
}
//5、后序遍历二叉树
status LastBiTree(BiTree& T) {
	if (T) {
		LastBiTree(T->lchild);
		LastBiTree(T->rchild);
		cout << (char)T->data << " ";
	}
	else {
		return 0;
	}
}
//6-1层序遍历里的入队出队操作
status InitQueue(LinkQueue& Q) {
	Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));//给这两个指针分配空间,队头队尾相等说明队列为空
	if (!Q.front)exit(OVERFLOW);
	Q.front->next = NULL;//初始化后队头指针的下一个元素是空
	return 1;
}
status EnQueue(LinkQueue& Q, BiTree t) {
	QueuePtr p;
	p = (QueuePtr)malloc(sizeof(QNode));
	if (p == NULL) {
		return 0;
	}
	else {
		p->data = t;
		p->next = NULL;
		Q.rear->next = p;
		Q.rear = p;
		return 1;
	}
}
BiTree DeQueue(LinkQueue& Q) {
	QueuePtr p;
	p = Q.front->next;
	BiTree t;
	if (p == NULL) {
		return 0;
	}
	else {
		t = p->data;
		Q.front->next = p->next;
		if (Q.rear == p)Q.front = Q.rear;
		free(p);
		return t;
	}
}
//6、层序遍历二叉树
status LevelBiTree(BiTree& T) {
	LinkQueue Q;
	InitQueue(Q);
	BiTree C = T;
	if (C) {
		EnQueue(Q, C); //把根节点入队
		while (Q.front != Q.rear) {
			C = DeQueue(Q);//这里出队一个下一个循环就入队这个的孩子,这个的位置不重要,因为每次只能出队一个元素
			cout << (char)C->data << " ";//输出队头元素,输出后就把他们的孩子进来
			if (C->lchild != NULL) {
				EnQueue(Q, C->lchild);
			}
			if (C->rchild != NULL) {
				EnQueue(Q, C->rchild);
			}
		}
	}
	return 0;
}
//7、求二叉树的深度
int max(int a, int b) {
	return a > b ? a : b;
}
status Depth(BiTree& T) {
	if (T == NULL) {
		return 0;
	}
	else {
		int h1 = Depth(T->lchild);
		int h2 = Depth(T->rchild);//不管这个子树存在不存在都可以遍历,返回的都是0,取最大永远取不到它
		return max(h1, h2) + 1;
	}
}

 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

用户1234567890

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值