Chinaunix首页 | 论坛 | 博客
  • 博客访问: 281844
  • 博文数量: 76
  • 博客积分: 1500
  • 博客等级: 上尉
  • 技术积分: 594
  • 用 户 组: 普通用户
  • 注册时间: 2011-08-05 23:43
文章分类

全部博文(76)

文章存档

2014年(4)

2013年(3)

2012年(20)

2011年(49)

分类: C/C++

2011-09-07 11:53:41

    1. 转载数据结构C语言实现系列[8]——树

    2. #include <stdio.h>
    3. #include <stdlib.h>
    4. #define kk 3 /* 定义树的度 */
    5. #define MS 10 /* 定义在建立树的存储结构时的栈空间大小 */
    6. #define MQ 10 /* 定义在树的按层遍历算法中的队列空间大小 */
    7. typedef char elemType;

    8. /************************************************************************/
    9. /*    以下是关于树操作的4个简单算法 */
    10. /************************************************************************/
    11. struct GTreeNode{
    12.     elemType data;
    13.     struct GTreeNode *t[kk];
    14.     struct GTreeNode *parent;
    15. };
    16. /* 建立树的存储结构 */
    17. void createGTree(struct GTreeNode* *gt, char *a)
    18. {
    19.     struct GTreeNode *s[MS]; /* 数组s作为存储树中结点指针的栈使用 */
    20.     int d[MS]; /* 数组d作为存储孩子结点链接到双亲结点指针域的序号栈使用 */
    21.     int top = -1; /* top作为两个栈的栈顶指针,初值为-1表示栈空 */
    22.     struct GTreeNode *p; /* 定义p为指向树结点的指针 */
    23.     int i = 0, j; /* i指示扫描字符串a中的当前字符位置 */
    24.     *gt = NULL; /* 初始将树根指针置空 */
    25.     
    26.     while(a[i] != 'o'){/* 每次循环处理一个字符,直到字符串结束为止 */
    27.         switch(a[i]){
    28.             /* 对空格不作处理 */
    29.             case ' ':
    30.                 break;
    31.             /* 处理左括号时,让p指针进s栈,0进d栈,表明待扫描的孩子
    32.             结点将被链接到s栈顶元素所指结点的第一个指针域*/
    33.             case '(':
    34.                 top++;
    35.                 s[top] = p;
    36.                 d[top] = 0;
    37.                 break;
    38.             /* 处理右括号时,让s和d退栈 */
    39.             case ')':
    40.                 top--;
    41.                 break;
    42.         /* 处理逗号时,让待读入的孩子的结点链接到s栈顶元素所指结点
    43.                的下一个指针域*/
    44.             case ',':
    45.                 d[top]++;
    46.                 break;
    47.             /* 此处处理的必然是字符元素 */
    48.             default:
    49.                 /* 根据a[i]字符生成新结点 */
    50.                 p = malloc(sizeof(struct GTreeNode));
    51.                 p->data = a[i];
    52.                 for(j = 0; j < kk; j++){/* 用kk表示树的深度k */
    53.                     p->t[j] = NULL;
    54.                 }
    55.                 if(NULL == *gt ){
    56.                     *gt = p; /* 使结点p成为树根 */
    57.                 }else{
    58.                     s[top]->t[d[top]] = p;/* 链接到双亲结点对应
    59.                     的指针域 */
    60.                 }
    61.                 break;
    62.         }
    63.         i++; /* 准备处理下一个字符 */
    64.     }
    65.     return;
    66. }

    67. /* 2.树的遍历 */
    68. /* 先根 */
    69. void preRoot(struct GTreeNode *gt)
    70. {
    71.     int i;
    72.     if(gt != NULL){
    73.         printf("%c ", gt->data); /* 访问根结点 */
    74.         for(i = 0; i < kk; i++){
    75.             preRoot(gt->t[i]); /* 递归遍历每一棵子树 */
    76.         }
    77.     }
    78.     return;
    79. }

    80. /* 后根 */
    81. void postRoot(struct GTreeNode *gt)
    82. {
    83.     int i;
    84.     if(gt != NULL){
    85.         for(i = 0; i < kk; i++){
    86.             postRoot(gt->t[i]); /* 递归遍历每一棵子树 */
    87.         }
    88.         printf("%c ", gt->data); /* 访问根结点 */
    89.     }

    90. }

    91. /* 按层 */
    92. void levelOrder(struct GTreeNode *gt)
    93. {
    94.     struct GTreeNode *p;
    95.     int i;
    96.     struct GTreeNode *q[MQ]; /* 队列用的数组q,存放根结点 */
    97.     int front = 0, rear = 0;
    98.     /* 将整棵树的树根指针入队 */
    99.     if(gt != NULL){
    100.         rear = (rear + 1 % MQ);
    101.         q[rear] = gt;
    102.     }
    103.     /* 当队列非空时执行循环 */
    104.     while(front != rear){
    105.         front = (front + 1) % MQ; /* */
    106.         /* 删除队首元素,输出队首元素所指结点的值 */
    107.         p = q[front];
    108.         printf("%c ", p->data);
    109.         /* 非空的孩子结点的指针依次进队 */
    110.         for(i = 0; i < kk; i++){
    111.             if(p->t[i] != NULL){
    112.                 rear = (rear + 1) % MQ;
    113.                 q[rear] = p->t[i];
    114.             }
    115.         }
    116.     }
    117.     return;
    118. }

    119. /* 3.从树中查找结点 */
    120. elemType *findGTree(struct GTreeNode *gt, elemType x)
    121. {
    122.     /* 若树空则返回NULL */
    123.     if(gt == NULL){
    124.         return NULL;
    125.     }else{
    126.         elemType *p;
    127.         int i;
    128.         /* 若查找成功返回结点值域的地址 */
    129.         if(gt->data == x){
    130.             return &(gt->data);
    131.         }
    132.         /* 向每棵子树继续查找,返回得到的值域地址 */
    133.         for(i = 0; i < kk; i++){
    134.             if(p = findGTree(gt->t[i], x)){
    135.                 return p;
    136.             }
    137.         }
    138.         return NULL; /* 查找不成功返回NULL */
    139.     }
    140. }

    141. /* 树的输出 */
    142. void printGTree(struct GTreeNode *gt)
    143. {
    144.     if(gt != NULL){
    145.         int i;
    146.         printf("%c", gt->data);
    147.         /* 判断gt结点是否有孩子 */
    148.         for(i = 0; i < kk; i++){
    149.             if(gt->t[i] != NULL){
    150.                 break;
    151.             }
    152.         }
    153.         /* 有孩子时才执行条件语句体的向下递归调用 */
    154.         if(i < kk){
    155.             printf("(");
    156.             printGTree(gt->t[0]); /* 输出第一棵子树 */
    157.             /* 输出其余各个子树 */
    158.             for(i = 1; i < kk; i++){
    159.                 printf(",");
    160.                 printGTree(gt->t[i]);
    161.             }
    162.             printf(")");
    163.         }
    164.     }
    165.     return;
    166. }

    167. /* 5.求树的深度 */
    168. int depthGTree(struct GTreeNode *gt)
    169. {
    170.     int i, max;
    171.     /* 空树的深度为0 */
    172.     if(gt == NULL){
    173.         return 0;
    174.     }
    175.     /* 求非空树的深度,max的初值为0 */
    176.     max = 0;
    177.     for(i = 0; i < kk; i++){
    178.         int d = depthGTree(gt->t[i]);/* 计算出一棵子树的深度并赋值给d */
    179.         if(d > max){
    180.             max = d;
    181.         }
    182.     }
    183.     return max + 1; /* 返回非空树的深度,它等于各子树的最大深度加1 */
    184. }

    185. /* 6.清除树中的所有结点,使之成为一棵空树 */
    186. void clearGTree(struct GTreeNode* *gt)
    187. {
    188.     if(*gt != NULL){
    189.         int i;
    190.         for(i = 0; i < kk; i++){
    191.             clearGTree(&((*gt)->t[i]));
    192.         }
    193.         free(*gt);
    194.         *gt = NULL;
    195.     }
    196.     return;
    197. }



    198. /************************************************************************/

    199. int main(int argc, char *argv[])
    200. {
    201.     char ch;
    202.     struct GTreeNode *gt = NULL;
    203.     char b[50]; /* 用于存入k叉树广义表的字符数组 */
    204.     printf("输入一棵%d叉树的广义表字符串: ", kk);
    205.     scanf("%s", b);
    206.     createGTree(&gt, b);
    207.     printf("先根遍历:");
    208.     preRoot(gt);
    209.     printf(" ");
    210.     printf("后根遍历:");
    211.     postRoot(gt);
    212.     printf(" ");
    213.     printf("按层遍历:");
    214.     levelOrder(gt);
    215.     printf(" ");
    216.     printf("按广义表的形式输出:");
    217.     printGTree(gt);
    218.     printf(" ");
    219.     printf("树的深度为:%d ", depthGTree(gt));
    220.     printf("输入待查找的字符:");
    221.     scanf(" %c", &ch);
    222.     if(findGTree(gt, ch)){
    223.         printf("查找成功! ");
    224.     }else{
    225.         printf("查找失败! ");
    226.     }
    227.     clearGTree(&gt);
    228.     return 0;
    229. }
阅读(673) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~