1、节点拥有的子树数称为节点的度(degree)。度为0的节点称为叶节点(leaf)或终端节点;
度不为0的节点称为非终端节点或分支节点。除根节点之外,分支节点也称为内部节点。树的度是
树内各节点的度的最大值。
2、节点间关系:节点的子树的根称为该节点的孩子(child),该节点称为孩子的双亲(parent)。
同一个双亲的孩子间互称兄弟(Sibling)。节点的祖先是从根到该节点所经分支上的所有节点。
以某节点为根的字数中任意节点都称为该节点的子孙。。。。。。
3、节点的层次:从根开始定义,根为第一层,根的孩子为第二层,根的孩子的孩子在第三层,
以此类推……树中节点的最大层次称为树的深度或高度。如果将树中节点的各子树看成从左至右是
有次序的不能交换的,则称该树是有序树,否则称为无序树。森林是m(m>=0)棵不想交的
树的集合;对树中每个节点而言,其子树的集合即为森林。
/*********双亲表示法**********/
/*树的双亲表示法节点结构定义*/
const MaxTreeSize 100
typedef int telmtp; //树节点的数据类型
typedef struct PTNode//节点结构
{
telmtp data; //节点数据
int parent; //双亲位置(指针)
}PTNode;
typedef struct //树结构
{
PTNode nodes[MaxTreeSize];//节点数组
int r,n; //根的位置和节点数
}PTree;
/*********孩子表示法**********/
//也称为多重链表表示法
/*树的孩子表示法结构定义*/
const MaxTreeSize 100
typedef struct CTNode//孩子节点
{
int child;
struct CTNode *next;
}*ChildPtr;
typedef struct //表头结构
{
telmtp data;
ChildPtr firstchild;
}CTBox;
typedef struct //树结构
{
CTBox nodes[MaxTreeSize];//节点数组
int r,n; //根的位置和节点数
}CTree;
/*******孩子兄弟表示法*******/
//设置两个指针,分别指向该节点的第一个孩子和此节点的右兄弟
typedef struct CSNode
{
telmtp data;
struct CSNode *firstchild,*rightsib;
}CSNode,*CSTree;
4、二叉树
· 每个节点最多有两棵子树,所以二叉树中不存在度大于2的节点
· 左子树和右子树是有顺序的,次序不能任意颠倒。
· 即使树中某节点只有一颗子树,也要区分是左子树还是右子树。
· 斜树:所有节点都只有左子树的称为左斜树,所有节点都只有右子树的称为右斜树,统称斜树
· 满二叉树:所有节点都有两颗子树,除叶节点。
· 完全二叉树:节点序号连续(从左到右,到最后一层次最后一节点,只有左叶节点或者有两叶节点,不可能只有右节点)。
二叉树的性质:
①二叉树在第 i 层上至多有2^(i-1)个节点。
②深度为 k 的二叉树最多有2^k-1个节点。
③对于任何一棵二叉树,端节点总数为n0,度为2的节点数为n2,则n0=n2+1
④具有n个节点的完全二叉树深度为[log(2)n+1].
⑤如果对一刻有n个节点的完全二叉树(其深度为[log(2)n+1])的节点按层序编号
(从第一层到第[log(2)n]+1层,每层从左到右),对任一节点i(1<=i<=n)有:
· 如果i=1,则节点i是二叉树的根;如果i>1,其双亲为节点[i/2]。
· 如果2i>n,则节点i无左孩子(节点i为叶子节点);否则其左孩子是节点2i。
· 如果2i+1>n,则节点i无右孩子;否则其右孩子是节点2i+1。
/*******二叉树的存储结构*******/
/*顺序存储结构*/
//该结构一般用于完全二叉树,不然有些极端的二叉树会造成空间浪费
。。。。。。。。。。。。。
这个。。就是把二叉树各节点用数组表示出来。。。
/*二叉链表*/
//二叉树的二叉链表节点结构定义
typedef struct BiTNode//节点结构
{
telmtp data; //节点数据
struct BiTNode *lchild,*rchild;//左右孩子指针
}BiTNode,*BiTree;
指的是从根节点出发,按照某种次序依次访问二叉树中所有节点,使得每个节点被访问一次
且仅被访问一次。
①前序遍历:规则是若二叉树为空,则空操作返回,否则先访问根节点,然后前序遍历左子树,再前序遍历右子树。
//前序遍历第归算法
void preOrderTraverse(BiTree T)
{
if(T==NULL)
return;
printf("%c",T->data);//显示节点数据,可以更改为其它对节点操作、
preOrderTraverse(T->lchild);//再先序遍历左子树
preOrderTraverse(T->rchild);//最后先序遍历右子树
}②中序遍历:规则是若树为空,则空操作返回,否则从根节点开始,中序遍历根节点左子树,然后是访问根节点,最后中序遍历右子树。//中序遍历第归算法
void InOrderTraverse(BiTree T)
{
if(T==NULL)
return;
InOrderTraverse(T->lchild);//中序遍历左子树
printf("%c",T->data); //显示节点数据,可以更改为其它对节点的操作
InOrderTraverse(T->rchild;)//最后中序遍历右子树
}③后序遍历:若树为空,则空操作返回,否则从左到右先叶子后节点方式遍历访问左右子树,最后访问根节点。//后序遍历算法
void PostOrderTraverse(BiTree T)
{
if(T==NULL)
return;
PostOrderTraverse(T->lchild);//先后序遍历左子树
PostOrderTraverse(T->rchild);//再后序遍历右子树
printf("%c",T->data); //显示节点数据,可以更改为其它对节点的操作
}④层序遍历:若树为空,则空操作返回,否则从树的第一层,从上而下逐层遍历,同一层中,按从左到右顺序对节点逐个访问。
6、二叉树的建立
void CreteBiTree(BiTree *T)
{
telmtp ch;
scanf("%c",&ch);
if(ch=='#')
*T=NULL;
else
{
*T=(BiTree)malloc(sizeof(BiTNode));
if(!*T)
exit(OVERFLOW);
(*T)->data=ch;//生成根节点
CreateBiTree(&(*T->lchild));//构造左子树
CreateBiTree(&(*T->rchild));//构造右子树
}
}7、线索二叉树把指向前驱和后继的指针称为线索,加上线索的二叉链表称为线索链表,相应的二叉树就称为线索二叉树。线索二叉树不仅节省了空间还可以减少遍历数,降低时间复杂度。
/*二叉树的二叉线索存储结构定义*/
//Link==0表示指向左右孩子指针
//Thread==1表示指向前驱或者后继的线索
//二叉线索存储节点结构
typedef enum{Link,Thread} PointerTag;
typedef struct BiThrNode //二叉线索存储节点结构
{
telmtp data; //节点数据
struct BiThrNode *lchild,*rchild;//左右孩子指针
PointerTag LTag;
PointerTag TTag; //左右标志
}BiThrNode,*BiThrTree;
/*例子:中序遍历线索化递归函数*/
BiThrTree pre; //全局变量,始终指向刚刚访问过的节点
//中序遍历进行中序线索化
void InThreading(BiThrTree p)
{
if(p)
{
InThreeding(p->lchild);//第归左子树线索化
if(!p->lchild) //没有左孩子
{
p->LTag=Thread; //线索前驱
p->lchild=pre; //左孩子指针指向前驱
}
if(!pre->rchild) //前驱没有右孩子
{
pre->RTag=Thread; //后继线索
pre->rchild=p; //前驱右孩子指针指向后继(当前节点p)
}
pre=p;
InThreading(p->rchild);//递归右子树线索化
}
}8、树转化为二叉树①、所有兄弟节点之间加一条线
②、只保留连接的横线和长子的线
③、树自然下垂
森林转化为二叉树
①每棵树转化为二叉树
②第一棵树不动,从第二棵树开始,依次把后一根二叉树作为第一棵二叉树的右孩子,
用线连接起来,所有二叉树连接起来得到由森林转化的二叉树。
二叉树转换为树
①加线,左孩子的n个右孩子节点都作为此节点的孩子。将该节点与这些右孩子节点用线连接起来。
②去线:删除原二叉树中所有节点与其右孩子节点的连线。
③层次调整。。。自然下垂。。
二叉树转化为森林
①去线:从根节点寻找右孩子去线
②连线:把去线后的几个二叉树的右孩子连到新分出来的根节点还原。
9、赫夫曼树及其应用
……再见。

被折叠的 条评论
为什么被折叠?



