花了一天时间写了个二叉树用二叉链表实现基本操作,主要是对链表不熟悉,所以花了很多时间。
其次是对之前的线性表不熟,所以想了一些更麻烦的方法来实现。慢慢来吧。
今天至少还是想明白了二叉链表的大概结构和基本操作方法的。
附上代码,以后如果强化了再来贴。
/**************************用二叉链表法实现二叉树*********************************************/
/***************************存储表示***********************/
typedef struct BiTNode{
char data;
struct BiTNode *Lchild,*Rchild;
}BiTNode,*BiTree;
struct BiTreeQueue{
BiTree t;
struct BiTreeQueue *next;
};
/*********************基本操作*****************************/
//1结构初始化
void InitBiTree(BiTree &T){
//操作结果:构造空二叉树T。
T= new BiTNode;
if(!T) exit(1);
T=NULL;
}
void CreateBiTree(BiTree &T){
//操作结果:按构造二叉树T。
char ch;
scanf("%c",&ch);
getchar();
if(ch!='/n'){
T=(BiTree)malloc(sizeof(BiTNode));//创建新子树
T->data=ch;
printf("请输入%c的左子树,若无请按两下回车/n",ch);
CreateBiTree(T->Lchild);//创建左子树
printf("请输入%c的右子树,若无请按两下#/n",ch);
CreateBiTree(T->Rchild);//创建右子树
}
else
T=NULL;
}
//2销毁结构
void DestroyBiTree(BiTree &T){
//初始条件:二叉树T存在。
//操作结果:销毁二叉树T。
if(T){//T存在
if(T->Lchild)//T有左子树
DestroyBiTree(T->Lchild);//销毁左子树
if(T->Rchild)//T有右子树
DestroyBiTree(T->Rchild);//销毁右子树
free(T);//释放根节点T
T=NULL;//空指针赋值为NULL
}
}
bool BiTreeEmpty(BiTree T){
//初始条件:二叉树T存在。
//操作结果:若T为空二叉树,则返回TRUE,否则返回FALSE。
if(T){//T存在
if(T->data!=NULL)//T不为空
return false;
}
return true;
}
int BiTreeDepth(BiTree T){
//初始条件:二叉树T存在。
//操作结果:返回T的深度。
if(T){//T存在
if(BiTreeDepth(T->Lchild)>=BiTreeDepth(T->Rchild))//左子树的深度大于等于右子树的深度
return BiTreeDepth(T->Lchild)+1;
else
return BiTreeDepth(T->Rchild)+1;
}
return 0;//T不存在,返回0;
}
char Root(BiTree T){
//初始条件:二叉树T存在。
//操作结果:返回T的根。
if(T)//T存在
return T->data;
return NULL;
}
char Value(BiTree T,BiTNode e){
//初始条件:二叉树T存在,e是T中某个结点。
//操作结果:返回e的值。
return e.data;
}
BiTree Point(BiTree T,char e){
//初始条件:T存在,e是T中某个结点
//操作结果:返回指向e的指针
struct BiTreeQueue *bt,*bw,*a,*c;//构建一个BiTree类型的链表结构
if(T){//非空树
bt=(struct BiTreeQueue *)malloc(sizeof(struct BiTreeQueue));
bt->t=T;
bt->next=NULL;
bw=bt;//根结点入链表
while(bt){//链表不为空
a=bt;//链表的头结点出列
if(a->t->data==e)
return a->t;//找到指向e的指针
if(a->t->Lchild){//左子树存在
c=(struct BiTreeQueue *)malloc(sizeof(struct BiTreeQueue));
c->t=a->t->Lchild;
c->next=NULL;
bw->next=c;
bw=bw->next;//左子树入链表;
}
if(a->t->Rchild){//右子树存在
c=(struct BiTreeQueue *)malloc(sizeof(struct BiTreeQueue));
c->t=a->t->Rchild;
c->next=NULL;
bw->next=c;
bw=bw->next;//右子树入链表;
}
bt=bt->next;
free(a);
}
}
return NULL;//找不到
}
char Parent(BiTree T,char e){
//初始条件:二叉树T存在,e是T中某个结点。
//操作结果:若e是T的非根结点,则返回它的双亲,否则返回“空”。
struct BiTreeQueue *bt,*bw,*a,*c;//构建一个BiTree类型的链表结构
if(T){//非空树
bt=(struct BiTreeQueue *)malloc(sizeof(struct BiTreeQueue));
bt->t=T;
bt->next=NULL;
bw=bt;//根结点入链表
while(bt){//链表不为空
a=bt;//链表的头结点出列
if(a->t->Lchild){//左子树存在
if(a->t->Lchild->data==e)
return a->t->data;//找到指向e的指针
c=(struct BiTreeQueue *)malloc(sizeof(struct BiTreeQueue));
c->t=a->t->Lchild;
c->next=NULL;
bw->next=c;
bw=bw->next;//左子树入链表;
}
if(a->t->Rchild){//右子树存在
if(a->t->Rchild->data==e)
return a->t->data;//找到指向e的指针
c=(struct BiTreeQueue *)malloc(sizeof(struct BiTreeQueue));
c->t=a->t->Rchild;
c->next=NULL;
bw->next=c;
bw=bw->next;//右子树入链表;
}
bt=bt->next;
free(a);
}
}
return NULL;//找不到
}
char LeftChild(BiTree T,char e){
//初始条件:二叉树T存在,e是T中某个结点。
//操作结果:返回e的左孩子。若e无左孩子,则返回“空”。
BiTree a;
if(T){
a=Point(T,e);
if(a){
if(a->Lchild)
return a->Lchild->data;
}
}
return NULL;
}
char RightChild(BiTree T,char e){
//初始条件:二叉树T存在,e是T中某个结点。
//操作结果:返回e的右孩子。若e无右孩子,则返回“空”。
BiTree a;
if(T){
a=Point(T,e);
if(a){
if(a->Rchild)
return a->Rchild->data;
}
}
return NULL;
}
char LeftSibling(BiTree T,char e){
//初始条件:二叉树T存在,e是T中某个结点。
//操作结果:返回e的左兄弟。若e是其双亲的左孩子或无左兄弟,则返回“空”。
char ch;
BiTree a;
ch=Parent(T,e);
a=Point(T,ch);
if(a){
if(!a->Lchild || a->Lchild->data==e)
return NULL;
else
return a->Lchild->data;
}
}
char RightSibling(BiTree T,char e){
//初始条件:二叉树T存在,e是T的结点。
//操作结果:返回e的右兄弟。若e是其双亲的右孩子或无右兄弟,则返回“空”。
char ch;
BiTree a;
ch=Parent(T,e);
a=Point(T,ch);
if(a){
if(!a->Rchild || a->Rchild->data==e)
return NULL;
else
return a->Rchild->data;
}
}
void PreOrderTraverse(BiTree T)
{ // 初始条件: 二叉树T存在,Visit是对结点操作的应用函数。算法6.1,有改动
// 操作结果: 先序递归遍历T,对每个结点调用函数Visit一次且仅一次
if(T) // T不空
{
// 先访问根结点
printf("%c",T->data);
PreOrderTraverse(T->Lchild); // 再先序遍历左子树
PreOrderTraverse(T->Rchild); // 最后先序遍历右子树
}
}
void InOrderTraverse(BiTree T)
{ // 初始条件: 二叉树T存在,Visit是对结点操作的应用函数
// 操作结果: 中序递归遍历T,对每个结点调用函数Visit一次且仅一次
if(T)
{
InOrderTraverse(T->Lchild); // 先中序遍历左子树
// 再访问根结点
printf("%c",T->data);
InOrderTraverse(T->Rchild); // 最后中序遍历右子树
}
}
//void PostOrderTraverse(BiTree T,visit());
//初始条件:二叉树T存在,visit是对结点操作的应用函数。
//操作结果:后序遍历T,对每个结点调用函数visit一次且仅一次。一旦visit()失
//败,则操作失败。
//void LevelOrderTraverse(BiTree T,visit());
//初始条件:二叉树T存在,visit是对结点操作的应用函数。
//操作结果:层序遍历T,对每个结点调用函数visit一次且仅一次.一旦visit()失
//败,则操作失败。
void ClearBiTree(BiTree &T){
//初始条件:二叉树T存在。
//操作结果:将二叉树T清为空树
if(T){
T->data=NULL;
ClearBiTree(T->Lchild);
ClearBiTree(T->Rchild);
free(T);
T=NULL;
}
}
void Assign(BiTree &T,char e,char value){
//初始条件:二叉树T存在,e是T中某个结点。
//操作结果:结点e赋值为value。
BiTree a;
a=Point(T,e);
a->data=value;
}
void InsertChild(BiTree &T,BiTree p,int LR,BiTree c){
//初始条件:二叉树T存在,p指向T中某个结点,LR为0或1,非空二叉树c与T不相交且右子树为空。
//操作结果:根据LR为0或1,插入c为T中p所指结点的左或右子树。p所指结点原有左或右子树成为c的右子树。
if(T){
if(LR==0){
c->Rchild=p->Lchild;
p->Lchild=c;
}
else{
c->Rchild=p->Rchild;
p->Rchild=c;
}
}
}
void DeleteChild(BiTree &T,BiTree p,int LR){
//初始条件:二叉树T存在,p指向T中某个结点,LR为0或1。
//操作结果:根据LR为0或1,删除T中p所指结点的左或右子树。
if(T){
if(p){
if(LR==0)
ClearBiTree(p->Lchild);
else
ClearBiTree(p->Rchild);
}
}
}
void ChangeLR(BiTree &T){
//将二叉树中所有结点的左、右子树相互交换
BiTree a;
if(T){
if(T->Lchild)
ChangeLR(T->Lchild);//使左子树完成改变
if(T->Rchild)
ChangeLR(T->Rchild);//使右子树完成改变
if(T->Lchild && T->Rchild){//交换左右子树
a=T->Lchild;
T->Lchild=T->Rchild;
T->Rchild=a;
}
else if(T->Lchild){
T->Rchild=T->Lchild;
T->Lchild=NULL;
}
else if(T->Rchild){
T->Lchild=T->Rchild;
T->Rchild=NULL;
}
else
;
}
}
/********************main基本操作运用**********************/
int main()
{
BiTree T;
char e;
InitBiTree(T);
printf("创建二叉树,请输入根结点/n");
CreateBiTree(T);
printf("/n您创建的二叉树,先序遍历结果为:");
PreOrderTraverse(T);
printf("/n您创建的二叉树,中序遍历结果为:");
InOrderTraverse(T);
printf("/n您创建的二叉树的深度为:%d,根为%c/n",BiTreeDepth(T),Root(T));
printf("请输入您要查看的结点:");
scanf("%c",&e);
printf("%c的双亲是%c,左兄弟是%c,右兄弟是%c,左孩子是%c,右孩子是%c/n",e,Parent(T,e),LeftSibling(T,e),RightSibling(T,e),LeftChild(T,e),RightChild(T,e));
ChangeLR(T);
printf("/n您改变后的二叉树,先序遍历结果为:");
PreOrderTraverse(T);
getchar();
printf("/n请输入您要查看的结点:");
scanf("%c",&e);
printf("%c的双亲是%c,左兄弟是%c,右兄弟是%c,左孩子是%c,右孩子是%c/n",e,Parent(T,e),LeftSibling(T,e),RightSibling(T,e),LeftChild(T,e),RightChild(T,e));
DestroyBiTree(T);
system("pause");
return 0;
}