函数:
typedef struct node *link;
struct node
{
Item item;
link l;
link r;
}
定义:任意两个节点只有一条唯一的路径。
如果在几对节点中不止一条的路径,或者在几对节点中没有路径,则为图。
二叉数性质:
- 根节点在第0层。
- 一棵有N个内部节点的二叉树有N+1个外部节点。
- 一棵有N个内部节点的二叉树有2N个链接:N-1个链接到内部的节点,N+1个链接到外部的节点。
- 数的高度就是树种节点层数中的最大值。
- 数的路径长度是所有数节点的层数的总和。
- 一棵二叉树的内部路径长度是树的所有内部节点层数的总和。
- 一棵二叉树的外部路径长度是树的所有外部节点层数的总和。
- 任何带有N个内部节点的二叉树的外部路径长度比内部路径长度大2N。
- 带有N个内部节点的二叉树的高度至少是lgN,至多是N-1.
数的遍历:
给出一个指向树的指针,系统的访问树中的每个节点。
递归前序遍历:
void traverse(link h,void (*visit)(link))
{
if(h =NULL)//递归结束条件
return;
(*visit)(h);//访问节点函数位于递归之前,前序遍历。位于递归中间,中序遍历。位于递归之后,后续遍历。
traverse(h->l,visit);
traverse(h->r,visit);
}
非递归前序遍历
进入一个循环,在这个循环中弹出并处理在栈顶的元素,如此继续,直到栈为空。如果弹出的元素是一个数据项,则访问它。如果弹出的元素是一棵树,则按照希望的顺序执行一系列的入栈操作:
对于前序:压入右子树,然后左子树,最后是节点。
对于中序:压入右子树,然后节点,最后是左子树。
对于后序:压入节点,然后右子树,最后左子树。
void traverse(link h,void (*visit)(link))
{
STACKinit(max);
STACKpush(h);
while(!STACKempty())
{
(*visit)(h = STACKpop());
if(h->r != NULL)
STACKpush(h->r);
if(h->l != NULL)
STACKpush(h->l);
}
}
层序遍历
从上到下,从左到右访问树中的节点。
使用队列FIFO先进先出数据结构。
void traverse(link h,void (*visit)(link))
{
QUEUEinit(max);//队列FIFO实现层序遍历
QUEUEput(h);
while(!QUEUEempty())
{
(*visit)(h = QUEUEget());//当访问节点时,将节点左右子节点加入队列。
if(h->l != NULL)
QUEUEput(h->l);
if(h->r != NULL)
QUEUEput(h->r);
}
}
递归二叉树算法
通过处理根节点和(递归的处理)它的子树来处理整棵树。
int count(link h)
{
if(h == NULL)
return 0;//空节点,计数为0
return count(h->l) + count(h->r) +1;//若可以进入子树,则说明有父节点,则需要加1.
}
int height(link h)
{
int u,v;
if(h == NULL)
return -1;//尽头
u = height(h->l);
v = height(h->r);
if(u > v) return u+1;//若能对节点进行左右递归,说明有父节点存在,则加1层。
else return v+1;//若能对节点进行左右递归,说明有父节点存在,则加1层。
}