2.2 实验2 二叉树应用

目的要求
1.掌握二叉树的存储实现。
2.掌握二叉树的遍历思想。
3.掌握二叉树的常见算法的程序实现。
实验内容
1.输入字符序列,建立二叉链表。
2.中序遍历二叉树:递归算法。
3.中序遍历二叉树:非递归算法。(最好也实现先序,后序非递归算法)
4.求二叉树的高度。
5.求二叉树的叶子数。
6.借助队列实现二叉树的层次遍历。
7.在主函数中设计一个简单的菜单,调用上述算法。
实验说明
1.类型定义 // 二叉链表存储
#define ElemType char // 元素类型
typedef struct BiTNode
{
ElemType data;
BiTNode *Lchild, *Rchild ;
} BiTNode, *pBiTree ;
2. 元素类型可根据实际需要选取。

#include<iostream>  
#include<cstdio>  
#include<stdlib.h>  
using namespace std;
#define MAXSIZE 100
#define SIZE 100
#define MORE 10
#define OK          1
#define ERROR       0
#define TRUE        1
#define FALSE       0
#define OVERFLOW    -1
#define STACK_INIT_SIZE     100
#define STACKINCREMENT      10
typedef int Status;
typedef char Elemtype;
typedef struct BiTnode
{
	Elemtype data;//数据域  
	struct BiTnode* Lchild, * Rchild; //左右子树域;  
}BiTnode, * BiTree;
typedef BiTree SElemType;

//栈 
typedef struct {//栈结构定义
	BiTree* base;
	BiTree* top;
	int stacksize;
}SqStack;
Status Visit(Elemtype e) {
	// 对二叉树中的数据元素访问
	if (e == '\0') {
		return ERROR;
	}
	else {
		printf("%c ", e);
	}
	return OK;
}


//-----------顺序栈操作--------------//
Status InitStack(SqStack* S) {
	//构造一个空栈S
	S->base = (SElemType*)malloc(STACK_INIT_SIZE * sizeof(SElemType));
	if (!S->base)//分配失败
	{
		printf("分配内存失败.\n");
		exit(0);
	}
	S->top = S->base;
	S->stacksize = STACK_INIT_SIZE;
	return OK;
}

Status DestroyStack(SqStack* S) {
	//销毁栈S,S不再存在
	if (!S)//S为空
	{
		printf("指针为空,释放失败.\n");
		exit(0);
	}
	free(S->base);
	return OK;
}

Status ClearStack(SqStack* S) {
	//把栈S置为空栈
	if (!S)//S不存在
		return FALSE;
	S->top = S->base;//直接将栈顶指针指向栈底
	return OK;
}

Status StackEmpty(SqStack S) {
	//若栈S为空栈,则返回TRUE,否则返回FALSE
	if (S.top == S.base)
		return TRUE;
	else
		return FALSE;
}

int StackLength(SqStack S) {
	//返回S元素的个数,即栈的长度
	return S.stacksize;
}

Status GetTop(SqStack S, SElemType* e) {
	//若栈不为空,则用e返回S的栈顶元素,并返回OK;否则返回FALSE
	if (S.top == S.base) {
		return FALSE;
	}
	else {
		*e = *(S.top - 1);
		return OK;
	}
}

Status Push(SqStack* S, SElemType e) {
	//插入元素e为新的栈顶元素
	if (S->top - S->base >= S->stacksize) {//栈已满,追加存储空间
		S->base = (SElemType*)realloc(S->base, (S->stacksize + STACKINCREMENT) * sizeof(SElemType));
		if (!S->base)
		{
			printf("重新申请空间失败.\n");
			exit(0);
		}
		S->top = S->base + S->stacksize;//更改栈顶指针
		S->stacksize += STACKINCREMENT;
	}
	*S->top++ = e;
	return OK;
}

Status Pop(SqStack* S, SElemType* e) {
	//若栈S不为空,则删除S的栈顶元素,用e返回其值,并返回OK,否则返回ERROR
	if (S->top == S->base) {//栈为空
		return ERROR;
	}
	*e = *(--S->top);
	return OK;
}




//队列 
typedef struct {
	BiTree* base; //初始化动态分配空间
	int front;
	int rear;
} SqQueue;

//队列 
void InitQueue(SqQueue& q)//构造空队列
{
	q.base = new BiTree[MAXSIZE];
	if (!q.base) exit(OVERFLOW);
	q.front = q.rear = 0;
}
void EnQueue(SqQueue& q, BiTree& T)//入队
{
	q.base[q.rear] = T;
	q.rear++;
}
BiTree OutQueue(SqQueue& q)
{
	BiTree T;
	T = q.base[q.front];
	q.front++;
	return T;
}





int create(BiTree* T)
{
	Elemtype ch;
	Elemtype temp;
	scanf_s("%c", &ch);
	temp = getchar();
	if (ch =='@')
	{
		*T = NULL;
	}
	else
	{
		*T = (BiTree)malloc(sizeof(BiTnode));
		if (!(*T))
		{
			exit(-1);
		}
		else
		{
			(*T)->data = ch;
			printf("请输入%c的左节点的值", ch);
			create(&(*T)->Lchild);
			printf("请输入%c的右节点的值", ch);
			create(&(*T)->Rchild);
		}

	}
	return 1;

}
//递归遍历二叉树
void Traverse(BiTree T)//前序遍历二叉树  
{
	if (NULL == T)
	{
		return;
	}
	else
	{
		printf("%c ", T->data);
		Traverse(T->Lchild);
		Traverse(T->Rchild);
	}

}

//中序遍历二叉树  
void midTraverse(BiTree T)
{
	if (T == NULL) { return; }
	midTraverse(T->Lchild);
	printf("%c ", T->data);
	midTraverse(T->Rchild);
}

//后序遍历二叉树  
void lasTraverse(BiTree T)
{
	if (T == NULL) { return; }
	lasTraverse(T->Lchild);
	lasTraverse(T->Rchild);
	printf("%c ", T->data);

}


//二叉树三种遍历的非递归算法,栈 
Status PreOrderNonRecursionTraverse(BiTree T, Status(*Visit)(Elemtype e)) {
	// 先序遍历二叉树T的非递归算法
	SqStack S;
	SElemType p;
	InitStack(&S);      Push(&S, T); // 根指针入栈
	while (!StackEmpty(S)) {
		Pop(&S, &p);	//访问根节点
		if (!Visit(p->data)) return ERROR;
		if (p->Rchild)
			Push(&S, p->Rchild);
		if (p->Lchild)
			Push(&S, p->Lchild);
	}//while
	DestroyStack(&S);
	return OK;
}
Status InOrderNonRecursionTraverse(BiTree T, Status(*Visit)(Elemtype e)) {
	// 中序遍历二叉树T的非递归算法
	SqStack S;
	SElemType p;
	InitStack(&S);      p = T;
	while (p || !StackEmpty(S)) {
		if (p) {
			Push(&S, p); p = p->Lchild;	//根指针进栈,遍历左子树
		}
		else {//根指针退栈,访问根节点,遍历右子树
			Pop(&S, &p);	if (!Visit(p->data))	return ERROR;
			p = p->Rchild;
		}//else
	}//while
	DestroyStack(&S);
	return OK;

}

