#include
#include
#define datatype char
#define M 50
#define MAXLEN 50
int num=0,counter1=0,counter2=0;
typedef struct node //定义一个二叉链表结构
{
datatype data;
int lt,rt;
struct node *lchild,*rchild;
}BT;
BT* createtree() // 1---创 建 树
{
BT *bt;
datatype x;
scanf("\n%c",&x);
if(x=='0') //指针为空的标志
{
bt=NULL; //
}
else
{
bt=(BT*)malloc(sizeof(BT)); // 申请一个新的的结点空间
bt->data=x;
bt->lchild=createtree(); // 创建结点的左子树
bt->rchild=createtree(); // 创建结点的右子树
}
return bt;
}
ShowTree(BT *T) //2--- 显 示 树
{
int i;
if(T==NULL)
{
return; //当结点为空,
}
else
{
num++; //全局变量 num 调控结点的位置
printf("\t\t\t");
for(i=0;i
{
printf(" ");
}
printf("%c",T->data);
for(i=0;i<20-num*2;i++)
{
printf("-");
}
printf("\n");
ShowTree(T->lchild); // 显示结点的左子树
ShowTree(T->rchild); // 显示结点的右子树
num=num-1;
}
}
void Preorder(BT *T) // 3---先 序 遍 历 树
{
if(T==NULL)
{
return;
}
else // 本函数调用结束
{
printf("%c ",T->data); // 输出结点的数据域
Preorder(T->lchild); // 先序递归遍历左子树
Preorder(T->rchild); // 先序递归遍历右子树
}
}
void Inorder(BT *T) // 4---中 序 遍 历 树
{
if(T==NULL)
{
return;
}
else // 本函数调用结束
{
Inorder(T->lchild); // 中序递归遍历左子树
printf("%c ",T->data); // 输出结点的数据域
Inorder(T->rchild); // 中序递归遍历右子树
}
}
void Postorder(BT *T) // 5---后 序 遍 历 树
{
if(T==NULL)
{
return; // 本函数调用结束
}
else
{
Postorder(T->lchild); // 后序递归遍历左子树
Postorder(T->rchild); // 后序递归遍历右子树
printf("%c ",T->data); // 输出结点的数据域
}
}
/* 算法思想
引用BT指针类型的数组(类似栈结构)来保存每个结点和它的左指针;
由于知道它的结点就可以知道它的左子树,所以只需要保存它的结点;
非空树 循环
1.结点指针入栈,直到结点左子树为空;
2.结点出栈,输出出栈结点的值,访问结点右子树;
3.栈和结点右子树不为空继续循环;
*/
void inorderse(BT *bt) //6---中序非递归遍历树
{
int i=0; //栈的初始化
BT *p,*s[M]; //保存每个结点的指针的栈
p=bt;
do
{
while(p!=NULL)
{
s[i++]=p; //结点的指针入栈
p=p->lchild; //进入左子树
} //左子树为空,退出
if(i>0) //如果栈不空
{
p=s[--i]; //结点的指针出栈
printf("%c ",p->data); //访问出栈的结点
p=p->rchild;
}
}while(i>0||p!=NULL); //右子树为空同时栈空,结束循环
}
/* 算法思想
从二叉树根结点开始,先将根结点指针放入队中,然后从队头取出一个结点元素,
每取出一个元素,执行以下操作
1.输出该结点元素的值。
2.若该结点左,右子树不为空,分别把该结点的左,右子树结点入队。
*/
void Levelorder(BT *T) // 7----按层次遍历二叉树BT, T 为指向根结点的指针
{
int i,j;
BT *q[MAXLEN],*p; // q为指针数组用以模拟队列,每个元素均为指向BT类型的指针, 用来存放结点地址
p=T;
if (p!=NULL) // 若二叉树非空,则根结点地址入队
{
i=1;
q[i]=p;
j=2;
} // i 指向对头,j 指向对尾
while (i!=j) // 当队列不为空时执行循环
{
p=q[i];
printf("%c ",p->data); // 访问队首结点的数据域
if( p->lchild!=NULL)
{
q[j]=p->lchild;
j++;
} // 将出队结点的左孩子的地址入队
if(p->rchild!=NULL)
{
q[j]=p->rchild;
j++;
} // 将出队结点的右孩子的地址入队
i++;
}
}
BT *zxxsh(BT *T) //8----中序非递归线索化二叉树
{
BT *p,*pr,*s[M],*t; //
int i=0; // 计数变量
t=(BT*)malloc(sizeof(BT));
t->lt=0; // lt 域为指针域
t->rt=1; // rt 域为线索域
t->rchild=t; // 线索后继(右)指向结点本身
if(T==NULL)
{
t->lchild=t; // 左子树指向结点本身
}
else
{
t->lchild=T; // 左子树指向 bt指针 指向的结点
pr=t;
p=T; //
do
{
while(p!=NULL)
{
s[i++]=p; // 结点指针入栈
p=p->lchild; // 进入左子树
}
if(i>0)
{
p=s[--i]; // 结点指针出栈
printf("%c ",p->data);
if(p->lchild==NULL)
{
p->lt=1; // lt 域为线索域
p->lchild=pr; // 线索前驱指向 pr指针
}
if(pr->rchild==NULL)
{
pr->rt=1; // rt 域为线索域
pr->rchild=p; // 线索前驱指针指向 p指针
}
pr=p;
p=p->rchild;
}
}while(i>0||p!=NULL);
pr->rchild=t;
pr->rt=1;
t->rchild=pr;
}
return t;
}
void zxblxss (BT *t) // 9----中序遍历找后继线索化二叉树
{
BT *p;
p=t->lchild;
do
{
while(p->lt==0)
{
p=p->lchild; // 最左的结点
}
printf("%c ",p->data); // 输出最左结点或右子树的左链尾
while( (p->rt==1)&&(p->rchild!=t) ) // 为线索且不是中序的尾结点
{
p=p->rchild; // p指向直接后继。
printf("%c ",p->data); // 输出直接后继结点
}
p=p->rchild; // p指向右子树
} while( p!=t );
}
/* 算法思想
从二叉树T的根结点开始,若二叉树的根结点的左,右子树都为空,该结点为叶子节点;
递归统计树T的左子树结点。
递归统计树T的右子树结点。
*/
void Nodenum(BT *T) //10-----统计数总结点数
{
if(T==NULL)
{
return;
}
else
{
counter2++; // 全局变量counter2,
Nodenum(T->lchild); // 递归统计结点左子树结点个数
Nodenum(T->rchild); // 递归统计结点右子树结点个数
}
}
/* 算法思想
从根结点开始,若结点左,右子树都为空,该结点为树的叶子结点,counter1++
递归统计左子树上的叶子节点;
递归统计右子树上的叶子节点;
*/
void Leafnum(BT *T) // 11-----叶 子 节 点 数
{
if(T==NULL) // 开始时,T为根结点所在链结点的指针。
{
return; // 若树为空,什么也不做,返回主调函数。
}
else
{
if(T->lchild==NULL&&T->rchild==NULL)
{
counter1++; // 统计叶子结点个数的全局变量 count(初值为0)加1。
}
Leafnum(T->lchild); // 递归统计 T 的左子树叶子结点数。
Leafnum(T->rchild); // 递归统计 T 的右子树叶子结点数
}
}
/* 算法思想
从根结点开始,结点为空,返回树层数为零。
否则
递归统计左,右子树的层次数;
返回左右子树中层次数较大的那一个;
*/
int TreeDepth(BT *T) // 12----树 深 度
{
int ldep,rdep; // 定义两个变量,存放左、右子树的深度
if(T==NULL)
{
return 0;
}
else
{
ldep=TreeDepth(T->lchild); // 递归统计左子树深度
rdep=TreeDepth(T->rchild); // 递归统计右子树深度
if(ldep>rdep)
{
return ldep+1;
}
else
{
return rdep+1;
}
}
}
/* 算法思想
从根结点开始,在树T中查找与x相等的值,若存在则返回该结点的地址,
先从根结点开始,根结点不满足条件,则在结点的左,右子树中查找x的值;
*/
int mask=0;
void Search(BT *T,datatype x)
{
if(T==NULL)
{
return ;
}
else
{
if(T->data==x)
{
mask=1;
}
Search(T->lchild,x);
Search(T->rchild,x);
}
}
void meau()
{
printf("\n\t\t\t 二 叉 树 子 系 统 \n");
printf("\t**************************************************************\n");
printf("\t* 1------建立二叉树的二叉链表存储结构 *\n");
printf("\t* 2------按凹入表显示二叉树 *\n");
printf("\t* 3------按先序遍历二叉树 *\n");
printf("\t* 4------按中序遍历二叉树 *\n");
printf("\t* 5------按后序遍历二叉树 *\n");
printf("\t* 6------按中序非递归调用算法遍历二叉树 *\n");
printf("\t* 7------按层次遍历二叉树 *\n");
printf("\t* 8------按中序非递归调用线索化二叉树 *\n");
printf("\t* 9------按找后继(或前驱)结点的算法遍历中序线索二叉树 *\n");
printf("\t* 10-----统计二叉树的结点总数 *\n");
printf("\t* 11-----统计二叉树的叶子结点总数 *\n");
printf("\t* 12-----统计二叉树的深度 *\n");
printf("\t* 13-----在二叉树中查找值为x的结点 *\n");
printf("\t* 0------返 回 *\n");
printf("\t**************************************************************\n");
printf("\t 请选择要执行的操作代号(0--13): ");
}
void main()
{
int i,chiose;
datatype x;
BT *T,*t;
while(1)
{
meau();
scanf("%d",&chiose);
if(chiose==1)
{
printf("\n\t 按先序次序输入二叉树中结点的值,以0字符表示空树\n");
printf("\t请输入: ");
T=createtree();
printf("\t 数据输入完毕!\n");
}
else if(chiose==2)
{
printf("\n\t\t\t凹入表显示二叉树\n");
ShowTree(T);
}
else if(chiose==3)
{
printf("\n\t\t先序遍历二叉树: ");
Preorder(T);
printf("\n");
}
else if(chiose==4)
{
printf("\n\t\t中序遍历二叉树: ");
Inorder(T);
printf("\n");
}
else if(chiose==5)
{
printf("\n\t\t后序遍历二叉树: ");
Postorder(T);
printf("\n");
}
else if(chiose==6)
{
printf("\n\t\t中序非递归遍历二叉树: ");
inorderse(T);
printf("\n");
}
else if(chiose==7)
{
printf("\n\t\t层次遍历二叉树: ");
Levelorder(T);
printf("\n");
}
else if(chiose==8)
{
printf("\n\t\t中序非递归线索化二叉树为: ");
t=zxxsh(T);
printf("\n");
}
else if(chiose==9)
{
printf("\n\t\t中序遍历找后继线索化二叉树:");
zxblxss(t);
printf("\n");
}
else if(chiose==10)
{
Nodenum(T);
printf("\n\t树的节点数为: %d\n",counter2);
counter2=0;
}
else if(chiose==11)
{
Leafnum(T);
printf("\n\t树的叶子节点数为: %d\n",counter1);
counter1=0;
}
else if(chiose==12)
{
printf("\n\t树的深度为: %d\n",TreeDepth(T));
}
else if(chiose==13)
{
printf("\n\t 输入你要查询的数据:");
scanf("\n%c",&x);
Search(T,x);
if(mask==1)
{
printf("\n\t 你要查找的数据%c在二叉树中\n",x);
}
else
{
printf("\n\t 你要查找的数据%c不在二叉树中\n",x);
}
mask=0;
}
else if(chiose==0)
{
break;
}
else
{
printf("\n\t\t 输入有误,请重新选择操作代号\n");
}
}
}