递归与树(二)

函数:

typedef struct node *link;

struct node

{

    Item item;

    link l;

    link r;

}

定义:任意两个节点只有一条唯一的路径。

如果在几对节点中不止一条的路径,或者在几对节点中没有路径,则为图。


二叉数性质:

  1. 根节点在第0层。
  2. 一棵有N个内部节点的二叉树有N+1个外部节点。
  3. 一棵有N个内部节点的二叉树有2N个链接:N-1个链接到内部的节点,N+1个链接到外部的节点。
  4. 数的高度就是树种节点层数中的最大值。
  5. 数的路径长度是所有数节点的层数的总和。
  6. 一棵二叉树的内部路径长度是树的所有内部节点层数的总和。
  7. 一棵二叉树的外部路径长度是树的所有外部节点层数的总和。
  8. 任何带有N个内部节点的二叉树的外部路径长度比内部路径长度大2N。
  9. 带有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层。

}

猜你喜欢

转载自blog.csdn.net/u010034085/article/details/80586632