zoukankan      html  css  js  c++  java
  • 树的二叉链表(孩子-兄弟)存储

     /* c6-5.h 树的二叉链表(孩子-兄弟)存储表示 */
     typedef struct CSNode
     {
       TElemType data;
       struct CSNode *firstchild,*nextsibling;
     }CSNode,*CSTree;
     /* bo6-5.c 树的二叉链表(孩子-兄弟)存储(存储结构由c6-5.h定义)的基本操作(17个) */
     Status InitTree(CSTree *T)
     { /* 操作结果: 构造空树T */
       *T=NULL;
       return OK;
     }
    
     void DestroyTree(CSTree *T)
     { /* 初始条件: 树T存在。操作结果: 销毁树T */
       if(*T)
       {
         if((*T)->firstchild) /* T有长子 */
           DestroyTree(&(*T)->firstchild); /* 销毁T的长子为根结点的子树 */
         if((*T)->nextsibling) /* T有下一个兄弟 */
           DestroyTree(&(*T)->nextsibling); /* 销毁T的下一个兄弟为根结点的子树 */
         free(*T); /* 释放根结点 */
         *T=NULL;
       }
     }
    
     typedef CSTree QElemType; /* 定义队列元素类型 */
     #include"c3-2.h" /* 定义LinkQueue类型 */
     #include"bo3-2.c" /* LinkQueue类型的基本操作 */
     Status CreateTree(CSTree *T)
     { /* 构造树T */
       char c[20]; /* 临时存放孩子结点(设不超过20个)的值 */
       CSTree p,p1;
       LinkQueue q;
       int i,l;
       InitQueue(&q);
       printf("请输入根结点(字符型,空格为空): ");
       scanf("%c%*c",&c[0]);
       if(c[0]!=Nil) /* 非空树 */
       {
         *T=(CSTree)malloc(sizeof(CSNode)); /* 建立根结点 */
         (*T)->data=c[0];
         (*T)->nextsibling=NULL;
         EnQueue(&q,*T); /* 入队根结点的指针 */
         while(!QueueEmpty(q)) /* 队不空 */
         {
           DeQueue(&q,&p); /* 出队一个结点的指针 */
           printf("请按长幼顺序输入结点%c的所有孩子: ",p->data);
           gets(c);
           l=strlen(c);
           if(l>0) /* 有孩子 */
           {
             p1=p->firstchild=(CSTree)malloc(sizeof(CSNode)); /* 建立长子结点 */
             p1->data=c[0];
             for(i=1;i<l;i++)
             {
               p1->nextsibling=(CSTree)malloc(sizeof(CSNode)); /* 建立下一个兄弟结点 */
               EnQueue(&q,p1); /* 入队上一个结点 */
               p1=p1->nextsibling;
               p1->data=c[i];
             }
             p1->nextsibling=NULL;
             EnQueue(&q,p1); /* 入队最后一个结点 */
           }
           else
             p->firstchild=NULL;
         }
       }
       else
         *T=NULL;
       return OK;
     }
    
     #define ClearTree DestroyTree /* 二者操作相同 */
    
     Status TreeEmpty(CSTree T)
     { /* 初始条件: 树T存在。操作结果: 若T为空树,则返回TURE,否则返回FALSE */
       if(T) /* T不空 */
         return FALSE;
       else
         return TRUE;
     }
    
     int TreeDepth(CSTree T)
     { /* 初始条件: 树T存在。操作结果: 返回T的深度 */
       CSTree p;
       int depth,max=0;
       if(!T) /* 树空 */
         return 0;
       if(!T->firstchild) /* 树无长子 */
         return 1;
       for(p=T->firstchild;p;p=p->nextsibling)
       {
         depth=TreeDepth(p);
         if(depth>max)
           max=depth;
       }
       return max+1;
     }
    
     TElemType Value(CSTree p)
     { /* 返回p所指结点的值 */
       return p->data;
     }
    
     TElemType Root(CSTree T)
     { /* 初始条件: 树T存在。操作结果: 返回T的根 */
       if(T)
         return Value(T);
       else
         return Nil;
     }
    
     CSTree Point(CSTree T,TElemType s)
     { /* 返回二叉链表(孩子-兄弟)树T中指向元素值为s的结点的指针。另加 */
       LinkQueue q;
       QElemType a;
       if(T) /* 非空树 */
       {
         InitQueue(&q); /* 初始化队列 */
         EnQueue(&q,T); /* 根结点入队 */
         while(!QueueEmpty(q)) /* 队不空 */
         {
           DeQueue(&q,&a); /* 出队,队列元素赋给a */
           if(a->data==s)
         return a;
           if(a->firstchild) /* 有长子 */
             EnQueue(&q,a->firstchild); /* 入队长子 */
           if(a->nextsibling) /* 有下一个兄弟 */
             EnQueue(&q,a->nextsibling); /* 入队下一个兄弟 */
         }
       }
       return NULL;
     }
    
     Status Assign(CSTree *T,TElemType cur_e,TElemType value)
     { /* 初始条件: 树T存在,cur_e是树T中结点的值。操作结果: 改cur_e为value */
       CSTree p;
       if(*T) /* 非空树 */
       {
         p=Point(*T,cur_e); /* p为cur_e的指针 */
         if(p) /* 找到cur_e */
         {
           p->data=value; /* 赋新值 */
           return OK;
         }
       }
       return Nil; /* 树空或没找到 */
     }
    
     TElemType Parent(CSTree T,TElemType cur_e)
     { /* 初始条件: 树T存在,cur_e是T中某个结点 */
       /* 操作结果: 若cur_e是T的非根结点,则返回它的双亲,否则函数值为"空" */
       CSTree p,t;
       LinkQueue q;
       InitQueue(&q);
       if(T) /* 树非空 */
       {
         if(Value(T)==cur_e) /* 根结点值为cur_e */
           return Nil;
         EnQueue(&q,T); /* 根结点入队 */
         while(!QueueEmpty(q))
         {
           DeQueue(&q,&p);
           if(p->firstchild) /* p有长子 */
           {
             if(p->firstchild->data==cur_e) /* 长子为cur_e */
               return Value(p); /* 返回双亲 */
             t=p; /* 双亲指针赋给t */
             p=p->firstchild; /* p指向长子 */
             EnQueue(&q,p); /* 入队长子 */
             while(p->nextsibling) /* 有下一个兄弟 */
             {
               p=p->nextsibling; /* p指向下一个兄弟 */
           if(Value(p)==cur_e) /* 下一个兄弟为cur_e */
             return Value(t); /* 返回双亲 */
           EnQueue(&q,p); /* 入队下一个兄弟 */
         }
           }
         }
       }
       return Nil; /* 树空或没找到cur_e */
     }
    
     TElemType LeftChild(CSTree T,TElemType cur_e)
     { /* 初始条件: 树T存在,cur_e是T中某个结点 */
       /* 操作结果: 若cur_e是T的非叶子结点,则返回它的最左孩子,否则返回"空" */
       CSTree f;
       f=Point(T,cur_e); /* f指向结点cur_e */
       if(f&&f->firstchild) /* 找到结点cur_e且结点cur_e有长子 */
         return f->firstchild->data;
       else
         return Nil;
     }
    
     TElemType RightSibling(CSTree T,TElemType cur_e)
     { /* 初始条件: 树T存在,cur_e是T中某个结点 */
       /* 操作结果: 若cur_e有右兄弟,则返回它的右兄弟,否则返回"空" */
       CSTree f;
       f=Point(T,cur_e); /* f指向结点cur_e */
       if(f&&f->nextsibling) /* 找到结点cur_e且结点cur_e有右兄弟 */
         return f->nextsibling->data;
       else
         return Nil; /* 树空 */
     }
    
     Status InsertChild(CSTree *T,CSTree p,int i,CSTree c)
     { /* 初始条件: 树T存在,p指向T中某个结点,1≤i≤p所指结点的度+1,非空树c与T不相交 */
       /* 操作结果: 插入c为T中p结点的第i棵子树 */
       /* 因为p所指结点的地址不会改变,故p不需是引用类型 */
       int j;
       if(*T) /* T不空 */
       {
         if(i==1) /* 插入c为p的长子 */
         {
           c->nextsibling=p->firstchild; /* p的原长子现是c的下一个兄弟(c本无兄弟) */
           p->firstchild=c;
         }
         else /* 找插入点 */
         {
           p=p->firstchild; /* 指向p的长子 */
           j=2;
           while(p&&j<i)
           {
             p=p->nextsibling;
             j++;
           }
           if(j==i) /* 找到插入位置 */
           {
             c->nextsibling=p->nextsibling;
             p->nextsibling=c;
           }
           else /* p原有孩子数小于i-1 */
             return ERROR;
         }
         return OK;
       }
       else /* T空 */
         return ERROR;
     }
    
     Status DeleteChild(CSTree *T,CSTree p,int i)
     { /* 初始条件: 树T存在,p指向T中某个结点,1≤i≤p所指结点的度 */
       /* 操作结果: 删除T中p所指结点的第i棵子树 */
       /* 因为p所指结点的地址不会改变,故p不需是引用类型 */
       CSTree b;
       int j;
       if(*T) /* T不空 */
       {
         if(i==1) /* 删除长子 */
         {
           b=p->firstchild;
           p->firstchild=b->nextsibling; /* p的原次子现是长子 */
           b->nextsibling=NULL;
           DestroyTree(&b);
         }
         else /* 删除非长子 */
         {
           p=p->firstchild; /* p指向长子 */
           j=2;
           while(p&&j<i)
           {
             p=p->nextsibling;
             j++;
           }
           if(j==i) /* 找到第i棵子树 */
           {
             b=p->nextsibling;
             p->nextsibling=b->nextsibling;
             b->nextsibling=NULL;
             DestroyTree(&b);
           }
           else /* p原有孩子数小于i */
             return ERROR;
         }
         return OK;
       }
       else
         return ERROR;
     }
    
     void PreOrderTraverse(CSTree T,void(*Visit)(TElemType))
     { /* 先根遍历孩子-兄弟二叉链表结构的树T */
       if(T)
       {
         Visit(Value(T)); /* 先访问根结点 */
         PreOrderTraverse(T->firstchild,Visit); /* 再先根遍历长子子树 */
         PreOrderTraverse(T->nextsibling,Visit); /* 最后先根遍历下一个兄弟子树 */
       }
     }
    
     void PostOrderTraverse(CSTree T,void(*Visit)(TElemType))
     { /* 后根遍历孩子-兄弟二叉链表结构的树T */
       CSTree p;
       if(T)
       {
         if(T->firstchild) /* 有长子 */
         {
           PostOrderTraverse(T->firstchild,Visit); /* 后根遍历长子子树 */
           p=T->firstchild->nextsibling; /* p指向长子的下一个兄弟 */
           while(p)
           {
             PostOrderTraverse(p,Visit); /* 后根遍历下一个兄弟子树 */
             p=p->nextsibling; /* p指向再下一个兄弟 */
           }
         }
         Visit(Value(T)); /* 最后访问根结点 */
       }
     }
    
     void LevelOrderTraverse(CSTree T,void(*Visit)(TElemType))
     { /* 层序遍历孩子-兄弟二叉链表结构的树T */
       CSTree p;
       LinkQueue q;
       InitQueue(&q);
       if(T)
       {
         Visit(Value(T)); /* 先访问根结点 */
         EnQueue(&q,T); /* 入队根结点的指针 */
         while(!QueueEmpty(q)) /* 队不空 */
         {
           DeQueue(&q,&p); /* 出队一个结点的指针 */
           if(p->firstchild) /* 有长子 */
           {
             p=p->firstchild;
             Visit(Value(p)); /* 访问长子结点 */
             EnQueue(&q,p); /* 入队长子结点的指针 */
             while(p->nextsibling) /* 有下一个兄弟 */
             {
               p=p->nextsibling;
               Visit(Value(p)); /* 访问下一个兄弟 */
               EnQueue(&q,p); /* 入队兄弟结点的指针 */
             }
           }
         }
       }
     }
     /* main6-5.c 检验bo6-5.c的主程序 */
     #include"c1.h"
     typedef char TElemType;
     TElemType Nil=' '; /* 以空格符为空 */
     #include"c6-5.h"
     #include"bo6-5.c"
    
     void vi(TElemType c)
     {
       printf("%c ",c);
     }
    
     void main()
     {
       int i;
       CSTree T,p,q;
       TElemType e,e1;
       InitTree(&T);
       printf("构造空树后,树空否? %d(1:是 0:否) 树根为%c 树的深度为%d\n",TreeEmpty(T),Root(T),TreeDepth(T));
       CreateTree(&T);
       printf("构造树T后,树空否? %d(1:是 0:否) 树根为%c 树的深度为%d\n",TreeEmpty(T),Root(T),TreeDepth(T));
       printf("先根遍历树T:\n");
       PreOrderTraverse(T,vi);
       printf("\n请输入待修改的结点的值 新值: ");
       scanf("%c%*c%c%*c",&e,&e1);
       Assign(&T,e,e1);
       printf("后根遍历修改后的树T:\n");
       PostOrderTraverse(T,vi);
       printf("\n%c的双亲是%c,长子是%c,下一个兄弟是%c\n",e1,Parent(T,e1),LeftChild(T,e1),RightSibling(T,e1));
       printf("建立树p:\n");
       InitTree(&p);
       CreateTree(&p);
       printf("层序遍历树p:\n");
       LevelOrderTraverse(p,vi);
       printf("\n将树p插到树T中,请输入T中p的双亲结点 子树序号: ");
       scanf("%c%d%*c",&e,&i);
       q=Point(T,e);
       InsertChild(&T,q,i,p);
       printf("层序遍历树T:\n");
       LevelOrderTraverse(T,vi);
       printf("\n删除树T中结点e的第i棵子树,请输入e i: ");
       scanf("%c%d",&e,&i);
       q=Point(T,e);
       DeleteChild(&T,q,i);
       printf("层序遍历树T:\n",e,i);
       LevelOrderTraverse(T,vi);
       printf("\n");
       DestroyTree(&T);
     }
    作者:cpoint
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    “菜鸟”程序员和“大神”程序员差距在哪里?别告诉我你连菜鸟都不算!
    Android开发:为什么你的学习效率如此低,为什么你很迷茫?
    Android架构师吐槽腾讯王者荣耀的程序员,排位匹配算法怎么搞的,每次都输
    程序员如何回答面试官“请介绍一下自己”这类问题
    Android程序员事件分发机制学习笔记
    面试时,问哪些问题能试出一个 Android 应用开发者真正的水平?
    List、Set、Map的区别
    在Eclipse中使用JUnit4进行单元测试(图文教程一)
    1
    2016、11、17
  • 原文地址:https://www.cnblogs.com/cpoint/p/3480182.html
Copyright © 2011-2022 走看看