/*******************************************************************************************
习题:实现二叉树的生成、先序遍历、中序遍历、后序遍历,统计二叉树的叶子结点、非叶子结点
程序中已给出二叉树生成函数CreateBiTree、先序遍历函数PreOrderTraverse和统计二叉树的叶子结点函数NonLeafCount
基本要求(必做):
1、将中序遍历(InOrderTraverse)、后序遍历(PostOrderTraverse)函数补充完整
2、将统计二叉树的非叶子结点函数NonLeafCount补充完整
3、程序中存在一个显著错误,请找出后改正之
选作:在程序中实现以下功能
1、求二叉树的根结点Root(T)
2、求某结点的父结点Parent(T,e)
3、求结点的左孩子LeftChild(T,e)
4、求结点的右孩子RightChild(T,e)
5、求结点的左兄弟LeftSibling(T,e)
6、求结点的右兄弟RightSibling(T,e)
7、插入孩子结点InsertChild(T,p,LR,c)
8、删除孩子结点DeleteChild(T,p,LR)
注意:
1、程序运行时,设初始输入序列为"ABC DE G F "
2、本作业成绩按最后完成的功能多少评分
******************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <stack>
#include <stdlib.h>
using namespace std;
int leaf_num;//叶子结点数目
int non_leaf_num;
typedef char TElemType; //定义树中结点的数据域的类型为字符型
typedef struct BiTNode //树的存储结构的定义
{
TElemType data; //结点的数据域
struct BiTNode * lchild, *rchild; //结点的左右孩子指针
} BiTNode, *BiTree;
void CreateBiTree(BiTree & T)//按先序序列创建二叉树 "ABC DE G F "
{
TElemType ch;
scanf("%c", &ch);
while (ch == '\n')
{
scanf("%c", &ch); //吃掉一些讨厌的回车
}
if (ch == ' ')
{
T = NULL;
}
else
{
T = (BiTNode *)malloc(sizeof(BiTNode));
T->data = ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
void PreOrderTraverse(BiTree T) //先序遍历
{
if (T)
{
printf("%c", T->data); //访问根结点
PreOrderTraverse(T->lchild); //先序访问左子树
PreOrderTraverse(T->rchild); //先序访问右子树
}
}
void InOrderTraverse(BiTree T)//中序递归遍历
{
if (T)
{
InOrderTraverse(T->lchild); //中序访问左子树
printf("%c", T->data);
InOrderTraverse(T->rchild); //中序访问右子树
}
}
void InOrderTraverse_2(BiTree T)//中序非递归遍历
{
stack<BiTree> S;
BiTree p;
S.push(T);
while (!S.empty())
{
p = S.top();
while (p)
{
S.push(p->lchild);
p = p->lchild;
}
S.pop();
if (!S.empty())
{
p = S.top();
S.pop();
if (p->data == ' ')
{
return;
}
printf("%c", p->data);
S.push(p->rchild);
}
}
}
void PostOrderTraverse(BiTree T) //后序遍历
{
if (T)
{
PostOrderTraverse(T->lchild); //后序访问左子树
PostOrderTraverse(T->rchild); //后序访问右子树
printf("%c", T->data);
}
}
void LeafCount(BiTree T)//统计二叉树叶子结点数目
{
if (T)
{
if (T->lchild == NULL && T->rchild == NULL) //判断条件:当前结点无左右孩子则该结点为叶子结点
{
leaf_num++; //计算器加1
}
LeafCount(T->lchild);//若非叶子结点则分别统计其左、右子树
LeafCount(T->rchild);
}
}
void NonLeafCount(BiTree T)//统计二叉树非叶子结点数目
{
if (T)
{
if (T->lchild != NULL || T->rchild != NULL) //判断条件:当前结点有右孩子则该结点为非叶子结点
{
non_leaf_num++; //计算器加1
}
NonLeafCount(T->lchild);//若非叶子结点则分别统计其左、右子树
NonLeafCount(T->rchild);
}
}
void Find(char f, char e, BiTree T) //找得到了父结点就找到了一切
{
if (!T)
{
printf("树为空,请先建树!\n");
return;
}
BiTree par, now;
int flag = 0; // 1 左, 2 右;
if (T->data == e)
{
if (f == 'b')
{
printf("%c 没有父结点\n", e);
}
else if (f == 'c')
{
if (T->lchild)
{
printf("左孩子是 %c\n", T->lchild->data);
}
else
{
printf("%c 没有左孩子结点\n", e);
}
}
else if (f == 'd')
{
if (T->rchild)
{
printf("右孩子是 %c\n", T->rchild->data);
}
else
{
printf("%c 没有右孩子结点\n", e);
}
}
else if (f == 'e')
{
printf("%c 没有左兄弟\n", e);
}
else
{
printf("%c 没有右兄弟\n", e);
}
return;
}
stack<BiTree> S;
while (T || !S.empty()) //先序非递归遍历
{
while (T)
{
S.push(T);
if (T->lchild) //先判断该结点是否有左孩子结点
if (T->lchild->data == e) //再判断左孩子结点是否和e相等
{
flag = 1;
par = T;
now = T->lchild;
break;
}
if (T->rchild) //先判断该结点是否有右孩子结点
if (T->rchild->data == e) //再判断右孩子结点是否和e相等
{
flag = 2;
par = T;
now = T->rchild;
break;
}
T = T->lchild;
}
if (flag != 0)
{
break;
}
T = S.top();
S.pop();
T = T->rchild;
}
if (!flag)
{
printf("没有这个结点\n");
return;
}
if (f == 'b')
{
printf("%c 的父结点是%c\n", e, par->data);
}
else if (f == 'c')
{
if (!now->lchild)
{
printf("%c 没有左孩子结点\n", e);
}
else
{
printf("%c 左孩子是 %c\n", e, now->lchild->data);
}
}
else if (f == 'd')
{
if (!now->rchild)
{
printf("%c 没有右孩子结点\n", e);
}
else
{
printf("%c 右孩子是 %c\n", e, now->rchild->data);
}
}
else if (f == 'e')
{
if (flag == 1 || !par->lchild)
{
printf("%c 没有左兄弟结点\n", e);
}
else
{
printf("%c 的左兄弟结点是 %c\n", e, par->lchild->data);
}
}
else
{
if (flag == 2 || !par->rchild)
{
printf("%c 没有右兄弟结点\n", e);
}
else
{
printf("%c 的右兄弟结点是 %c\n", e, par->rchild->data);
}
}
}
void Insert(BiTree & TT) //插入树
{
int LR;
char p, flag;
BiTree now, next, C, f, T = TT;
stack<BiTree> S;
printf("请先建立要插入的树\n");
CreateBiTree(C);
f = C;
printf("请输入p(结点),LR(左孩子右孩子0,1):\t");
scanf(" %c%d", &p, &LR);
while (T || !S.empty()) //先序非递归遍历
{
while (T)
{
S.push(T);
if (T->data == p) //再判断左孩子结点是否和e相等
{
flag = 1;
now = T;
break;
}
T = T->lchild;
}
if (flag != 0)
{
break;
}
T = S.top();
S.pop();
T = T->rchild;
}
if (!flag || LR > 1)
{
printf("没有结点 %c 或 LR输入错误\n", p);
return;
}
if (LR == 0)
{
next = now->lchild;
now->lchild = C;
}
else
{
next = now->rchild;
now->rchild = C;
}
while (f->rchild) //p所指结点的原有左子树或右子树成为c的右子树
{
f = f->rchild;
}
f->rchild = next;
}
void destroyBiTree(BiTree & T) //删除树
{
if (T)
{
destroyBiTree(T->lchild);
destroyBiTree(T->rchild);
free(T);
T = NULL;
}
}
void DelChild(BiTree & TT, char p, int LR)
{
BiTree now, T = TT;
int flag = 0;
stack <BiTree> S;
while (T || !S.empty()) //先序非递归遍历
{
while (T)
{
S.push(T);
if (T->data == p) //再判断左孩子结点是否和e相等
{
flag = 1;
now = T;
break;
}
T = T->lchild;
}
if (flag != 0)
{
break;
}
T = S.top();
S.pop();
T = T->rchild;
}
if (!flag || LR > 1)
{
printf("没有结点 %c 或 LR输入错误\n", p);
return;
}
if (LR == 0)
{
destroyBiTree(now->lchild);
}
else
{
destroyBiTree(now->rchild);
}
}
int main()
{
//freopen("1.txt", "r", stdin);
BiTree bt;
int flag = 1, LR; //用于switch语句的控制位
char option, e, c;//用户输入字符
/** 按先序输入二叉树序列,构造二叉树**/
printf("构造二叉树,请按先序输入二叉树序列\n");
CreateBiTree(bt);
while (flag)
{
printf("\n请选择:\n");
printf("1. 构造新二叉树\n");
printf("2. 二叉树先序遍历\n");
printf("3. 二叉树中序遍历\n");
printf("4. 二叉树后序遍历\n");
printf("5. 统计二叉树叶子结点数目\n");
printf("6. 统计二叉树非叶子结点数目\n");
printf("a、求二叉树的根结点\n");
printf("b、求某结点的父结点Parent(T,e)\n");
printf("c、求结点的左孩子LeftChild(T,e)\n");
printf("d、求结点的右孩子RightChild(T,e)\n");
printf("e、求结点的左兄弟LeftSibling(T,e)\n");
printf("f、求结点的右兄弟RightSibling(T,e)\n");
printf("g、插入孩子结点InsertChild(T,p,LR,c)\n");
printf("h、删除孩子结点DeleteChild(T,p,LR)\n");
printf("7. 退出程序\n");
scanf(" %c", &option);
system("cls");
switch (option)
{
case '1':
printf("请输入二叉树序列:\n");
CreateBiTree(bt);
break;
case '2':
printf("二叉树先序遍历结果: ");
PreOrderTraverse(bt);
printf("\n");
break;
case '3':
printf("二叉树中序递归遍历结果: ");
InOrderTraverse(bt);
printf(" 中序非递归遍历结果: ");
InOrderTraverse_2(bt);
printf("\n");
break;
case '4':
printf("二叉树后序遍历结果: ");
PostOrderTraverse(bt);
printf("\n");
break;
case '5':
leaf_num = 0;
LeafCount(bt);
printf("二叉树叶子结点数目: %d\n", leaf_num);
break;
case '6':
non_leaf_num = 0;
NonLeafCount(bt);
printf("二叉树叶非子结点数目: %d\n", non_leaf_num);
break;
case 'a':
printf("二叉树的根节点是:\t%c\n", bt->data);
break;
case 'b':
printf("请输入该点(求父结点):\t");
scanf(" %c", &e);
Find(option, e, bt);
break;
case 'c':
printf("请输入该点(求左孩子):\t");
scanf(" %c", &e);
Find(option, e, bt);
break;
case 'd':
printf("请输入该点(求右孩子):\t");
scanf(" %c", &e);
Find(option, e, bt);
break;
case 'e':
printf("请输入该点(求左兄弟):\t");
scanf(" %c", &e);
Find(option, e, bt);
break;
case 'f':
printf("请输入该点(求右兄弟):\t");
scanf(" %c", &e);
Find(option, e, bt);
break;
case 'g':
Insert(bt);
break;
case 'h':
printf("请输入要删除的结点p的LR(0,1): ");
scanf(" %c %d", &c, &LR);
DelChild(bt, c, LR);
break;
case '7':
flag = 0;
printf("程序结束,按任意键退出!\n");
break;
default:
{
printf("输入错误,重新输入\n");
break;
}
//
}// end switch
//option = getchar();
}//end while
return 0;
}//end
二叉树的先序中序后序递归非递归遍历,插入删除等操作
最新推荐文章于 2024-07-28 17:42:24 发布