目的要求
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;
}
输入示例与运行结果: