您的位置:首页 > 理论基础 > 数据结构算法

二叉树操作--数据结构

2013-11-15 21:24 274 查看
二叉树操作:

实现以二叉链表为存储结构的二叉树的创建、遍历、查找、插入和删除操作。

说明:

1、按先序遍历思想创建二叉树;

2、分别实现中序遍历和层次遍历;

3、给定元素值查找结点指针位置并返回其指针,可利用指针引用data域输出;

4、实现插入左右孩子操作,指定元素值,找到结点后若已存在对应位置的孩子结点则不插入;

5、删除指定元素值的结点,若该结点存在子树则将其子树所有结点全部删除回收;
6、程序提供简单功能菜单。 

#include <iostream>

using namespace std;

//定义一个二叉树
typedef struct node
{
char date;    //数据成员
struct node *lchild,*rchild;
} BTNode,*SecondTree;

//定义一个全局变量树
SecondTree seTree;
//定义全局变量,用来判断是否有此亲节点;
bool boolen=false;

//定义一个队,层次遍历时用
typedef struct Queue
{
char chardate;
struct Queue *next;

}* LQueue;

//判断队是否为空
bool isEmpaty(LQueue D);
//入队操作
void PushQueue(LQueue D,char pchar);
//出队函数,返回值char类型
char PopQueue(LQueue D);
//通过父节点,返回孩子节点
bool returnSun(SecondTree T,char f,char &sun1,char &sun2);
//层次遍历二叉树
void CengCi(SecondTree T);
//中序遍历二叉树
void MidTree(SecondTree Tree);
//先序遍历二叉树
void PreTree(SecondTree Tree);
//创建二叉树
void CreateBTNode(BTNode *);
//用先序遍历创建二叉树
//系统默认生成的广义表
//查找节点
bool findTree(SecondTree T,char f);
//插入节点
bool TreeInsert(SecondTree &T,char parent,char insert);
//删除节点
bool delNode(SecondTree &T,char delchar);
//主菜单
void Menu();
//导航栏
int MenuMethod();

int main()
{

MenuMethod();

return 0;
}

//创建二叉树
void CreateBTNode(BTNode *)
{

BTNode *&T=seTree;
cout<<endl<<"程序默认了一个以广义表形式构造的二叉树。无需手动输入。返回主菜单。"<<endl;

char c[19]="A(B(D(,G)),C(E,F))";

BTNode*St[10],*p;

int top=-1,k,j=0;
char ch;

T=NULL;
ch=c[j];
while(ch!='\0')
{
switch(ch)
{
case '(' :top++;St[top]=p;k=1;break;//开始处理左孩子节点
case ')' :top--;break;
case ',' :k=2;break;//开始处理右孩子节点
default :p=new BTNode;
p->date =ch;
p->lchild=p->rchild=NULL;
if(T==NULL)//尚未建立根节点
{
T=p;//*p为根节点
}
else
{
switch(k)
{
case 1:St[top]->lchild=p;break;
case 2:St[top]->rchild=p;break;
}
}
}
j++;
ch=c[j];

}
}

//查找节点元素  如果T中存在字符f则返回true,并打印出一句话”f 字符已找到!“。否则返回false
bool findTree(SecondTree T,char f)
{
SecondTree top=T;
if(T==NULL)
{
return false;
}
if(T->date!=f)
{
findTree(T->lchild, f);
findTree(T->rchild, f);

}
else
{
cout<<f<<" 字符已找到!!!!!"<<endl;
return true;
}

return false;
}
/*

插入节点元素,如果找不到要插入节点的双亲则返回false 找到结点后若已存在对应
位置的孩子结点则不插入返回false ,若找到结点后没有字节点 ,则插入节点元素返回true
*/
bool TreeInsert(SecondTree &T,char parent,char insert)
{

//SecondTree top=T;
BTNode *Jnode;
if(T==NULL)
{
return false;
cout<<"二叉树为空。"<<endl;
}

else if(T->date==parent )
{
boolen=true;
if (T->lchild!=NULL&&T->rchild!=NULL)
{
cout<<"左右孩子节点都已经存在。无须再插入。"<<endl;
return false;

}
else if (T->lchild==NULL)
{
Jnode=new node;
Jnode->date=insert;
Jnode->lchild=NULL;
Jnode->rchild=NULL;
T->lchild=Jnode;

cout <<"插入左孩子节点成功"<<endl;
return true;
}
else  if(T->rchild==NULL)
{
Jnode=new node;
Jnode->date=insert;
Jnode->lchild=NULL;
Jnode->rchild=NULL;
T->rchild=Jnode;

cout <<"插入右孩子节点成功"<<endl;
return true;
}

}
else if(T->date!=parent)
{
TreeInsert(T->lchild,parent,insert);

TreeInsert(T->rchild,parent,insert);

}

return false;
}

