数据结构中二叉树很重要,关于二叉树的操作包括二叉树的创建、遍历(先序、中序、后序、层序)、计算二叉树深度、显示结点数据、清空二叉树、计算叶子结点个数并输出等
一、二叉树的创建
1.在已知二叉树前序遍历(二叉树的结构已知)的情况下,可以通过递归的方法创建二叉树。将二叉树变成扩展二叉树,即把叶子结点的孩子补成#,作为标记
扩展之后
在输入的时候,需要输入: ab#d##c#e## (输入后,按enter键)
程序如下:
#include<iostream>
using namespace std;
typedef struct node
{
struct node *leftChild;
struct node *rightChild;
char data;
}BiTreeNode, *BiTree;
void createBiTree(BiTree &T)
{
char c;
cin >> c;
if('#' == c)
T = NULL;
else
{
T = new BiTreeNode;
T->data = c;
createBiTree(T->leftChild);
createBiTree(T->rightChild);
}
}
int main()
{
BiTree T;
createBiTree(T);
return 0;
}
参考:点击打开链接
2. 通过创建根结点、添加结点和左右子树的方法程序如下:
定义变量和树结点
#define MAXLEN 20 //最大长度
typedef char DATA; //定义元素类型
struct CBTType //定义二叉树结点类型
{
DATA data; //元素数据
CBTType * left; //左子树结点指针
CBTType * right; //右子树结点指针
};
初始化二叉树:将一个结点设置为二叉树的根结点
CBTType * InitTree()
{
CBTType * node;
if(node = new CBTType) //申请内存
{
cout<<"请先输入一个根节点数据:"<<endl;
cin>>node->data;
node->left=NULL;
node->right=NULL;
if(node!=NULL) //如果二叉树结点不为空
{
return node;
} else
{
return NULL;
}
}
return NULL;
}
查找结点:遍历二叉树中的每一个节点,逐个比较数据,当找到目标数据时将返回该数据所在结点的指针。
CBTType *TreeFindNode(CBTType *treeNode,DATA data)
{
CBTType *ptr;
if(treeNode==NULL)
{
return NULL;
}else
{
if(treeNode->data==data)
{
return treeNode;
}
else //分别向左右子树查找
{
if(ptr=TreeFindNode(treeNode->left,data)) //左子树递归查找
{
return ptr;
}
else if(ptr=TreeFindNode(treeNode->right,data)) //右子树递归查找
{
return ptr;
}
else
{
return NULL;
}
}
}
}
添加结点:在二叉树中添加结点数据,添加结点时除了要输入结点数据外,还需要指定其父结点,以及添加的结点作为左子树还是右子树。然后将该结点置为其父结点的左子树或者右子树。
void AddTreeNode(CBTType *treeNode)
{
CBTType *pnode,*parent;
DATA data;
char menusel;
if(pnode=new CBTType) //分配内存
{
cout<<"输入二叉树结点数据:"<<endl;
cin>>pnode->data;
pnode->left=NULL; //设置左子树为空
pnode->right=NULL; //设置左子树为空
cout<<"输入该结点的父结点数据"<<endl;
cin>>data;
parent=TreeFindNode(treeNode,data);//查找父结点,获得结点指针
if(!parent)
{
cout<<"没有找到父结点"<<endl;
delete pnode;
return ;
}
cout<<"1.添加该结点到左子树;2.添加该结点到右子树。请输入操作对应的数字。"<<endl;
do
{
cin>>menusel;
if(menusel=='1'||menusel=='2')
{
switch(menusel)
{
case '1': //添加结点到左子树
if(parent->left) //左子树不为空
{
cout<<"左子树结点不为空"<<endl;
}
else
{
parent->left=pnode;
cout<<"数据添加成功!"<<endl;
}
break;
case '2': //添加结点到右子树
if(parent->right) //右子树不为空
{
cout<<"右子树结点不为空"<<endl;
}
else
{
parent->right=pnode;
cout<<"数据添加成功!"<<endl;
}
break;
default:
cout<<"子节点选择error!"<<endl;
break;
}
}
}while(menusel!='1'&&menusel!='2');
}
}
int main()
{
CBTType *root=NULL; //root为指向二叉树根结点的指针
char menusel;
//设置根结点
root=InitTree();
//添加结点
do
{
cout<<"请选择菜单添加二叉树的结点:"<<endl;
cout<<"0.退出;1.添加二叉树的结点。"<<endl;
cin>>menusel;
switch(menusel)
{
case '1':
AddTreeNode(root);
break;
case '0':
break;
default:
cout<<"添加结点error"<<endl;
break;
}
}while(menusel!='0');
}
参考原网页:http://www.jb51.net/article/42068.htm
二. 二叉树的遍历
1.先序遍历
void DLRTree(CBTType *treeNode)
{
if(treeNode)
{
ShowNodeData(treeNode); //显示结点内容
DLRTree(treeNode->left); //显示左子树内容
DLRTree(treeNode->right); //显示右子树内容
}
}
2. 中序遍历
void LDRTree(CBTType *treeNode)
{
if(treeNode)
{
LDRTree(treeNode->left); //显示左子树内容
ShowNodeData(treeNode); //显示结点内容
DLRTree(treeNode->right); //显示右子树内容
}
}
3. 后续遍历
void LRDTree(CBTType *treeNode)
{
if(treeNode)
{
LRDTree(treeNode->left); //显示左子树内容
DLRTree(treeNode->right); //显示右子树内容
ShowNodeData(treeNode); //显示结点内容
}
}
3. 层序遍历
void LevelTree(CBTType *treeNode)
{
CBTType *p;
CBTType *q[MAXLEN]; //定义一个队列
int head=0,tail=0;
if(treeNode) //如果队首指针不为空
{
tail=(tail+1)%MAXLEN; //计算循环队列队尾序号
q[tail]=treeNode; //二叉树根指针进入队列
while(head!=tail)
{
head=(head+1)%MAXLEN; //计算循环队列的队首序号
p=q[head]; //获取队首元素
ShowNodeData(p); //输出队首元素
if(p->left!=NULL) //如果存在左子树
{
tail=(tail+1)%MAXLEN; //计算队列的队尾序号
q[tail]=p->left; //左子树入队
}
if(p->right!=NULL) //如果存在右子树
{
tail=(tail+1)%MAXLEN; //计算队列的队尾序号
q[tail]=p->right; //右子树入队
}
}
}
}
三、计算二叉树的深度
int Depth(BiTree T) //求二叉树的深度
{
int dep=0,depl,depr;
if(!T) dep=0;
else
{
depl=Depth(T->lchild);
depr=Depth(T->rchild);
dep=1+(depl>depr?depl:depr);
}
return dep;
}
四、显示结点数据
void ShowNodeData(CBTType *treeNode)
{
cout<<treeNode->data<<"\t"; //直接输出结点数据
}
五、清空二叉树
void ClearTree(CBTType *treeNode)
{
if(treeNode) //判断当前树不为空
{
ClearTree(treeNode->left); //清空左子树
ClearTree(treeNode->right); //清空右子树
delete treeNode; //释放当前结点所占用的内存
}
}
六、计算叶子结点并输出
int Sumleaf(BiTree T)
{ //求叶子节点的个数
int sum=0,m,n;
if(T)
{
if((!T->lchild)&&(!T->rchild))
{
sum++;
printf("%c ",T->data);
}
m=Sumleaf(T->lchild);
sum+=m;
n=Sumleaf(T->rchild);
sum+=n;
}
return sum;
}
参考网址:http://blog.163.com/almerzhimin@126/blog/static/15525631020103112347782/
以上内容总结转摘自以下博文或网页,感谢作者的贡献
http://www.jb51.net/article/42068.htm
http://blog.csdn.net/stpeace/article/details/8138303
http://blog.163.com/almerzhimin@126/blog/static/15525631020103112347782/