树结构是一种描述非线性关系的数据结构。对于树的基本概念不想过多赘述,可以自行查阅相关资料,这里主要讲解一种简单的树结构——二叉树。二叉树是树的一种特殊形式,它有n个结点,每个结点最多有两个子结点。二叉树的子树仍然是二叉树,二叉树的两个子树分别是左子树和右子树,因此二叉树也是有序树。二叉树又分为:完全二叉树和满二叉树,概念不再详述,自行查找。
完全二叉树的性质:
1、如果m!=1,则结点m的父节点为m/2;
2、如果2*m<=n,则m的左子树编号为2*m;若2*m>n则无左子树,也无右子树。
3、如果2*m+1<=n,则m的右子树编号为2*m+1;若2*m+1>n则无右子树。
完全二叉树的深度为[log2n]+1。
二叉树的存储方式:1、顺序存储 2、链式存储。
顺序存储即按层将二叉树存储到一个数组中,这里不再详述,重点讲链式存储。
二叉树的链式存储:
1、数据部分
class CBTType //定义二叉树结点类型
{
String data; //元素数据
CBTType left; //左子树结点指针
CBTType right; //右子树结点指针
}
2、初始化二叉树
CBTType InitTree() //初始化二叉树的根
{
CBTType node;
if((node=new CBTType())!=null) //申请内存
{
System.out.printf("请先输入一个根结点数据:\n");
node.data=input.next();
node.left=null;
node.right=null;
if(node!=null) //如果二叉树根结点不为空
{
return node;
}
else
{
return null;
}
}
return null;
}
3、添加结点
void AddTreeNode(CBTType treeNode) //添加结点
{
CBTType pnode,parent;
String data;
int menusel;
if((pnode=new CBTType())!=null) //分配内存
{
System.out.printf("输入二叉树结点数据:\n");
pnode.data=input.next();
pnode.left=null; //设置左右子树为空
pnode.right=null;
System.out.printf("输入该结点的父结点数据:");
data=input.next();
parent=TreeFindNode(treeNode,data); //查找指定数据的结点
if(parent==null) //如果未找到
{
System.out.printf("未找到该父结点!\n");
pnode=null; //释放创建的结点内存
return;
}
System.out.printf("1.添加该结点到左子树\n2.添加该结点到右子树\n");
do
{
menusel=input.nextInt(); //输入选择项
if(menusel==1 || menusel==2)
{
if(parent==null)
{
System.out.printf("不存在父结点,请先设置父结点!\n");
}
else
{
switch(menusel)
{
case 1: //添加到左结点
if(parent.left!=null) //左子树不为空
{
System.out.printf("左子树结点不为空!\n");
}
else
{
parent.left=pnode;
}
break;
case 2: //添加到右结点
if( parent.right!=null) //右子树不为空
{
System.out.printf("右子树结点不为空!\n");
}
else
{
parent.right=pnode;
}
break;
default:
System.out.printf("无效参数!\n");
}
}
}
}while(menusel!=1 && menusel!=2);
}
}
4、查找结点
CBTType TreeFindNode(CBTType treeNode,String data) //查找结点
{
CBTType ptr;
if(treeNode==NULL)
{
return NULL;
}
else
{
if(treeNode.data.equals(data))
{
return treeNode;
}
else //查找左右子树
{
if((ptr=TreeFindNode(treeNode.left,data))!=NULL)
{
return ptr;
}
else if((ptr=TreeFindNode(treeNode.left,data))!=NULL)
{
return ptr;
}
else
{
return null;
}
}
}
}
5、获取左/右子树
CBTType TreeLeftNode(CBTType treeNode) //获取左子树
{
if(treeNode!=null)
{
return treeNode.left; //返回值
}
else
{
return null;
}
}
CBTType TreeRightNode(CBTType treeNode) //获取右子树
{
if(treeNode!=null)
{
return treeNode.right; //返回值
}
else
{
return null;
}
}
6、判断树是否为空 计算二叉树深度
int TreeIsEmpty(CBTType treeNode) //判断空树
{
if(treeNode!=null)
{
return 0;
}
else
{
return 1;
}
}
int TreeDepth(CBTType treeNode) //计算二叉树深度
{
int depleft,depright;
if(treeNode==null)
{
return 0; //对于空树,深度为0
}
else
{
depleft = TreeDepth(treeNode.left); //左子树深度 (递归调用)
depright = TreeDepth(treeNode.right); //右子树深度 (递归调用)
if(depleft>depright)
{
return depleft + 1;
}
else
{
return depright + 1;
}
}
}
7、清空二叉树 显示结点数据
void ClearTree(CBTType treeNode) // 清空二叉树
{
if(treeNode!=null)
{
ClearTree(treeNode.left); //清空左子树
ClearTree(treeNode.right); //清空右子树
treeNode=null; //释放当前结点所占内存
// treeNode=null;
}
}
void TreeNodeData(CBTType p) //显示结点数据
{
System.out.printf("%s ",p.data); //输出结点数据
}
8、二叉树遍历算法
(1)按层遍历算法
void LevelTree(CBTType treeNode) //按层遍历
{
CBTType p;
CBTType[] q=new CBTType[MAXLEN]; //定义一个顺序栈
int head=0,tail=0;
if(treeNode!=null) //如果队首指针不为空
{
tail=(tail+1)%MAXLEN; //计算循环队列队尾序号
q[tail] = treeNode; //将二叉树根指针进队
}
while(head!=tail) //队列不为空,进行循环
{
head=(head+1)%MAXLEN; //计算循环队列的队首序号
p=q[head]; //获取队首元素
TreeNodeData(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; //将右子树指针进队
}
}
}
(2)先序遍历
void DLRTree(CBTType treeNode) //先序遍历
{
if(treeNode!=null)
{
TreeNodeData(treeNode); //显示结点的数据
DLRTree(treeNode.left);
DLRTree(treeNode.right);
}
}
(3)中序遍历
void LDRTree(CBTType treeNode) //中序遍历
{
if(treeNode!=null)
{
LDRTree(treeNode.left); //中序遍历左子树
TreeNodeData(treeNode); //显示结点数据
LDRTree(treeNode.right); //中序遍历右子树
}
}
(4)后序遍历
void LRDTree(CBTType treeNode) //后序遍历
{
if(treeNode!=null)
{
LRDTree(treeNode.left); //后序遍历左子树
LRDTree(treeNode.right); //后序遍历右子树
TreeNodeData(treeNode); //显示结点数据
}
}
到此为止,树的基本数据结构就到此结束了!