关于二叉树的创建、遍历等问题
树是一种非线性结构,其中以二叉树应用最为广泛,比如说优化算法的堆排就是以二叉树为基础;所以先来从二叉树的创建、遍历总结起;定义二叉树 以及节点的空间申请 用遍历结果创建二叉树 计算叶子节点个数、节点个数、各种分支个数等
- 定义二叉树 以及节点的空间申请
typedef char ElemType;
typedef struct node
{
node * leftchild;
node *rightchild;
ElemType data;
}BTtree;
BTtree *buynode()
{
BTtree *s=(BTtree *)malloc(sizeof(BTtree));
if(s==NULL)exit(0);
return s;
}
- 创建二叉树 (首先以一种简单的方法创建二叉树:假设二叉树的左右孩子为NULL时用’#’来代替)
BTtree* creat_tree1()
{
BTtree *s=NULL;
ElemType tmp;
scanf("%c",&tmp);
if(tmp!='#')
{
s=buynode(); //节点空间的申请
s->data=tmp;
s->leftchild=creat_tree1(); //通过递归来创建二叉树
s->rightchild=creat_tree1();
}
return s;
}
当然这种方法比较简单,接下来先总结二叉树的遍历然后再总结通过不同的遍历顺序来创建二叉树
3. 二叉树的遍历(觉得老师上课讲的二叉树例子特别有代表性)
(1)、先序遍历(结果为:ABCDEFGH)
void pre_order(BTtree *r)
{
if(r==NULL)return;
pre_order(r->leftchild); //三种遍历的方法都是采用递归
printf("%c ",r->data);
pre_order(r->rightchild);
}
(2)、中序遍历(结果为:CBEDFAGH )
void in_order(BTtree *r)
{
if(r==NULL)return;
in_order(r->leftchild);
printf("%c ",r->data);
in_order(r->rightchild);
}
(3)、后序遍历(结果为:CEFDBHGA)
void las_order(BTtree *r)
{
if(r==NULL)return;
las_order(r->leftchild);
las_order(r->rightchild);
printf("%c ",r->data);
}
- 已知两种不同的遍历顺序创建二叉树
(1)已知先序和中序来创建二叉树
int find(char *is,int n,ElemType x)//find函数的目的是比较数据是否在两种遍历次序中都有出现并返回中序中的位置
{
for(int i = 0;i<n;++i)
{
if(is[i] == x)
return i;
}
return -1;
}
BTtree * cre_pi(char *ps,char *is,int n)
{
int pos = find(is,n,ps[0]);//调用find 如果没有找到则说明先序中的数据在中序中没有找到
if(pos == -1) exit(1);
BTtree *s = NULL;
if(n > 0)
{
s = buynode();
s->data = ps[0];
s->leftchild = cre_pi(ps+1,is,pos);//分为左右子树来创建时注意每次传入的位置
s->rightchild = cre_pi(ps+pos+1,is+pos+1,n-pos-1);
}
return s;
}
BTtree * create_pi(char *ps,char *is)
{
if(ps == NULL || is == NULL)
{
return NULL;
}else
{
int n = strlen(ps);
return cre_pi(ps,is,n);
}
}
(2)已知中序和后序来创建二叉树
BTtree * cre_il(char *is,char *ls,int n)
{
int pos=Find(is,n,ls[n-1]);
if(pos==-1)exit;
BTtree *s=NULL;
if(n>0)
{
s=buynode();
s->data=ls[n-1];
s->leftchild=cre_il(is,ls,pos);
s->rightchild=cre_il(is+pos+1,ls+pos,n-pos-1);
}
return s;
}
BTtree * creat_il(char *is,char *ls)
{
if(is==NULL || ls==NULL) return NULL;
else
{
int n=strlen(is);
return cre_il(is,ls,n);
}
}
在创建二叉树时,只考虑了一种没有重复数据的二叉树创建方法,如果有重复数据,则可能创建出错误的二叉树;关于这个问题,还有待思考。。。
- 二叉树的某些常用函数
(1)二叉树的节点个数
int size(BTtree *ptr)
{
int size=0;
if(ptr==NULL) size=0;
else size=1+size(ptr->leftchild)+size(ptr->rightchild);
return size;
}
(2)二叉树的叶子节点个数
int size_leaf(BTtree *ptr)
{
if(ptr==NULL) return 0;
else if(ptr->leftchild==NULL && ptr->rightchild==NULL) return 1;
else return size_leaf(ptr->leftchild)+size_leaf(ptr->rightchild);
}
(3)二叉树的深度
int depth(BTtree *ptr)
{
if(ptr==NULL)return 0;
else
{
return depth(ptr->leftchild)>depth(ptr->rightchild)?
depth(ptr->leftchild)+1 :depth(ptr->rightchild)+1;
}
}
(4)判断是否为满二叉树
bool full_binarytree(BTtree *ptr)
{
int d=depth(ptr);//树的深度
int le=size_leaf(ptr);//叶子节点
int n=pow(2,(d-1)*1.0);//求满二叉树的叶子节点
if(le==n)return 1;
else return 0;
}
(5)求树的双分支节点个数
int size_treebrch(BTtree *ptr)
{
if(ptr==NULL)return 0;
else
{
int size=0;
if(ptr->leftchild!=NULL && ptr->rightchild!=NULL)size=1;
return size+size_treebrch(ptr->leftchild)+size_treebrch(ptr->rightchild);
}
}
(6)求二叉树的单分支节点个数
int size_onebrch(BTtree *ptr)
{
if(ptr==NULL)return 0;
else
{
int size=0;
if(ptr->leftchild!=NULL && ptr->rightchild==NULL || ptr->leftchild==NULL && ptr->rightchild!=NULL ) size=1;
return size+size_onebrch(ptr->leftchild)+size_onebrch(ptr->rightchild);
}
}
(7)求二叉树的左单分支节点个数
int size_onelbrch(BTtree *ptr)
{
if(ptr==NULL)return 0;
else
{
int size=0;
if(ptr->leftchild!=NULL && ptr->rightchild==NULL)size=1;
return size+size_onelbrch(ptr->leftchild)+size_onelbrch(ptr->rightchild);
}
}
(8)求二叉树的右单分支节点个数
int size_onerbrch(BTtree *ptr)
{
if(ptr==NULL)return 0;
else
{
int size=0;
if(ptr->leftchild==NULL && ptr->rightchild)size=1;
return size+size_onerbrch(ptr->leftchild)+size_onerbrch(ptr->rightchild);
}
}
在利用中序先序或者中序后序(先序后序是没有办法创建二叉树的,因为没有办法确定左右子树从哪里分)来建立二叉树时,除过递归的方法 用栈也可以实现 这个以后再总结