• 由遍历序列创建二叉树


      #返回上一级

    @Author: 张海拔

    @Update: 2014-01-19

    @Link: http://www.cnblogs.com/zhanghaiba/p/3525693.html

      1 /*
      2  *Author: ZhangHaiba
      3  *Date: 2014-1-19
      4  *File: order_create_binary_tree.c
      5  *
      6  *this demo shows how to use inorder list & preorder list to rebuild binary tree
      7  *and how to use inorder list & postorder list as well
      8  */
      9 
     10 
     11 #include <stdio.h>
     12 #include <stdlib.h>
     13 #define LEN 512
     14 #define CMD_LEN 128
     15 
     16 typedef struct node* link;
     17 
     18 typedef struct node {
     19     int item;
     20     link left;
     21     link right;
     22 }node;
     23 
     24 //public
     25 link NODE(int item, link left, link right);
     26 void set_order(int len, int *first, int *second);
     27 void set_error(void);
     28 link create_by_order1(int *inorder, int *preorder, int len);
     29 link create_by_order2(int *inorder, int *postorder, int len);
     30 void show_by_tree(link root);
     31 //private
     32 void tree_print(link root, FILE *fd);
     33 
     34 //private
     35 node error;
     36 int ERROR;
     37 int inorder[LEN];
     38 int preorder[LEN];
     39 int postorder[LEN];
     40 
     41 int main(void)
     42 {
     43     int len, i;
     44     link root;
     45 
     46     printf("enter the length of order list:
    ");
     47     scanf("%d", &len);
     48     printf("enter inorder and preorder list:
    ");
     49     set_order(len, inorder, preorder);
     50     set_error();
     51     root = create_by_order1(inorder, preorder, len);
     52     root == &error ? printf("input illegal
    ") : show_by_tree(root);
     53 
     54     printf("enter the length of order list:
    ");
     55     scanf("%d", &len);
     56     printf("enter inorder and postorder list:
    ");
     57     set_order(len, inorder, postorder);
     58     set_error();
     59     root = create_by_order2(inorder, postorder, len);
     60     root == &error ? printf("input illegal
    ") : show_by_tree(root);    
     61     return 0;
     62 }
     63 
     64 link NODE(int item, link left, link right)
     65 {
     66     link born = malloc(sizeof (node));
     67     born->item = item;
     68     born->left = left;
     69     born->right = right;
     70     return born;
     71 }
     72 
     73 void set_order(int len, int* first, int *second)
     74 {
     75     int i;
     76 
     77     for (i = 0; i < len; ++i)
     78         scanf("%d", first+i);
     79     for (i = 0; i < len; ++i)
     80         scanf("%d", second+i);
     81 }
     82 
     83 void set_error(void)
     84 {
     85     ERROR = 0;
     86 }
     87 
     88 link create_by_order1(int *inorder, int *preorder, int len)
     89 {
     90     if (ERROR) return NULL; //if ERROR==1, no need to expand nodes
     91     if (len <= 0) return NULL;
     92     int m = 0;
     93     while (inorder[m] != preorder[0] && m < len)
     94          ++m;
     95     if (m == len) ERROR = 1;
     96     link root = NODE(preorder[0], NULL, NULL);
     97     root->left = create_by_order1(inorder, preorder+1, m);
     98     root->right = create_by_order1(inorder+(m+1), preorder+(m+1), len-(m+1));
     99     return ERROR ? &error : root;
    100 }
    101 
    102 
    103 link create_by_order2(int *inorder, int *postorder, int len)
    104 {
    105     if (ERROR) return NULL; //if ERROR==1, no need to expand nodes
    106     if (len <= 0) return NULL;
    107     int m = 0;
    108     while (inorder[m] != postorder[len-1] && m < len)
    109         ++m;
    110     if (m == len) ERROR = 1;
    111     link root = NODE(postorder[len-1], NULL, NULL);
    112     root->left = create_by_order2(inorder, postorder, m);
    113     root->right = create_by_order2(inorder+(m+1), postorder+m, len-(m+1));
    114     return ERROR ? &error : root;
    115 }
    116 
    117 void show_by_tree(link root)
    118 {
    119     char cmd[CMD_LEN];
    120 
    121     sprintf(cmd, "rm -f ./tree_src.txt");
    122     system(cmd);
    123 
    124     FILE *fd = fopen("./tree_src.txt", "a+");
    125     fprintf(fd, "
    	\tree");
    126     tree_print(root, fd);
    127     fprintf(fd, "
    
    ");
    128     fclose(fd);
    129 
    130     sprintf(cmd, "cat ./tree_src.txt | ~/tree/tree");
    131     system(cmd);
    132 }
    133 
    134 void tree_print(link root, FILE *fd)
    135 {    
    136     fprintf(fd, "(");
    137     if (root != NULL) {
    138         fprintf(fd, "%d", root->item);
    139         tree_print(root->left, fd);
    140         tree_print(root->right, fd);
    141     }
    142     fprintf(fd, ")");
    143 }

    测试示范

    ZhangHaiba-MacBook-Pro:code apple$ ./a.out
    enter the length of order list:
    12
    enter inorder and preorder list:
    4 10 5 30 9 7 13 20 11 15 8 12
    10 4 20 30 5 9 13 7 8 11 15 12
    
                  10
             _____|______
             |          |
             4          20
            _|__  ______|______
            |  |  |           |
                  30          8
               ___|___     ___|___
               |     |     |     |
               5     9     11    12
              _|__  _|__  _|__  _|__
              |  |  |  |  |  |  |  |
                       13    15
                      _|__  _|__
                      |  |  |  |
                      7
                     _|__
                     |  |
    
    enter the length of order list:
    12
    enter inorder and postorder list:
    4 10 5 30 9 7 13 20 11 15 8 12
    4 5 7 13 9 30 15 11 12 8 20 10
    
                  10
             _____|______
             |          |
             4          20
            _|__  ______|______
            |  |  |           |
                  30          8
               ___|___     ___|___
               |     |     |     |
               5     9     11    12
              _|__  _|__  _|__  _|__
              |  |  |  |  |  |  |  |
                       13    15
                      _|__  _|__
                      |  |  |  |
                      7
                     _|__
                     |  |
    
    
    ZhangHaiba-MacBook-Pro:code apple$ ./a.out
    enter the length of order list:
    7
    enter inorder and preorder list:
    2 3 7 10 22 11 8
    10 2 3 7 8 11 33
    input illegal
    enter the length of order list:
    7
    enter inorder and postorder list:
    2 3 7 10 22 11 8
    7 3 2 22 11 8 10
    
                   10
             ______|______
             |           |
             2           8
            _|__        _|__
            |  |        |  |
               3        11
              _|__     _|__
              |  |     |  |
                 7     22
                _|__  _|__
                |  |  |  |

      

    给出中序序列和前序序列建二叉树,处理方法类似分治法。

    前序序列的第一个元素是树根,在中序序列里面找到这个元素,设下标为m,则该元素左边数组是左子树的中序序列,右边数组是右子树的中序序列。

    注意到,子树的前序序列和中序序列元素个数必定是相同的,所以,左子树前序是preorder+1,长度是m;右子树前序是preorder+(m+1),长度是len-(m+1)。

    确定了子树的中序和前序序列,则分别对左、右子树调用创建函数,显然该过程是递归进行的。

    写递归函数,首先要确定好递归结束条件同时考虑第一次调用的情况,这里是当len <= 0,则不(再)创建,返回NULL。

    给出中序序列和后序序列建二叉树,原理同上。

    值得一提的是,如果序列长度用begin和end两个参量来确定边界则相对麻烦,用len一个参量反而更简单。

    可以对比中序和后序建树函数的写法,仅仅是后序序列首地址比前序序列首地址小了一个单位。

    左子树: perorder+1 : postorder; 右子树: perorder+(m+1) : postorder + m。

    说明:

    (1)怎样像测试示范那样打印出一棵树,参考 二叉排序树的递归实现 link(public)

    (2)创建函数中,与二叉排序树的插入等函数不同,参数列表没有link root,主要是考虑到这个创建过程类似一个原子操作。而BST插入函数的写法是为了代码复用。

    (3)上述实现中,还加入了错误检查。即如果在中序序列中,找不到前序序列或后序序列中的某个元素,则说明输入的序列是非法的。

    一旦发生错误,用全局错误标记ERROR来控制抑制树的继续生长,并最终返回一个全局错误节点error的地址,而不要返回一棵残缺无意义的树的树根。

    (4)上述程序假定输入序列中元素都是唯一的(不可重集)。有相同元素的序列不能唯一确定一棵二叉树,即有多棵二叉树与之对应。这个话题另外讨论。

      #返回上一级

  • 相关阅读:
    最后一次不用看脸的日子
    经典算法_指针
    #include <process.h>
    经典算法_文件
    stdin、stdout、stderr
    经典算法_位运算
    经典算法_结构体
    经典算法_字符串
    #include <string.h>
    #include <stdio.h>
  • 原文地址:https://www.cnblogs.com/zhanghaiba/p/3525693.html
Copyright © 2020-2023  润新知