//定义删除节点函数,第一个参数为指向树的指针,第二个参数为要删除的节点字符
bool delNode(SecondTree &T,char delchar)
{
if (T!=NULL)
{

//如果跟节点不为空
if (T->date==delchar)
{//如果根节点为要删除的节点···
cout<<"已找到节点!!下面执行删除"<<endl;
/**/
delete T->lchild;
T->lchild=NULL;
delete T->rchild;
T->rchild=NULL;
delete T;
T=new node;
T->lchild=NULL;
T->rchild=NULL;
return true;

}
else if (T->lchild!=NULL&&T->lchild->date==delchar)
{
//如果左孩子为要删除的节点
cout <<"删除左孩子:"<<endl;
delete T->lchild->lchild;
delete T->lchild->rchild;
delete T->lchild;
T->lchild=NULL;
return true;

}
else if (T->rchild!=NULL&&T->rchild->date==delchar)
{
//如果左孩子为要删除的节点
cout <<"删除右孩子:"<<endl;

delete T->rchild->lchild;
delete T->rchild->rchild;
delete T->rchild;
T->rchild=NULL;
return true;
}
else
{
if(T->lchild!=NULL)
{
//如果左孩子不为空
delNode(T->lchild,delchar);
}
if(T->rchild!=NULL)
{
//如果右孩子不为空
delNode(T->rchild,delchar);
}

}
}

return false;

}

//定义目录函数
void Menu(){
cout<<endl<<"                                二叉树操作"<<endl;
cout<<endl;
cout<<"********************************************************************************";
cout <<endl<<"功能表:    "<<endl<<endl;
cout <<"        1:  先序遍历创建树;                2:  中序遍历树;"<<endl<<endl;
cout <<"        3:  先序遍历树;                    4:  层次遍历;"<<endl<<endl;
cout <<"        5:  插入节点;                      6:  删除节点;"<<endl<<endl;
cout <<"        7:  查找节点;                      8:  结束操作;"<<endl;
cout<<endl<<"********************************************************************************"<<endl;

}

int MenuMethod()
{
char Cnumber;
//输出目录
Menu();

cout <<endl<<"请您按键选择:"<<endl;
cin >>Cnumber;

while(Cnumber!=0)
{
switch(Cnumber)
{

case '1':
//先序遍历创建树
CreateBTNode(seTree);
break;
case '2':
cout<<"中序遍历结果:"<<endl;
MidTree(seTree);//调用中序遍历
cout<<"返回主菜单。"<<endl;
break;

case '3':
cout<<"先序遍历结果:"<<endl;
PreTree(seTree);//调用先序遍历
cout<<"返回主菜单。"<<endl;
break;

case '4':
//层次遍历
CengCi(seTree);
cout<<"返回主菜单。"<<endl;
break;
case '5':
//插入字符
char parent,insert;
cout<<"请输入你要插入字符的双亲:"<<endl;
cin>>parent;
cout<<"输入你要插入的字符"<<endl;
cin>>insert;
TreeInsert(seTree,parent,insert);
if(boolen==false)
{
cout<<"插入失败,不存在此双亲。,返回主菜单。"<<endl;
}
break;
case '6':
//删除节点
char delchar;
cout <<"请输入你要删除的节点字符:"<<endl;
cin >>delchar;
delNode(seTree,delchar);
cout<<"返回主菜单。"<<endl;
break;

case '7':
//调用查找树的节点函数

char f;
cout<<"请输入你要查找的字符"<<endl;
cin>>f;
findTree(seTree, f);
break;
case '8':
return 0;
break;
default :
//如果输入错误
cout <<"输入错误!!!请重新输入!"<<endl;
break;
}
Menu();//输出目录
cout <<endl<<"请输入你的选择:"<<endl;
cin >>Cnumber;
}
return 0;
}

