二叉树的顺序存储结构

一、程序如下

/*
项目名称:二叉树的顺序存储结构
编译环境:VC++ 2008
作者相关:。。。
最后修改:2019.10.13
学习目标:1.掌握二叉树顺序存储结构的基本操作
注意事项:1.测试所有功能是否正常
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define  MAX_TREE_SIZE 100//二叉树最大结点数
#define  OK            1
#define  ERROR         0
#define  FALSE         0
#define  TRUE          1

#define ClearBiTree InitBiTree

typedef bool  Status;
typedef int   TElemType;
typedef TElemType SqBiTree[MAX_TREE_SIZE];//0号单元存储根节点

typedef struct
{
	int level,order;//结点的层,本层序号(每层从1开始)
}Position;

TElemType Nil=0;//设整型以0为空

Status InitBiTree(SqBiTree T);

Status CreatBiTree(SqBiTree T);

Status BiTreeEmpty(SqBiTree T);

int    BiTreeDepth(SqBiTree T);

Status Root(SqBiTree T,TElemType *e);

TElemType Value(SqBiTree T,Position e);

Status Assign(SqBiTree T,Position e,TElemType value);

TElemType Parent(SqBiTree T,TElemType e);

TElemType LeftChild(SqBiTree T,TElemType e);

TElemType RightChild(SqBiTree T,TElemType e);

TElemType LeftSibling(SqBiTree T,TElemType e);

TElemType RightSibling(SqBiTree T,TElemType e);

void PreTraverse(SqBiTree T,int e);

Status PreOrderTraverse(SqBiTree T);

void InTraverse(SqBiTree T,int e);

Status InOrderTraverse(SqBiTree T);

void PostTraverse(SqBiTree T,int e);

Status PostOrderTraverse(SqBiTree T);

void LevelOrderTraverse(SqBiTree T);

void Print(SqBiTree T);

Status visit(TElemType c);

int main()
{
	Status i;
	TElemType e;
	SqBiTree T;
	Position p;

	InitBiTree(T);
	CreatBiTree(T);
	printf("建立二叉树后,树空否?%d(1:是 0:否)\n",BiTreeEmpty(T));
	printf("树的深度为:%d\n",BiTreeDepth(T));

	i=Root(T,&e);
	if(i)
		printf("二叉树的根为: %d\n",e);
	else
		printf("树空,无根\n");

	printf("层序遍历二叉树:\n");
	LevelOrderTraverse(T);
	printf("前序遍历二叉树:\n");
	PreOrderTraverse(T);
	printf("中序遍历二叉树:\n");
	InOrderTraverse(T);
	printf("后序遍历二叉树:\n");
	PostOrderTraverse(T);

	printf("修改结点的层号3本层序号2\n");
	p.level=3;
	p.order=2;
	e=Value(T,p);
	printf("待修改结点的原值为%d,请输入新值:50\n",e);
	e=50;
	Assign(T,p,e);
	printf("前序遍历二叉树:\n");
	PreOrderTraverse(T);

	printf("结点%d的双亲为%d,左右孩子分别为",e,Parent(T,e));
	printf("%d,%d,左右兄弟分别为",LeftChild(T,e),RightChild(T,e));
	printf("%d,%d\n",LeftSibling(T,e),RightSibling(T,e));
	ClearBiTree(T);

	ClearBiTree(T);
	printf("清除二叉树后,树空否?%d(1:是 0:否)\n",BiTreeEmpty(T));
	i=Root(T,&e);
	if(i)
		printf("二叉树的根为:%d\n",e);
	else
		printf("树空,无根\n");

	return 0;
}
//建立一棵空树
Status InitBiTree(SqBiTree T)
{
	for(int i=0;i<MAX_TREE_SIZE;i++)
		T[i]=Nil;
	return OK;
}
//按层次次序输入二叉树结点中的值,构造二叉树
Status CreatBiTree(SqBiTree T)
{
	int i=0;
	printf("下面建立值为1~10的二叉树:\n");
	while(i<10)
	{
		T[i]=i+1;//给树赋值1-10
		if(i!=0&&T[(i+1)/2-1]==Nil&&T[i]!=Nil)
		{
			printf("出现无双亲的非根节点%d\n",T[i]);
			exit(ERROR);
		}
		i++;
	}    

	return OK;
}

Status BiTreeEmpty(SqBiTree T)
{
	if(T[0]==Nil)//根节点为空,则树空
		return TRUE;
	else
		return FALSE;
}
/*
1.求树的深度
2.2^(k-1)<=depth<=2^k
*/
int BiTreeDepth(SqBiTree T)
{
	if(BiTreeEmpty(T))
		return 0;

	int i,depth=1;
	for(i=MAX_TREE_SIZE-1;i>=0;--i)//找到最后的结点
		if(T[i]!=Nil)
			break;
	++i;//得到结点数
	while(i>=powl(2,depth))//powl表示求2的depth次幂
	{
		++depth;
	}

	return depth;
}
//若T非空,则用e返回T的根
Status Root(SqBiTree T,TElemType *e)
{
	if(BiTreeEmpty(T))
		return ERROR;
	else
	{
		*e=T[0];
		return OK;
	}
}
//若T存在,e是T中结点位置,返回该位置结点的值
/*
1.level层从1~n结点     2.对应的本层次序
       2^(level-1)          1
       2^(level-1)+1        2
       2^(level-1)+2        3
       2^(level-1)+3        4
       ......
       2^(level-1)+n        n+1

2.可见n+1-n==1,设本层次序为e.order,第level层结点为2^(level-1)+a
那么a=e.order-1

3.那么该结点位置为2^(level-1)+e.order-1,该结点对应的值为
T[2^(level-1)+e.order-2]
*/
TElemType Value(SqBiTree T,Position e)
{
	if(BiTreeEmpty(T))
		return ERROR;
	else
		return T[(int)powl(2,e.level-1)+e.order-2];
}
//T存在,给处于位置e的结点重新赋值
Status Assign(SqBiTree T,Position e,TElemType value)
{
	int i=(int)powl(2,e.level-1)+e.order-2;

	if(value!=Nil&&T[(i+1)/2-1]==Nil)//给结点赋非空值但双亲为空
		return ERROR;//例如完全二叉树按层序:1,0,3,0,0,4,5,给T[3]赋值就出错
	else if(value==Nil&&(T[i*2+1]!=Nil||T[i*2+2]!=Nil))//给双亲赋空值但有叶子不空
		return ERROR;

	T[i]=value;
	return OK;
}
//T存在,e为非根结点,返回它的双亲
TElemType Parent(SqBiTree T,TElemType e)
{
	if(BiTreeEmpty(T))
		return ERROR;
	for(int i=1;i<MAX_TREE_SIZE;++i)
		if(T[i]==e)
			return T[(i+1)/2-1];

	return Nil;//没有找到e
}
//T存在,e是T中某结点,返回其左孩子,没有就返回空
TElemType LeftChild(SqBiTree T,TElemType e)
{
	if(BiTreeEmpty(T))
		return ERROR;
	for(int i=0;i<MAX_TREE_SIZE;++i)
		if(T[i]==e)
			return T[2*i+1];

	return Nil;
}
//T存在,e是T中某结点,返回其右孩子,没有就返回空
TElemType RightChild(SqBiTree T,TElemType e)
{
	if(BiTreeEmpty(T))
		return ERROR;
	for(int i=0;i<MAX_TREE_SIZE;++i)
		if(T[i]==e)
			return T[2*i+2];

	return Nil;
}
//T存在,e是T中某结点,返回e的左兄弟;若e是左孩子或无左兄弟返回空
TElemType LeftSibling(SqBiTree T,TElemType e)
{
	if(BiTreeEmpty(T))
		return ERROR;
	for(int i=1;i<MAX_TREE_SIZE;++i)
		if(T[i]==e&&i%2==0)//找的e并且序号为偶数(右孩子)
			return T[i-1];
	return Nil;
}
//T存在,e是T中某结点,返回e的右兄弟;若e是右孩子或无右兄弟返回空
TElemType RightSibling(SqBiTree T,TElemType e)
{
	if(BiTreeEmpty(T))
		return ERROR;
	for(int i=1;i<MAX_TREE_SIZE;++i)
		if(T[i]==e&&i%2==1)//找的e并且序号为奇数(左孩子)
			return T[i+1];
	return Nil;
}
//PreOrderTraverse()调用
/*
递归调用
1.确定函数功能:先序遍历树,即"根左右"
2.确定递归终止条件,遍历左/右孩子时,结点为空时停止
3.确定联系,假设3个结点:0,1,2,发现PreTraverse(T,0)就能先序遍历这3个结点
4.因为1,2是0的两个孩子,假设结点为e,那么它的两个孩子就是2*e+1和2*e+2
*/
void PreTraverse(SqBiTree T,int e)
{
	visit(T[e]);
	if(T[2*e+1]!=Nil)//递归结束条件,左子树不空
		PreTraverse(T,2*e+1);

	//注意:上面这个递归结束后,下面这个e仍从0开始
	if(T[2*e+2]!=Nil)//递归结束条件,右子树不空
		PreTraverse(T,2*e+2);
}
//T存在,先序遍历T
Status PreOrderTraverse(SqBiTree T)
{
	if(BiTreeEmpty(T))
		return ERROR;
	PreTraverse(T,0);
	printf("\n");

	return OK;
}
//供InOrderTraverse调用
void InTraverse(SqBiTree T,int e)
{
	if(T[2*e+1]!=Nil)//左子树不空
		InTraverse(T,2*e+1);
	visit(T[e]);
	if(T[2*e+2]!=Nil)//右子树不空
		InTraverse(T,2*e+2);
}
//T存在,中序遍历,"左根右"
Status InOrderTraverse(SqBiTree T)
{
	if(BiTreeEmpty(T))
		return ERROR;
	InTraverse(T,0);
	printf("\n");

	return OK;
}
//供PostOrderTraverse()调用,同样采用0,1,2找规律
void PostTraverse(SqBiTree T,int e)
{
	if(T[2*e+1]!=Nil)
		PostTraverse(T,2*e+1);
	if(T[2*e+2]!=Nil)
		PostTraverse(T,2*e+2);
	visit(T[e]);
}
//后序遍历,"左右根"
Status PostOrderTraverse(SqBiTree T)
{
	if(!BiTreeEmpty(T))
		PostTraverse(T,0);
	printf("\n");
	return OK;
}
//层序遍历二叉树
void LevelOrderTraverse(SqBiTree T)
{
	int i=MAX_TREE_SIZE-1;
	while(T[i]==Nil)
		--i;//找到最后一个非空结点对应的下标值
	for(int j=0;j<=i;j++)
		if(T[j]!=Nil)
			visit(T[j]);//只遍历非空的结点
	printf("\n");
}
//逐层、按本层序号输出二叉树;结点数i<=2^k-1
void Print(SqBiTree T)
{
	Position p;
	TElemType e;
	for(int depth=1;depth<=BiTreeDepth(T);depth++)
	{
		printf("在%d层: ",depth);
		for(int NodeOrder=1;NodeOrder<=powl(2,depth-1);NodeOrder++)
		{
			p.level=depth;
			p.order=NodeOrder;
			e=Value(T,p);
			if(e!=Nil)//只遍历非空结点
				printf("%d:%d ",NodeOrder,e);
		}
		printf("\n");
	}
}

//输出元素值
Status visit(TElemType c)
{
	printf("%d ",c);
	return OK;
}

二、结果

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值