• 浅谈数据结构之二叉树存储结构实现(七)


      树:是n个结点的有限集;n=0时称为空树。在任意一棵非空树中,有且只有一个特定的结点称为根结点;其余的结点可分为m(m>0)个互不相交的有限集,其中每一个有限集都是一棵子树。结点拥有的子树数称为结点的度;度为0的结点称为叶结点或者终端结点,度不为0的结点称为分支结点或者非终端结点;树的度就是树内各结点的度的最大值。

      二叉树的特点有:(1).每个结点最多有两棵子树,所以二叉树不存在度大于2的结点(注意:不是只有两棵子树,而是最多有两棵子树,没有子树或者有一颗子树都是可以的);(2).左子树和右子树都是有顺序的,次序不能任意颠倒;(3).即使只有一棵子树,也要区分清它是左子树还是右子树。

      对于树这种一对多的结构来说,简单的顺序存储和链式存储结构都不能满足树的存储结构的实现;不过可以利用顺序存储与链式存储的特点来实现树的存储结构的表示。但对于二叉树这种特殊的树来说,它的顺序存储结构完全可以实现;用一维数组存储二叉树中的结点,并且结点的存储位置,也就是数组的下标要能体现结点之间的逻辑关系,比如双亲和孩子的关系,左右兄弟的关系。二叉树的链式存储结构,我们一般称为二叉链表,即为它设计一个数据域和两个指针域,其中两个指针域分别存放指向左孩子和右孩子的指针。

      二叉树的遍历是指从根结点出发,按照某种次序依次访问二叉树中所有结点,使得每个结点被访问一次且仅被访问一次。二叉树的遍历方式主要有四种:(1).前序遍历,规则是若二叉树为空,则空操作返回,否则先访问根结点,然后前序遍历左子树,再前序遍历右子树;(2).中序遍历,规则是若二叉树为空,则空操作返回,否则从根结点开始(注意并不是先访问根结点),中序遍历根结点的左子树,然后访问根结点,最后中序遍历右子树;(3).后序遍历,若二叉树为空,则空操作返回,否则从左到右先叶子后结点的方式遍历左右子树,最后访问根结点;(4).层序遍历,规则是若二叉树为空,则空操作返回,否则从树的第一层,也就是从根结点开始访问,从上而下逐层遍历,在同一层中,按从左到右的顺序依次访问。

    二叉树顺序存储结构的实现,遍历方式源程序代码如下所示:

      1 #include <stdio.h>   
      2 #include <stdlib.h>  
      3 #include <math.h> 
      4 
      5 #define OK 1
      6 #define ERROR 0
      7 #define TRUE 1
      8 #define FALSE 0
      9 
     10 #define MAXSIZE 100             /* 存储空间初始分配量 */
     11 #define MAX_TREE_SIZE 100       /* 二叉树的最大结点数 */
     12 #define ClearBiTree InitBiTree  /* 在顺序存储结构中,两函数完全一样 */
     13 
     14 typedef int Status;             /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
     15 typedef int TElemType;          /* 树结点的数据类型,目前暂定为整型 */
     16 typedef TElemType SqBiTree[MAX_TREE_SIZE];       /* 0号单元存储根结点  */
     17 
     18 typedef struct
     19 {
     20     int level,order;            /* 结点的层,本层序号(按满二叉树计算) */
     21 }Position;
     22 
     23 TElemType Nil=0;                /* 设整型以0为空 */
     24 
     25 Status visit(TElemType c)
     26 {
     27     printf("%d ",c);
     28     return OK;
     29 }
     30 
     31 /* 构造空二叉树T。因为T是固定数组,不会改变,故不需要& */
     32 Status InitBiTree(SqBiTree T)
     33 {
     34     int i;
     35     for(i=0;i<MAX_TREE_SIZE;i++)
     36         T[i]=Nil;                 /* 初值为空 */
     37     return OK;
     38 }
     39 
     40 /* 按层序次序输入二叉树中结点的值(字符型或整型), 构造顺序存储的二叉树T */
     41 Status CreateBiTree(SqBiTree T)
     42 { 
     43     int i=0;
     44      printf("请按层序输入结点的值(整型),0表示空结点,输99结束。结点数≤%d:
    ",MAX_TREE_SIZE);
     45     while(i<10)
     46     {
     47         T[i]=i+1;
     48         
     49         if(i!=0&&T[(i+1)/2-1]==Nil&&T[i]!=Nil)         /* 此结点(不空)无双亲且不是根 */
     50         {
     51             printf("出现无双亲的非根结点%d
    ",T[i]);
     52             exit(ERROR);
     53         }
     54         i++;
     55     }
     56     while(i<MAX_TREE_SIZE)
     57     {
     58         T[i]=Nil;                 /* 将空赋值给T的后面的结点 */
     59         i++;
     60     }
     61 
     62     return OK;
     63 }
     64 
     65 /* 初始条件: 二叉树T存在 */
     66 /* 操作结果: 若T为空二叉树,则返回TRUE,否则FALSE */
     67 Status BiTreeEmpty(SqBiTree T)
     68 { 
     69     if(T[0]==Nil)               /* 根结点为空,则树空 */
     70         return TRUE;
     71     else
     72         return FALSE;
     73 }
     74 
     75 /* 初始条件: 二叉树T存在。操作结果: 返回T的深度 */
     76 int BiTreeDepth(SqBiTree T)
     77 { 
     78     int i,j=-1;
     79     for(i=MAX_TREE_SIZE-1;i>=0;i--)         /* 找到最后一个结点 */
     80     if(T[i]!=Nil)
     81            break;
     82     i++; 
     83     do
     84          j++;
     85     while(i>=powl(2,j));                    /* 计算2的j次幂。 */
     86     return j;
     87 }
     88 
     89 /* 初始条件: 二叉树T存在,e是T中某个结点(的位置) */
     90 /* 操作结果: 返回处于位置e(层,本层序号)的结点的值 */
     91 TElemType Value(SqBiTree T,Position e)
     92 { 
     93      return T[(int)powl(2,e.level-1)+e.order-2];
     94 }
     95 
     96 /* 初始条件: 二叉树T存在,e是T中某个结点(的位置) */
     97 /* 操作结果: 给处于位置e(层,本层序号)的结点赋新值value */
     98 Status Assign(SqBiTree T,Position e,TElemType value)
     99 { 
    100     int i=(int)powl(2,e.level-1)+e.order-2;     /* 将层、本层序号转为矩阵的序号 */
    101     if(value!=Nil&&T[(i+1)/2-1]==Nil)           /* 给叶子赋非空值但双亲为空 */
    102         return ERROR;
    103     else if(value==Nil&&(T[i*2+1]!=Nil||T[i*2+2]!=Nil))     /*  给双亲赋空值但有叶子(不空) */
    104         return ERROR;
    105     T[i]=value;
    106     return OK;
    107 }
    108 
    109 /* 初始条件: 二叉树T存在,e是T中某个结点 */
    110 /* 操作结果: 若e是T的非根结点,则返回它的双亲,否则返回"空" */
    111 TElemType Parent(SqBiTree T,TElemType e)
    112 { 
    113     int i;
    114     if(T[0]==Nil)       /* 空树 */
    115         return Nil;
    116     for(i=1;i<=MAX_TREE_SIZE-1;i++)
    117         if(T[i]==e)     /* 找到e */
    118             return T[(i+1)/2-1];
    119     return Nil;         /* 没找到e */
    120 }
    121 
    122 
    123 /* 初始条件: 二叉树T存在,e是T中某个结点 */
    124 /* 操作结果: 返回e的左孩子。若e无左孩子,则返回"空" */
    125 TElemType LeftChild(SqBiTree T,TElemType e)
    126 { 
    127     int i;
    128     if(T[0]==Nil)       /* 空树 */
    129         return Nil;
    130     for(i=0;i<=MAX_TREE_SIZE-1;i++)
    131         if(T[i]==e)     /* 找到e */
    132             return T[i*2+1];
    133     return Nil;         /* 没找到e */
    134 }
    135 
    136 /* 初始条件: 二叉树T存在,e是T中某个结点 */
    137 /* 操作结果: 返回e的右孩子。若e无右孩子,则返回"空" */
    138 TElemType RightChild(SqBiTree T,TElemType e)
    139 { 
    140     int i;
    141     if(T[0]==Nil)       /* 空树 */
    142         return Nil;
    143     for(i=0;i<=MAX_TREE_SIZE-1;i++)
    144         if(T[i]==e)     /* 找到e */
    145             return T[i*2+2];
    146     return Nil;         /* 没找到e */
    147 }
    148 
    149 /* 初始条件: 二叉树T存在,e是T中某个结点 */
    150 /* 操作结果: 返回e的左兄弟。若e是T的左孩子或无左兄弟,则返回"空" */
    151 TElemType LeftSibling(SqBiTree T,TElemType e)
    152 { 
    153     int i;
    154     if(T[0]==Nil)       /* 空树 */
    155         return Nil;
    156     for(i=1;i<=MAX_TREE_SIZE-1;i++)
    157         if(T[i]==e&&i%2==0) /* 找到e且其序号为偶数(是右孩子) */
    158             return T[i-1];
    159     return Nil;         /* 没找到e */
    160 }
    161 
    162 /* 初始条件: 二叉树T存在,e是T中某个结点 */
    163 /* 操作结果: 返回e的右兄弟。若e是T的右孩子或无右兄弟,则返回"空" */
    164 TElemType RightSibling(SqBiTree T,TElemType e)
    165 { 
    166     int i;
    167     if(T[0]==Nil)           /* 空树 */
    168         return Nil;
    169     for(i=1;i<=MAX_TREE_SIZE-1;i++)
    170         if(T[i]==e&&i%2)    /* 找到e且其序号为奇数(是左孩子) */
    171             return T[i+1];
    172     return Nil;             /* 没找到e */
    173 }
    174 
    175 /* PreOrderTraverse()调用 */
    176 void PreTraverse(SqBiTree T,int e)
    177 { 
    178     visit(T[e]);
    179     if(T[2*e+1]!=Nil)    /* 左子树不空 */
    180         PreTraverse(T,2*e+1);
    181     if(T[2*e+2]!=Nil)    /* 右子树不空 */
    182         PreTraverse(T,2*e+2);
    183 }
    184 
    185 /* 初始条件: 二叉树存在 */
    186 /* 操作结果: 先序遍历T。*/
    187 Status PreOrderTraverse(SqBiTree T)
    188 { 
    189     if(!BiTreeEmpty(T))   /* 树不空 */
    190      PreTraverse(T,0);
    191     printf("
    ");
    192     return OK;
    193 }
    194 
    195 /* InOrderTraverse()调用 */
    196 void InTraverse(SqBiTree T,int e)
    197 { 
    198     if(T[2*e+1]!=Nil)     /* 左子树不空 */
    199         InTraverse(T,2*e+1);
    200     visit(T[e]);
    201     if(T[2*e+2]!=Nil)     /* 右子树不空 */
    202         InTraverse(T,2*e+2);
    203 }
    204 
    205 /* 初始条件: 二叉树存在 */
    206 /* 操作结果: 中序遍历T。*/
    207 Status InOrderTraverse(SqBiTree T)
    208 { 
    209     if(!BiTreeEmpty(T))   /* 树不空 */
    210         InTraverse(T,0);
    211     printf("
    ");
    212     return OK;
    213 }
    214 
    215 /* PostOrderTraverse()调用 */
    216 void PostTraverse(SqBiTree T,int e)
    217 { 
    218     if(T[2*e+1]!=Nil)     /* 左子树不空 */
    219         PostTraverse(T,2*e+1);
    220     if(T[2*e+2]!=Nil)     /* 右子树不空 */
    221         PostTraverse(T,2*e+2);
    222     visit(T[e]);
    223 }
    224 
    225 /* 初始条件: 二叉树T存在 */
    226 /* 操作结果: 后序遍历T。 */
    227 Status PostOrderTraverse(SqBiTree T)
    228 { 
    229     if(!BiTreeEmpty(T))  /* 树不空 */
    230         PostTraverse(T,0);
    231     printf("
    ");
    232     return OK;
    233 }
    234 
    235 /* 层序遍历二叉树 */
    236 void LevelOrderTraverse(SqBiTree T)
    237 { 
    238     int i=MAX_TREE_SIZE-1,j;
    239     while(T[i]==Nil)
    240         i--;             /* 找到最后一个非空结点的序号 */
    241     for(j=0;j<=i;j++)    /* 从根结点起,按层序遍历二叉树 */
    242         if(T[j]!=Nil)
    243             visit(T[j]); /* 只遍历非空的结点 */
    244     printf("
    ");
    245 }
    246 
    247 /* 逐层、按本层序号输出二叉树 */
    248 void Print(SqBiTree T)
    249 { 
    250     int j,k;
    251     Position p;
    252     TElemType e;
    253     for(j=1;j<=BiTreeDepth(T);j++)
    254     {
    255         printf("第%d层: ",j);
    256         for(k=1;k<=powl(2,j-1);k++)
    257         {
    258             p.level=j;
    259             p.order=k;
    260             e=Value(T,p);
    261             if(e!=Nil)
    262                 printf("%d:%d ",k,e);
    263         }
    264         printf("
    ");
    265     }
    266 }
    267 
    268 
    269 int main()
    270 {
    271     Status i;
    272     Position p;
    273     TElemType e;
    274     SqBiTree T;
    275     
    276     InitBiTree(T);
    277     CreateBiTree(T);
    278     printf("1.建立二叉树后,树的深度=%d
    ",BiTreeDepth(T));
    279 
    280     printf("2.层序遍历二叉树: ");
    281     LevelOrderTraverse(T);
    282     
    283     printf("3.前序遍历二叉树: ");
    284     PreOrderTraverse(T);
    285     
    286     printf("4.中序遍历二叉树: ");
    287     InOrderTraverse(T);
    288     
    289     printf("5.后序遍历二叉树: ");
    290     PostOrderTraverse(T);
    291     
    292     printf("6.修改结点的层号2,本层序号1;
    ");
    293     p.level=2;
    294     p.order=1;
    295     e=Value(T,p);
    296     printf("7.待修改结点的原值为%d,请输入新值: %d
    ",e,36);
    297     e=36;
    298     Assign(T,p,e);
    299     
    300     printf("8.前序遍历二叉树: ");
    301     PreOrderTraverse(T);
    302     
    303     printf("9.后序遍历二叉树: ");
    304     PostOrderTraverse(T);
    305     
    306     printf("10.结点%d的双亲为%d;左右孩子分别为",e,Parent(T,e));
    307     printf("%d,%d;左右兄弟分别为",LeftChild(T,e),RightChild(T,e));
    308     printf("%d,%d
    ",LeftSibling(T,e),RightSibling(T,e));
    309     
    310     ClearBiTree(T);
    311     printf("11.清空二叉树后,树的深度=%d
    ",BiTreeDepth(T));
    312     
    313     return 0;
    314 }

     二叉树链式存储结构的实现,遍历方式源程序代码如下所示:

      1 #include <stdio.h>
      2 #include <stdlib.h> 
      3 #include <string.h>
      4 #include <math.h>
      5 
      6 #define OK 1
      7 #define ERROR 0
      8 #define TRUE 1
      9 #define FALSE 0
     10 
     11 #define ClearBiTree DestroyBiTree
     12 
     13 #define MAXSIZE 100          /* 存储空间初始分配量 */
     14 
     15 typedef int Status;          /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
     16 
     17 /* 构造二叉树 */
     18 int index=1;
     19 typedef char String[24];     /*  0号单元存放串的长度 */
     20 String str;
     21 
     22 Status StrAssign(String T,char *chars)
     23 { 
     24     int i;
     25     if(strlen(chars)>MAXSIZE)
     26         return ERROR;
     27     else
     28     {
     29         T[0]=strlen(chars);
     30         for(i=1;i<=T[0];i++)
     31             T[i]=*(chars+i-1);
     32         return OK;
     33     }
     34 }
     35 
     36 typedef char TElemType;
     37 TElemType Nil=' ';            /* 字符型以空格符为空 */
     38 
     39 Status visit(TElemType e)
     40 {
     41     printf("%c ",e);
     42     return OK;
     43 }
     44 
     45 typedef struct BiTNode       /* 结点结构 */
     46 {
     47    TElemType data;            /* 结点数据 */
     48    struct BiTNode *lchild,*rchild;         /* 左右孩子指针 */
     49 }BiTNode,*BiTree;
     50 
     51 
     52 /* 构造空二叉树T */
     53 Status InitBiTree(BiTree *T)
     54 { 
     55     *T=NULL;
     56     return OK;
     57 }
     58 
     59 /* 初始条件: 二叉树T存在。操作结果: 销毁二叉树T */
     60 void DestroyBiTree(BiTree *T)
     61 { 
     62     if(*T) 
     63     {
     64         if((*T)->lchild)     /* 有左孩子 */
     65             DestroyBiTree(&(*T)->lchild);         /* 销毁左孩子子树 */
     66         if((*T)->rchild)     /* 有右孩子 */
     67             DestroyBiTree(&(*T)->rchild);         /* 销毁右孩子子树 */
     68         free(*T);            /* 释放根结点 */
     69         *T=NULL;             /* 空指针赋0 */
     70     }
     71 }
     72 
     73 /* 按前序输入二叉树中结点的值(一个字符) */
     74 /* #表示空树,构造二叉链表表示二叉树T */
     75 void CreateBiTree(BiTree *T)
     76 { 
     77     TElemType ch;
     78     
     79     /* scanf("%c",&ch); */
     80     ch=str[index++];
     81 
     82     if(ch=='#') 
     83         *T=NULL;
     84     else
     85     {
     86         *T=(BiTree)malloc(sizeof(BiTNode));
     87         if(!*T)
     88             exit(OVERFLOW);
     89         (*T)->data=ch;         /* 生成根结点 */
     90         CreateBiTree(&(*T)->lchild);             /* 构造左子树 */
     91         CreateBiTree(&(*T)->rchild);             /* 构造右子树 */
     92     }
     93 }
     94 
     95 /* 初始条件: 二叉树T存在 */
     96 /* 操作结果: 若T为空二叉树,则返回TRUE,否则FALSE */
     97 Status BiTreeEmpty(BiTree T)
     98 { 
     99     if(T)
    100         return FALSE;
    101     else
    102         return TRUE;
    103 }
    104 
    105 /* 初始条件: 二叉树T存在。操作结果: 返回T的深度 */
    106 int BiTreeDepth(BiTree T)
    107 {
    108     int i,j;
    109     if(!T)
    110         return 0;
    111     if(T->lchild)
    112         i=BiTreeDepth(T->lchild);
    113     else
    114         i=0;
    115     if(T->rchild)
    116         j=BiTreeDepth(T->rchild);
    117     else
    118         j=0;
    119     return i>j?i+1:j+1;
    120 }
    121 
    122 /* 初始条件: 二叉树T存在。操作结果: 返回T的根 */
    123 TElemType Root(BiTree T)
    124 { 
    125     if(BiTreeEmpty(T))
    126         return Nil;
    127     else
    128         return T->data;
    129 }
    130 
    131 /* 初始条件: 二叉树T存在,p指向T中某个结点 */
    132 /* 操作结果: 返回p所指结点的值 */
    133 TElemType Value(BiTree p)
    134 {
    135     return p->data;
    136 }
    137 
    138 /* 给p所指结点赋值为value */
    139 void Assign(BiTree p,TElemType value)
    140 {
    141     p->data=value;
    142 }
    143 
    144 /* 初始条件: 二叉树T存在 */
    145 /* 操作结果: 前序递归遍历T */
    146 void PreOrderTraverse(BiTree T)
    147 { 
    148     if(T==NULL)
    149         return;
    150     printf("%c",T->data);            /* 显示结点数据,可以更改为其它对结点操作 */
    151     PreOrderTraverse(T->lchild);     /* 再先序遍历左子树 */
    152     PreOrderTraverse(T->rchild);     /* 最后先序遍历右子树 */
    153 }
    154 
    155 /* 初始条件: 二叉树T存在 */
    156 /* 操作结果: 中序递归遍历T */
    157 void InOrderTraverse(BiTree T)
    158 { 
    159     if(T==NULL)
    160         return;
    161     InOrderTraverse(T->lchild);      /* 中序遍历左子树 */
    162     printf("%c",T->data);            /* 显示结点数据,可以更改为其它对结点操作 */
    163     InOrderTraverse(T->rchild);      /* 最后中序遍历右子树 */
    164 }
    165 
    166 /* 初始条件: 二叉树T存在 */
    167 /* 操作结果: 后序递归遍历T */
    168 void PostOrderTraverse(BiTree T)
    169 {
    170     if(T==NULL)
    171         return;
    172     PostOrderTraverse(T->lchild);    /* 先后序遍历左子树  */
    173     PostOrderTraverse(T->rchild);    /* 再后序遍历右子树  */
    174     printf("%c",T->data);            /* 显示结点数据,可以更改为其它对结点操作 */
    175 }
    176 
    177 int main()
    178 {
    179     int i;
    180     BiTree T;
    181     TElemType e1;
    182     InitBiTree(&T);
    183 
    184     StrAssign(str,"ABDH#K###E##CFI###G#J##");
    185 
    186     CreateBiTree(&T);
    187     printf("1.构造空二叉树后,树的深度=%d
    ",BiTreeDepth(T));
    188     
    189     e1=Root(T);
    190     printf("2.二叉树的根为:%c
    ",e1);
    191 
    192     printf("3.前序遍历二叉树:");
    193     PreOrderTraverse(T);
    194     
    195     printf("
    4.中序遍历二叉树:");
    196     InOrderTraverse(T);
    197     
    198     printf("
    5.后序遍历二叉树:");
    199     PostOrderTraverse(T);
    200     
    201     ClearBiTree(&T);
    202     printf("
    6.清除二叉树后,树的深度=%d
    ",BiTreeDepth(T));
    203     
    204     return 0;
    205 }

        

  • 相关阅读:
    回溯、递归、DFS方法
    3-11日学习记录
    文本清洗总结
    归并排序学习
    3-9日学习笔记
    P3182 [HAOI2016]放棋子 错排问题
    P2880 [USACO07JAN]平衡的阵容Balanced Lineup 线段树 树状数组
    P3469 [POI2008]BLO-Blockade 强连通
    P2756 飞行员配对方案问题 网络流 二分图匹配
    P1823 [COI2007] Patrik 音乐会的等待 单调栈
  • 原文地址:https://www.cnblogs.com/mix88/p/6213130.html
Copyright © 2020-2023  润新知