Status PostOrderNonRecursionTraverse(BiTree T, Status(*Visit)(Elemtype e)) {
	// 后序遍历二叉树T的非递归算法
	SqStack S;
	SElemType p, q;
	InitStack(&S);      Push(&S, T); // 根指针入栈
	while (!StackEmpty(S)) {
		while (GetTop(S, &p) && p && (p->Lchild || p->Rchild)) {
			Push(&S, p->Rchild);		// 右子树入栈
			Push(&S, p->Lchild);		// 左子树入栈
		}//注意栈中存在空指针,表示某个结点的右子树为空
		if (!StackEmpty(S)) {//访问结点
			Pop(&S, &p);
			if (p) {
				if (!Visit(p->data)) return ERROR;
			}
			else {		// 存在右子树为空的结点,继续向上返回
				Pop(&S, &p);
				if (!Visit(p->data)) return ERROR;
			}
			while (GetTop(S, &q) && q && p == q->Rchild) {//若当前为右子树,则继续出栈
				Pop(&S, &p);
				if (!Visit(p->data)) return ERROR;
				GetTop(S, &q);
			}
		}//if
	}//while
	DestroyStack(&S);
	return OK;
}


//求二叉树的深度  
int TreeDeep(BiTree T)
{
	int deep = 0;
	if (T)
	{
		int leftdeep = TreeDeep(T->Lchild);
		int rightdeep = TreeDeep(T->Rchild);
		deep = leftdeep >= rightdeep ? leftdeep + 1 : rightdeep + 1;

	}
	return deep;

}

//求二叉树叶子节点个数  
int Leafcount(BiTree T, int& num)
{
	if (T)
	{
		if (T->Lchild == NULL && T->Rchild == NULL)
		{
			num++;
		}
		Leafcount(T->Lchild, num);
		Leafcount(T->Rchild, num);
	}
	return num;
}


void SeqOrderTraverse(BiTree T)//层序遍历
{
	SqQueue q;
	InitQueue(q);
	EnQueue(q, T);
	while (q.rear != q.front)
	{
		BiTree root = OutQueue(q);
		/*cout << root->data << " ";*/
		printf("%c ", root->data);
		if (root->Lchild)
			EnQueue(q, root->Lchild);
		if (root->Rchild)
			EnQueue(q, root->Rchild);
	}/*
	cout << endl;*/
	printf("\n");
}
 void menu(void)//菜单
 {
	 printf("\n");
	 printf("*********二叉树应用*********\n");
	 printf("1.递归中序遍历二叉树\n");
	 printf("2.非递归中序遍历二叉树\n");
	 printf("3.非递归前序遍历二叉树\n");
	 printf("4.非递归后序遍历二叉树\n");
	 printf("5.求二叉树高度\n");
	 printf("6.求二叉树的叶子数\n");
	 printf("7.借助队列实现二叉树层次遍历\n");
	 printf("0.退出\n\n");
}

int main()
{
	BiTree T; Status(*visit)(Elemtype e) = Visit;
	BiTree* p = (BiTree*)malloc(sizeof(BiTree));
	int deepth = 0, num = 0;
	printf("请输入第一个节点的值,@代表没有叶节点:\n");
	create(&T);
	
	int choice;
	menu();
	while (1)
	{

		printf("选择你的操作:");
		scanf_s("%d", &choice);
		switch (choice)
		{
		case 1:

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

			break;
		case 2:
			printf("非递归中序遍历二叉树:\n");
			InOrderNonRecursionTraverse(T, visit);
			printf("\n");


			break;
		case 3:
			printf("非递归先序遍历二叉树:\n");
			PreOrderNonRecursionTraverse(T, visit);
			printf("\n");
			break;
		case 4:

			printf("非递归后序遍历二叉树:\n");
			PostOrderNonRecursionTraverse(T, visit);
			printf("\n");
			break;

		case 5:
			deepth = TreeDeep(T);
			printf("树的深度:%d\n", deepth);
			printf("\n");
			break;
		case 6:
			Leafcount(T, num);
			printf("二叉树的叶子节点个数为:%d\n", num);
			printf("\n");
			break;
		case 7:
			printf("层序遍历二叉树:\n");
			SeqOrderTraverse(T);
			break;
		case 0:
			return 0;
		default:
			printf("输入错误,请重新输入\n");
		}
	}
	return 0;
}

输入示例与运行结果:
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值