C语言 数据结构 树 KTV点歌系统,数据结构(二叉树子系统:c语言实现)

#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");

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值