函数:
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层。 }