一、相关概念
0、树的结点包含一个数据元素及若干指向其子树的分支;
1.、树的结点:包含一个数据元素和指向其子树的所有分支;
2.、结点的度:一个结点拥有的子树个数,度为零的结点称为叶结点;
3.、树的度:树中所有结点的度的最大值 Max(D(I));
含义:树中最大分支数为树的度;
4.、结点的层次及树的深度:根为第一层,根的孩子为第二层,若某结点为第k层,则其孩子为k+1层;
树中结点的最大层次称为树的深度或高度;
5、森林:是m(m>=0)棵互不相交的树的集合;
森林与树概念相近,相互很容易转换;
6 、有序树、无序树 如果树中每棵子树从左向右的排列拥有一定的顺序,不得互换,则称为有序树,否则称为无序树。
7、二叉树(BinaryTree)是n(n≥0)个结点的有限集。它或者是空集(n=0),或者同时满足以下两个条件:
(1) 有且仅有一个根结点;
(2) 其余的结点分成两棵互不相交的左子树和右子树。
二叉树与树有区别:树至少应有一个结点,而二叉树可以为空;树的子树没有顺序,但如果二叉树的根结点只有一棵子树,必须明确区分它是左子树还是右子树,因为两者将构成不同形态的二叉树。因此,二叉树不是树的特例。它们是两种不同的数据结构。
8、两种特殊形态的二叉树
(1) 满二叉树(FullBinaryTree)
深度为k,且有2k-1个结点的二叉树。
特点:(1)每一层上结点数都达到最大;
(2)度为1的结点n1=0,树叶都在最下一层上。
(2) 完全二叉树(Complete BinaryTree)
深度为k,结点数为n的二叉树,当且仅当每个结点的编号都与相同深度的满二叉树中从1到n的结点一一对应时,称为完全二叉树。
完全二叉树的特点:
(1)每个结点i的左子树的深度Lhi-其结点i的右子树的深度Rhi等于0或1,即叶结点只可能出现在层次最大或次最大的两层上。
(2)完全二叉树结点数n满足2k-1-1<n≤2k-1
(3)满二叉树一定是完全二叉树,反之不成立。
9、二叉树的性质
性质1 在二叉树的第i层上至多有2i-1 个结点(i≥1)。
性质2 深度为k的二叉树至多有2k-1个结点(k≥1)。
(深度一定,二叉树的最大结点数也确定)
性质3 二叉树中,终端结点数n0与度为2的结点数n2有如下关系:
n0=n2+1
性质4 结点数为n的完全二叉树,其深度为以2为底的Log(n)加1。
存储结构如下:
typedef struct node
{ ElemType data;
struct node *lchild;
struct node *rchild;
} BTree,*tree;
其中,tree是指向根结点的指针。
性质5 具有n个结点的二叉链表中,共有2n个指针域。其中只有n-1个用来指示结点的左、右孩子,其余的n+1个指针域为空。
二、遍历算法
分中序(前缀表示,也称波兰式),中序(中缀表示),后序(后缀表示,也称逆波兰式)三咱遍历方法。
先序:
preorder(BTree *root) //前序遍历
{ if(root!= NULL) //如果不是空结点
{ printf(“%c\n”,root->data); //输出当前结点值
preorder(root->lchild); //递归前序遍历左子结点
preorder(root->rchild); //递归前序遍历右子结点
}
return; //结束
}
中序:
void inorder(BTree *root) //中序遍历
{ if(root!=NULL) //如果不是空结点
{ inorder(root->lchild); //递归中序遍历左子结点
printf(“%c\n”,root->data); //输出当前结点值
inorder(root->rchild); //递归中序遍历右子结点
}
}
后序:
void postorder(BTree *root) //后序遍历
{ if(root!=NULL) //如果不是空结点
{ postorder(root->lchild); //递归后序遍历左子结点
postorder(root->rchild); //递归后序遍历右子结点
printf(“%c\n”,root->data); //输出当前结点值
}
}
Status inorder(BiTree root)
{//中序遍历非递归算法
SqStack S;
InitStack(S);
Push(S,root);
BiTree p;
while(!StackEmpty(S))
{
while(GetTop(S,p)&&p) Push(S,p->lchild);
Pop(S,p); //空指针退栈
if(!StackEmpty(S))
{
Pop(S,p);
printf("%c\n",p->data);
Push(S,p->rchild);
}//if
}//while
return ok;
}
三、算法实现(举个例子)
#include "stdio.h"
#include "stdlib.h"
typedef char ElemType3;
typedef int Status;
#define ok 1
#define error 0
int count=0;
typedef struct BiTNode //定义链表结构
{
ElemType3 data; //定义结点值
struct BiTNode *lchild; //定义左子结点指针
struct BiTNode *rchild; //定义右子结点指针
}BiTNode,*BiTree;
Status preorder(BiTree root)
{
if(root!=NULL)
{
printf("%c\n",root->data);
preorder(root->lchild);
preorder(root->rchild);
}//
return ok;
}
Status inorder(BiTree root)
{
if(root!=NULL)
{
inorder(root->lchild);
printf("%c\n",root->data);
inorder(root->rchild);
}//
return ok;
}
Status CreateBitree(BiTree &T)
{//按先序次序输入二叉树
char ch,enter;
scanf("%c%c",&ch,&enter);
if(ch==' ') T=NULL;
else{
if(!(T=(BiTNode*)malloc(sizeof(BiTNode)))) exit(1);
T->data=ch;
CreateBitree(T->lchild);
CreateBitree(T->rchild);
}//else
return ok;
}//CreateBitree
int main()
{
BiTree T;
CreateBitree(T);
preorder(T);
inorder(T);
return 1;
}