//判断队是否为空
bool isEmpaty(LQueue D)
{
if (D->next==NULL)
{
return true;
}
else
return false;
}
//入队操作
void PushQueue(LQueue D,char pchar)
{
while (D->next!=NULL)
{
D=D->next;
}

D->next=new Queue;
D->next->chardate=pchar;
D->next->next=NULL;

}
//出队函数,返回值char类型
char PopQueue(LQueue D)
{

char pchar;
if(D->next!=NULL)
{
pchar=D->next->chardate;
}
else
{
pchar='#';
return pchar;
}
if (D->next->next!=NULL)
{
D->next=D->next->next;
}
else
{
D->next=NULL;
}
return pchar;

}

//通过父节点,返回孩子节点
bool returnSun(SecondTree T,char f,char &sun1,char &sun2)
{

SecondTree top=T;
if(T==NULL)
{
return false;
}
if(T->date!=f)
{
if (T->lchild!=NULL)
returnSun(T->lchild, f,sun1,sun2);
if (T->rchild!=NULL)
returnSun(T->rchild, f,sun1,sun2);

}
else
{
//cout<<f<<" 字符已找到lelelell!"<<endl;
if (T->lchild!=NULL)
{      //如果左孩子不为空,把其值储存到sun1中
sun1=T->lchild->date;
}
else
{
sun1='#';
}
if (T->rchild!=NULL)
{     //如右孩子不为空,把其值储存到sun2中
sun2=T->rchild->date;
}
else
{
sun2='#';
}

return true;
}

return false;
}

//层次遍历二叉树
void CengCi(SecondTree T)
{

SecondTree Top=T;
LQueue TopQueue;
TopQueue=new Queue;
cout<<endl<<"层次遍历二叉树: "<<endl;
TopQueue->next=NULL;
if (T!=NULL)
{  //如果头结点不为空,读出头结点。
cout <<T->date<<endl;
//如果左孩子不为空,入队
if (T->lchild!=NULL)
{
PushQueue(TopQueue,T->lchild->date);
}
//如果右孩子不为空,入队

if (T->rchild!=NULL)
{
PushQueue(TopQueue,T->rchild->date);
}
}
//while 队不为空,出队 ,读该节点,把孩子入队
char pchar;
char sun1,sun2;

if (!isEmpaty(TopQueue))
{
while (!isEmpaty(TopQueue))
{
//出队
pchar=PopQueue(TopQueue);
//找到pchar 读出它
cout<<pchar<<endl;
returnSun(T,pchar,sun1,sun2);//获得出队元素的左右孩子
if(sun1!='#')
{//左孩子不为空。则入队
PushQueue(TopQueue,sun1);
}
if(sun2!='#')
{//右孩子不为空。则入队
PushQueue(TopQueue,sun2);
}
}
}

}

//中序遍历二叉树
void MidTree(SecondTree Tree)
{
SecondTree top=Tree;
if(top!=NULL)
{    //如果节点不为空

MidTree(top->lchild); //先序遍历左子树

cout<<top->date<<endl;//输出节点数
MidTree(top->rchild);//先序遍历右子树

}

}

//先序遍历二叉树,参数为指向结构体变量的指针
void PreTree(SecondTree Tree)
{

SecondTree top=Tree;
if(top!=NULL)
{    //如果节点不为空
cout<<top->date<<endl;//输出节点数
PreTree(top->lchild); //先序遍历左子树
PreTree(top->rchild);//先序遍历右子树
}

}


输出结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: