多叉树前序转后序
给定一颗多叉树,
1.改进方案:
该多叉树可以用一个后序遍历的字符串表示为4(0),5(0),1(2),6(0),2(1),7(0),8(0),9(0),10(0),3(4),0(3)
其中括号内的数字表示该节点的子节点数,比如0(3)表示节点0有3个子节点,而节点按照后序遍历的顺序排列。
给定一个类似的多叉树后序遍历的字符串,试写出一个程序输出其对应前序遍历的字符串。
如上述多叉树的前序遍历字符串为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;
}
#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;
}
}
}