顺序存储结构--将二叉树按层序依次存入数组中
已知一个节点在数组中序号为i,则该节点的
双亲节点序号为:((i+1)/2)-1
左孩子: 2*i+1
右孩子: 2*i+2
代码实现关键点:
1.创建二叉树CreateBiTree():按层次顺序输入二叉树中节点的值
1)对非空无双亲的非根节点的判断 if(i!=0&&T[(i+1)/2-1]==0&&T[i]!=0)
非根节点--i!=0;无双亲--T[(i+1)/2-1]=Nil;非空--T[i]=Nil
此种节点的存在不合理:除根节点外,其他非空节点都有双亲节点。如果出现 非根,非空,但又没有双亲的节点,
则该该节点不合法。
2.得到二叉树的深度BiTreeDepth
先得到节点数,然后利用二叉树性质2(深度为k的二叉树至多有(2^k)-1个节点)得到深度。
3.Assign()给处于位置(level,order)的节点赋值。(level,order)表示(层,层序),从左到右
因为二叉树第k层最多有2^(k-1)个节点,所以有对赋值节点位置越界的判断
if(level>BiTreeDepth(T)||order>(int)powl(2,level-1))
int pos = (int)powl(2,e.level-1)+e.order-2 ---将(level,order)转化为节点在数组的位置
两种不合法赋值判断:1).给叶子赋值,但是双亲为空;2).给双亲赋空值,但是其有叶子节点(非空)
1)---if(value!=Nil&&T[(pos+1)/2-1]==Nil)
2)---if(value==Nil&&(T[pos*2+1]!=Nil||T[pos*2+2]!=Nil))
3.RightSibling返回节点e的右兄弟,否则返回空
if(T[i]==e&&i%2!=0)---找到e,且i为奇数--左孩子,则其右兄弟为T[i+1]
4.三种遍历:先序,中序,后序
三者在代码上没有太大区别,只是反问局部根节点的顺序分别为:左根右、根左右、左右根
判断是否为左孩子:if(T[2*i+1]!=Nil)
判断是否为右孩子:if(T[2*i+2]!=Nil)
代码(站在巨人的肩膀上)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 100
#define MAX_TREE_SIZE 100
typedef int Status;
typedef int TElemType;
typedef TElemType SqBiTree[MAX_TREE_SIZE];//将SqBiTree定义为元素TElemType的数组
typedef struct
{
int level,order;
}Position;
TElemType Nil = 0;//Nil表示无值,是object-c,Ruby,Lua中的关键字
//创建空树,此处树中每个节点都为0
Status InitBiTree(SqBiTree T)
{
for(int i = 0;i<MAXSIZE;i++)
{
T[i]=0;//The initial data of the tree node is zero
}
return OK;
}
//创建树,按层次顺序输入二叉树中节点的值
Status CreateBiTree(SqBiTree T)
{
int i=0;
if(NULL==T)
{
return ERROR;
}
printf("请按层顺序输入节点的值(整型),0表示空节点,输入0结束.节点树<%d\n",MAX_TREE_SIZE);
while(i<20)
{
T[i]=i+1;
if(i!=0&&T[(i+1)/2-1]==0&&T[i]!=Nil)//二叉树中没有此内节点。非根节点--i!=0;无双亲--T[(i+1)/2-1]==Nil;非空节点--T[i]!=Nil
{
printf("出现非空的无双亲的非根节点%d\n",T[i]);
exit(ERROR);
}
i++;
}
while(i<MAX_TREE_SIZE)
{
T[i] = 0;
i++;
}
return OK;
}
//ClearBiTree将树的节点数据清零,相当于函数InitTree
#define ClearBiTree InitBiTree
//初始条件:二叉树存在
//操作结果:EmptyBiTree检查树是否为空,如果为空返回TRUE,否则返回FALSE
Status EmptyBiTree(SqBiTree T)
{
if(NULL==T)
{
return ERROR;
}
if(Nil==T[0]) //根节点为空,则树为空
{
return TRUE;
}
return FALSE;
}
//初始条件:二叉树存在
//操作结果:返回树的深度(层)
int BiTreeDepth(SqBiTree T)
{
if(NULL==T)
{
return ERROR;
}
int i,j=0;
for(i=MAX_TREE_SIZE-1;i>=0;i--)
{
if(T[i]!=Nil)
{
break;
}
}
i++; //节点数
while(i>=powl(2,j)) //二叉树性质:深度为k的二叉树至多有(2^k)-1个节点
{
j++;
}
return j;
}
//初始条件:二叉树存在
//操作结果:得到根节点,并用e返回根,返回OK;否则返回ERROR
Status Root(SqBiTree T,TElemType *e)
{
if(EmptyBiTree(T))
{
return ERROR;
}else
{
*e = T[0];
return OK;
}
}
//初始条件:二叉树存在
//操作结果:返回指定节点的值,没有则返回ERROR;Position(层,本层序号)确定节点位置
TElemType Value(SqBiTree T,Position e)
{
if(NULL==T)
{
return ERROR;
}
if(0==T[0])
{
return ERROR;
}
if(e.level>BiTreeDepth(T)||e.order>(int)powl(2,e.level-1))//节点不存在
{
return ERROR;
}
int pos = (int)powl(2,e.level-1)+e.order-2;//根据e确定节点在数组中的位置
return T[pos];
}
//初始条件:二叉树存在
//操作处理:给处于e的树T的节点赋值value,没有则返回ERROR
Status Assign(SqBiTree T,Position e,TElemType value)
{
if(NULL==T)
{
return ERROR;
}
if(e.level>BiTreeDepth(T)||e.order>(int)powl(2,e.level-1))//位置越界
{
return ERROR;
}
int pos = (int)powl(2,e.level-1)+e.order-2; //将Position转化为节点在数组的位置
if(value!=Nil&&T[(pos+1)/2-1]==Nil)//给叶子赋值,但是双亲为空
{
return ERROR;
}else if(value==Nil&&(T[pos*2+1]!=Nil||T[pos*2+2]!=Nil))//给双亲赋空值,但是有叶子节点(不空)
{
return ERROR;
}
T[pos] = value;
return OK;
}
//初始条件:二叉树存在
//操作处理:返回非根节点e的双亲节点,没有则返回“空”
TElemType Parent(SqBiTree T,TElemType e)
{
if(NULL == T)
{
return ERROR;
}
int i;
for(i=0;i<MAX_TREE_SIZE-1;i++)//顺序结构,遍历方便
{
if(e==T[i])
{
return T[(i+1)/2-1];//找到则返回其双亲节点T[(i+1)/2-1]
}
}
return Nil; //没找到则返回空
}
//初始条件:二叉树存在
//操作处理:若e是树T的非叶节点,则返回它的左孩子,否则返回空
TElemType LeftChild(SqBiTree T,TElemType e)
{
if(NULL==T)
{
return ERROR;
}
int i;
for(i=0;i<MAX_TREE_SIZE;i++)
{
if(e==T[i])
{
return T[i*2+1];//找到返回其左孩子
}
}
return Nil;
}
//初始条件:二叉树存在
//操作处理:返回节点e的右兄弟,否则返回空
TElemType RightSibling(SqBiTree T,TElemType e)
{
if(NULL==T)
{
return ERROR;
}
if(Nil==T[0])
{
return Nil;
}
int i;
for(i=0;i<=MAX_TREE_SIZE-1;i++)
{
if(T[i]==e&&i%2!=0)//找到e,且i为奇数--左孩子
return T[i+1];
}
return Nil;
}
//访问某个节点--打印节点值
Status visit(TElemType c)
{
printf("%d ",c);
return OK;
}
//先序遍历:被调函数
void PreTraverse(SqBiTree T,int i)
{
visit(T[i]); //访问根节点
if(T[2*i+1]!=Nil) //如果有左孩子,先访问左孩子
{
PreTraverse(T,2*i+1);
}
if(T[2*i+2]!=Nil)//如果有右孩子,后访问右孩子
{
PreTraverse(T,2*i+2);
}
}
//初始条件:二叉树存在
//操作处理:先序遍历树T
Status PreOrderTraverse(SqBiTree T)
{
if(!EmptyBiTree(T))
{
PreTraverse(T,0);
}
printf("\n");
return OK;
}
//中序遍历:被调函数。思路同PreTraverse
void InTraverse(SqBiTree T,int i)
{
if(T[i*2+1]!=Nil)
{
InTraverse(T,i*2+1);
}
visit(T[i]);
if(T[i*2+2]!=Nil)
{
InTraverse(T,i*2+2);
}
}
//初始条件:二叉树存在
//操作处理:中序遍历树T
Status InOrderTraverse(SqBiTree T)
{
if(!EmptyBiTree(T))
{
InTraverse(T,0);
}
printf("\n");
return OK;
}
int main()
{
SqBiTree T;
CreateBiTree(T);
/*返回树的深度*/
int depth = BiTreeDepth(T);
printf("深度:%d\n",depth);
/*返回特定位置的节点的值*/
printf("返回特定位置的节点值---输入节点位置:\n");
Position e;
scanf("%d %d",&e.level,&e.order);
TElemType value = Value(T,e);
printf("处于位置e的节点值为:%d\n",value);
/*给特定节点赋值*/
printf("给特定节点赋值---输入节点位置:\n");
Position pos;
scanf("%d %d",&pos.level,&pos.order);
Status sts = Assign(T,pos,4);
if(OK==sts)
{
printf("节点e被赋值为:%d\n",T[(int)powl(2,pos.level-1)+pos.order-2]);
}else
{
printf("赋值失败!\n");
}
/*返回双亲节点*/
printf("返回双亲节点---输入节点值:\n");
TElemType c;
scanf("%d",&c);
TElemType parent = Parent(T,c);
printf("双亲节点值为:%d\n",parent);
/*返回右兄弟*/
printf("返回右兄弟节点---输入节点值:\n");
TElemType d;
scanf("%d",&d);
TElemType rightsibling = RightSibling(T,d);
printf("右兄弟节点值为:%d\n",rightsibling);
/*先序遍历*/
PreOrderTraverse(T);
/*中序遍历*/
InOrderTraverse(T);
}