C语言版数据结构(从0开始) 8. 树和二叉树的遍历

1.树的遍历

遍历: 按一定规律走遍树的各个顶点,且使每一顶点仅被访问一次,即找一个完整而有规律的走法,以得到树中所有结点的一个线性排列

常用方法
先根(序)遍历:先访问树的根结点,然后依次先根遍历根的每棵子树

后根(序)遍历:先依次后根遍历每棵子树,然后访问根结点

按层次遍历:先访问第一层上的结点,然后依次遍历第二层,……第n层的结点
qq-735429101

2.二叉树的遍历

方法
先序遍历:先访问根结点,然后分别先序遍历左子树、右子树
中序遍历:先中序遍历左子树,然后访问根结点,最后中序遍历右子树
后序遍历:先后序遍历左、右子树,然后访问根结点
按层次遍历:从上到下、从左到右访问各结点

2.1 递归算法

qq-735429101
先序遍历算法:

void preorder(JD *bt)
{  if(bt!=NULL)
   {  printf("%d\t",bt->data);
      preorder(bt->lchild);
      preorder(bt->rchild);
   }
}

qq-735429101
中序遍历算法:

void inorder(JD *bt)
{  if(bt!=NULL)
   {  inorder(bt->lchild);
      printf("%d\t",bt->data);
      inorder(bt->rchild);
   }
}

qq-735429101
后序遍历算法:

void postorder(JD *bt)
{  if(bt!=NULL)
   {  postorder(bt->lchild);
      postorder(bt->rchild);
      printf("%d\t",bt->data);
   }
}

qq-735429101

2.2 非递归算法
void inorder(JD *bt)
{   int i=0;
    JD *p,*s[M];
    p=bt;
    do
    {  while(p!=NULL)
       {   s[i++]=p;
           p=p->lchild;
       }
       if(i>0)
       {   p=s[--i];
           printf("%d\t",p->data);
           p=p->rchild;
       }
    }while(i>0||p!=NULL);
}

qq-735429101
qq-735429101
qq-735429101
qq-735429101

3. 遍历算法的应用
  • 按先序遍历序列建立二叉树的二叉链表
JD *crt_bt_pre(JD *bt)
{  char ch;
   printf("ch=");
   scanf("%c",&ch);
   if(ch==' ')  bt=NULL;
   else
   {   bt=(JD *)malloc(sizeof(JD));
       bt->data=ch;
       bt->lchild=crt_bt_pre(bt->lchild);
       bt->rchild=crt_bt_pre(bt->rchild);
   }
   return(bt);
}
  • 统计二叉树中叶子结点个数算法
#include <alloc.h>
#include <stdio.h>

typedef struct node
{   char data;
    struct node *lchild,*rchild;
}JD;

void countleaf(JD *bt,int *count)
{   if(bt!=NULL)
    {  if((bt->lchild==NULL)&&(bt->rchild==NULL))
       {   (*count)++;
	   return;
       }
       countleaf(bt->lchild,count);
       countleaf(bt->rchild,count);
    }
}

JD *crt_bt_pre(JD *bt)
{  char ch;
   printf("ch=");
   scanf("%c",&ch);
   if(ch==' ')  bt=NULL;
   else
   {   bt=(JD *)malloc(sizeof(JD));
       bt->data=ch;
       bt->lchild=crt_bt_pre(bt->lchild);
       bt->rchild=crt_bt_pre(bt->rchild);
   }
   return(bt);
}

void main()
{  /* ABC00DE0G00F000  */
    JD *head=NULL;
    int count=0;
   head=crt_bt_pre(head);
   countleaf(head,&count);
   printf("count of leaf node is %d\n",count);
}

  • 求二叉树的深度算法
#include <alloc.h>
#include <stdio.h>

typedef struct node
{   char data;
    struct node *lchild,*rchild;
}JD;

JD *crt_bt_pre(JD *bt)
{  char ch;
   printf("ch=");
   scanf("%c",&ch);
   getchar();
   if(ch==' ')  bt=NULL;
   else
   {   bt=(JD *)malloc(sizeof(JD));
       bt->data=ch;
       bt->lchild=crt_bt_pre(bt->lchild);
       bt->rchild=crt_bt_pre(bt->rchild);
   }
   return(bt);
}
void treedepth(JD *bt,int *l,int *h)
{
    int l1=0,l2=0,h1=0,h2=0;
    if(bt!=NULL)
    {  (*l)++;
       if (*l>*h) *h=*l;
       treedepth(bt->lchild,&l1,&h1);
       treedepth(bt->rchild,&l2,&h2);
       if (h1>h2)  *h=*h+h1;
       else	*h=*h+h2;

    }
}
void main()
{  /* ABC00DE0G00F000  */
    JD *head=NULL;
    int level=0,high=0;
   head=crt_bt_pre(head);
   treedepth(head,&level,&high);
   printf("depth of tree is %d\n",high);
}
4.线索二叉树
4.1 线索二叉树定义

定义:
前驱与后继:在二叉树的先序、中序或后序遍历序列中两个相邻的结点互称为~
线索:指向前驱或后继结点的指针称为~
线索二叉树:加上线索的二叉链表表示的二叉树叫~
线索化:对二叉树按某种遍历次序使其变为线索二叉树的过程叫~

实现
在有n个结点的二叉链表中必定有n+1个空链域
在线索二叉树的结点中增加两个标志域
lt :若 lt =0, lc 域指向左孩子;若 lt=1, lc域指向其前驱
rt :若 rt =0, rc 域指向右孩子;若 rt=1, rc域指向其后继

结点定义

typedef  struct node
{   int  data;
     int lt, rt;
     struct node *lc, *rc;
}JD;
4.2 算法

按中序线索化二叉树

JD *zxxsh(JD *bt)
{  JD *p,*pr,*s[M],*t;
   int i=0;
   t=(JD *)malloc(sizeof(JD));
   t->lt=0;
   t->rt=1;
   t->rc=t;
   if(bt==NULL)
      t->lc=t;
   else
   {  t->lc=bt;
      pr=t;
      p=bt;
      do
      {   while(p!=NULL)
	  {   s[i++]=p;
	      p=p->lc;
	  }
	  if(i>0)
	  {   p=s[--i];
	      printf("%c  ",p->data);
	      if(p->lc==NULL)
	      {   p->lt=1;
		  p->lc=pr;
	      }
	      if(pr->rc==NULL)
	      {   pr->rt=1;
		  pr->rc=p;
	      }
	      pr=p;
	      p=p->rc;
	  }
      }while(i>0||p!=NULL);
      pr->rc=t;
      pr->rt=1;
      t->rc=pr;
   }
   return(t);
}

遍历中序线索二叉树

void zxblxss(JD *t)
{   JD *p;
    p=t->lc;
    do
    {   while(p->lt==0)
	   p=p->lc;
	printf("%c  ",p->data);
	while((p->rt==1)&&(p->rc!=t))
	{   p=p->rc;
	   printf("%c  ",p->data);
	}
	p=p->rc;
    }while(p!=t);
}

在中序线索二叉树中找结点后继的方法:
(1)若rt=1, 则rc域直接指向其后继
(2)若rt=0, 则结点的后继应是其右子树的左链尾(lt=1)的结点

在中序线索二叉树中找结点前驱的方法:
(1)若lt=1, 则lc域直接指向其前驱
(2)若lt=0, 则结点的前驱应是其左子树的右链尾(rt=1)的结点

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值