多叉树后序转前序++

多叉树前序转后序

返回比赛首页

给定一颗多叉树,


该多叉树可以用一个后序遍历的字符串表示为4(0),5(0),1(2),6(0),2(1),7(0),8(0),9(0),10(0),3(4),0(3)

其中括号内的数字表示该节点的子节点数,比如0(3)表示节点03个子节点,而节点按照后序遍历的顺序排列。

给定一个类似的多叉树后序遍历的字符串,试写出一个程序输出其对应前序遍历的字符串。

如上述多叉树的前序遍历字符串为0,1,4,5,2,6,3,7,8,9,10

注意,在输出中不包含节点的子节点数。注意子节点是有顺序的,在输出中应保证子节点的顺序和后序遍历一致,比如在上例中,输出0,1,5,4,2,6,3,7,8,9,10是错误的。


输入:

输入多行数据,直到结束。每行数据包含一个多叉树的后序遍历的字符串。


输出:

对于每行输入数据,通过stdout,输出一行该多叉树的前序遍历的字符串


样例输入:

4(0),5(0),1(2),6(0),2(1),7(0),8(0),9(0),10(0),3(4),0(3)

1(0),3(0),4(0),2(2),0(2)

4(0),5(0),2(2),3(0),1(2),0(1)


样例输出:

0,1,4,5,2,6,3,7,8,9,10

0,1,2,3,4

0,1,2,4,5,3


解决方案:

#include <stdio.h>
#include <stdlib.h>

#define MAX 100
typedef struct node {
    int num;
    int size;
    struct node * children[MAX];
} node_t;

node_t * list[100000];


 void preOrderTree( node_t *root) {
    int i;

    if(root) {
        printf("%d,", root->num);
        for(i = 0; i < root->size; ++i) {
            preOrderTree(root->children[i]);
        }
    }
 }

 void destroyTree(node_t *root) {
    int i;

    if(root) {
        for(i = 0; i < root->size; ++i) {
            destroyTree(root->children[i]);
        }
        free(root);
    }
}

int main(int argc, char *argv[])
{
    int i;

    int num;
    int size;
    int count = 0;

    FILE *fp = fopen("sysFileUrl", "r");
    if(NULL != fp) {
            while(fscanf(fp, "%d(%d),", &num, &size) != EOF) {
                node_t *p = malloc(sizeof(node_t));
                if(NULL != p) {
                    p->num = num;
                    p->size = size;

                    if(size == 0 ) {
                        list[count++] = p;
                    }else {
                        for(i = size - 1; i >= 0; --i) {
                            p->children[i] = list[--count];
                        }

                        if(num != 0) {
                            list[count++] = p;
                        }
                    }

                    if(num == 0) {
                        preOrderTree(p);
                        printf("\n");
                        destroyTree(p);
                    }
                }
            }

        fclose(fp);
    }

    return 0;
}


1.改进方案:
//树节点中的孩子数组,采用动态数组,可以节省空间;
//此外,当某个节点度数(孩子节点个数)极端多的情况,
//将会避免更多空间的浪费,同时也能保证算法的可行性;

//list中元素最多时,不超过最大度数的的2倍

代码如下:

#include <stdio.h>
#include <stdlib.h>

//树中的节点的最大度数
#define MAX 100

//树节点中的孩子数组,采用动态数组,可以节省空间;
//此外,当某个节点度数(孩子节点个数)极端多的情况,
//将会避免更多空间的浪费,同时也能保证算法的可行性;
typedef struct node {
    int num;
    int size;
//struct node * children[MAX];
    struct node *children[0];
} node_t;

//list中元素最多时,不超过最大度数的的2倍;
node_t *list[MAX*2];


 void preOrderTree( node_t *root) {
    int i;
    if(root) {
        printf("%d,", root->num);
        for(i = 0; i < root->size; ++i) {
            preOrderTree(root->children[i]);
        }
    }
 }

 void destroyTree(node_t *root) {
    int i;

    if(root) {
        for(i=0; i < root->size; ++i) {
            destroyTree(root->children[i]);
        }
        free(root);
    }
}

int main(int argc, char *argv[])
{
    int i;

    int num;
    int size;
    int count = 0;
    printf("\\n = %d \n", '\n');
    printf("\\r = %d \n", '\r');

    FILE *fp = fopen("sysFileUrl", "r");
    if(NULL != fp) {
            while(fscanf(fp, "%d(%d),", &num, &size) != EOF) {
                node_t *p = (node_t *) malloc(sizeof(node_t) + size * sizeof(node_t *));
                int tag = 0;
                int ch = fgetc(fp);
                if( ch == '\n' || ch == '\r' || ch == EOF ) {
                    printf("ch = %d \n", ch);
                    ungetc(ch, fp);
                    tag = 1
                }
                if(NULL != p) {
                    p->num = num;
                    p->size = size;

                    if(size == 0 ) {
                        list[count++] = p;
                    }else {
                        for(i = size - 1; i >= 0; --i) {
                            p->children[i] = list[--count];
                        }

                        if(num != 0) {
                            list[count++] = p;
                        }
                    }

                    if(num == 0) {
                        preOrderTree(p);
                        printf("\n");
                        destroyTree(p);
                    }
                }
            }

        fclose(fp);
    }

    return 0;
}



改进方案2:  避免通过测试节点值为0,作为根节点的标志。
#include <stdio.h>
#include <stdlib.h>

//树中的节点的最大度数
#define MAX 100

//树节点中的孩子数组,采用动态数组,可以节省空间;
//此外,当某个节点度数(孩子节点个数)极端多的情况,
//将会避免更多空间的浪费,同时也能保证算法的可行性;
typedef struct node {
    int num;
    int size;
//struct node * children[MAX];
    struct node *children[0];
} node_t;

//list中元素最多时,不超过最大度数的的2倍;
node_t *list[MAX*2];


 void preOrderTree( node_t *root) {
    int i;
    if(root) {
        printf("%d,", root->num);
        for(i = 0; i < root->size; ++i) {
            preOrderTree(root->children[i]);
        }
    }
 }

 void destroyTree(node_t *root) {
    int i;

    if(root) {
        for(i=0; i < root->size; ++i) {
            destroyTree(root->children[i]);
        }
        free(root);
    }
}

//获取换行标志
int getTag(FILE *fp) {
    int tag = 0;

    int ch = fgetc(fp);
    if( ch == '\n' || ch == '\r' /*|| ch == EOF */) {
      //  printf("ch = %d \n", ch);
        tag = 1;
    }
    ungetc(ch, fp);

    return tag;
}


int main(int argc, char *argv[])
{
    int i;

    int num;
    int size;
    int count = 0;
    int tag;   // 换行标志,以示,一棵树到达root;

    FILE *fp = fopen("sysFileUrl", "r");
    if(NULL != fp) {
            while(fscanf(fp, "%d(%d),", &num, &size) != EOF) {
                node_t *p = (node_t *) malloc(sizeof(node_t) + size * sizeof(node_t *));
                tag = getTag(fp);

                if(NULL != p) {
                    p->num = num;
                    p->size = size;

                    //叶子节点
                    if(size == 0 ) {
                        list[count++] = p;
                    }else {
                        for(i = size - 1; i >= 0; --i) {
                            p->children[i] = list[--count];
                        }
                        //非根节点也非叶子节点
                        if(!tag) {
                            list[count++] = p;
                        }
                    }

                    //根节点
                    if(tag) {
                        preOrderTree(p);
                        printf("\n");
                        destroyTree(p);
                    }
                }
            }

        fclose(fp);
    }

    return 0;
}



2.将句子中单词逆序,如 “Hello world" 变为”world Hello"
思路:首先将句子逆序,然后将每个逆序的单词进行逆序。

代码实现:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void swap(char *p, char *q);
void reverseStringWord(char *str);


int main(int argc, char *argv[])
{
        char str[] = "Hello world. ";
        reverseStringWord(str);
        printf(str);
        printf("\n");


        return 0;
}

void swap(char *p, char *q) {
        char temp = *p;
        *p = *q;
        *q = temp;
}

void reverseStringWord(char *str) {
        char *p;
        char *q;
        char *r;
        int length;

        if(str) {
                length = strlen(str);
                p = str;
                q = str + length - 1;

                //实现句子逆序
                while(p < q) {
                        swap(p++, q--);
                }

                //实现句子中的每个单词逆序
                p = str;
                while(*p) {
                        //跳过单词前的空格
                        while(*p && *p == ' ') ++p; // p指向word的开始字符
                        //if(*p == '\0') break;

                        //找到单词的结尾字符
                        q = p;
                        while(*q && *q != ' ')  ++q; //q指向word的结尾字符的下一个字符
                        r = q - 1;  // r 指向word的结尾字符

                        //实现单词逆序
                        while(p < r) {
                                swap(p++, r--);
                        }

                        p = q;
                }
        }

}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值