我是巴西的一名计算机工程专业的学生,本学期我将学习算法和数据结构课程。我现在的主题是“通用树”。我有一个模拟 cmd 之类的程序的活动,这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define true 1
#define false 0
typedef int bool;
typedef struct No {
char nome[1025];
struct No *primFilho;
struct No *proxIrmao;
struct No *pai;
} No;
typedef struct TipoRaiz {
No *raiz;
} TipoRaiz;
int contador = 0;
No *CriaNovoNo(char nome[1025]) {
No *novoNo = (No*) malloc(sizeof(No));
strcpy(novoNo->nome, nome);
novoNo->primFilho = NULL;
novoNo->proxIrmao = NULL;
novoNo->pai = NULL;
return novoNo;
}
void inicializa(TipoRaiz *raiz) {
raiz->raiz = CriaNovoNo("\\root");
}
void printTree(No *root, int depth) {
if (root == NULL)
return;
for (int i = 0; i < depth; i++)
printf(" ");
printf("%s\n", root->nome);
printTree(root->primFilho, depth + 1);
printTree(root->proxIrmao, depth);
}
No *buscaNo(char nome[], No *raiz) {
if(raiz == NULL)
return NULL;
if(strcmp(raiz->nome, nome) == 0)
return raiz;
No *p = raiz->primFilho;
while(p) {
No *resp = buscaNo(nome, p);
if(resp)
return resp;
p = p->proxIrmao;
}
return NULL;
}
void insere(TipoRaiz *root, char novoNo[], char localPai[]) {
No *pai = buscaNo(localPai, root->raiz);
if(pai == NULL)
return;
No *inserido = CriaNovoNo(novoNo);
inserido->pai = pai;
if(pai->primFilho == NULL) {
pai->primFilho = inserido;
}
else {
inserido->proxIrmao = pai->primFilho;
pai->primFilho = inserido;
}
contador++;
}
void removeNo(No *no) {
No *p = no->pai;
No *q = no->primFilho;
if(p != NULL) {
if(p->primFilho == no)
p->primFilho = no->proxIrmao;
else {
while(q->proxIrmao != no) {
q = q->proxIrmao;
}
q->proxIrmao = no->proxIrmao;
}
free(no);
}
}
void printCaminho(No* no) {
No* pilha[contador];
int top = -1;
while (no != NULL) {
pilha[++top] = no;
no = no->pai;
}
while(top >= 0) {
printf("%s ", pilha[top--]->nome);
}
}
int main() {
TipoRaiz root;
inicializa(&root);
int n;
char nome[1025], localPai[1025], comando[3], buscado[1025];
scanf("%d", &n);
scanf("%s", buscado);
for(int i = 0; i < n; i++) {
scanf("%s %s %s", comando, nome, localPai);
if(strcmp(comando, "-a") == 0)
insere(&root, nome, localPai);
else if(strcmp(comando,"-r") == 0) {
No *noParaRemover = buscaNo(nome, &root);
removeNo(noParaRemover);
}
else if (strcmp(comando, "-m") == 0) {
if(buscaNo(localPai, &root)) {
No *noParaMover = buscaNo(nome, &root);
removeNo(noParaMover);
insere(&root, nome, localPai);
}
}
}
// used for debuging purposes printTree(root.raiz, 0);
No *buscadoNo = buscaNo(buscado, root.raiz);
if(buscadoNo == NULL)
printf("Arquivo nao encontrado!\n");
else {
printCaminho(buscadoNo);
printf("\n");
}
return 0;
}
我有 10 个条目将针对我的代码进行测试,但在只有 2 个条目中,我遇到了问题,这可能是在我的“insere”函数中,该函数在树中插入一个新节点,或者在我的“删除”函数中函数,从树中删除节点。第一个条目给了我一个超过时间限制的信息,我不知道如何优化代码以使其运行得更快,而下一个条目给了我一个错误的输出,这里是测试(请随意修复您发现的更多错误)在我的代码中找到)v:
输入数字1(时限错误):
30
file8
-a \dir1 \root
-a \dir2 \root
-a \dir3 \root
-a \dir4 \root
-a \dir5 \root
-a \dir6 \root
-a \dir7 \root
-a \dir8 \root
-a \dir9 \root
-a \dir10 \root
-a file1 \root
-a file2 \root
-a file3 \root
-a file4 \root
-a file5 \root
-a file6 \root
-a file7 \root
-a file8 \root
-a file9 \root
-a file10 \root
-r file1
-r file3
-r file5
-r file7
-r file9
-r file2
-r file6
-r file10
-r file4
-m file8 \dir10
输出1应该是:
file8 \dir10 \root
输入数字2:
134
arq10
-a \dir1 \root
-a \dir2 \dir1
-a \dir3 \dir2
-a \dir4 \dir3
-a \dir5 \dir4
-a \dir6 \dir5
-a \dir7 \dir6
-a \dir8 \dir7
-a \dir9 \dir8
-a \dir10 \dir9
-a \dir11 \dir10
-a \dir12 \dir11
-a \dir13 \dir12
-a \dir14 \dir13
-a \dir15 \dir14
-a \dir16 \dir15
-a \dir17 \dir16
-a \dir18 \dir17
-a \dir19 \dir18
-a arq1 \dir1
-a arq2 \dir2
-a arq3 \dir3
-a arq4 \dir4
-a arq5 \dir5
-a arq6 \dir6
-a arq7 \dir7
-a arq8 \dir8
-a arq9 \dir9
-a arq10 \dir10
-a arq11 \dir11
-a arq12 \dir12
-a arq13 \dir13
-a arq14 \dir14
-a arq15 \dir15
-a arq16 \dir16
-a arq17 \dir17
-a arq18 \dir18
-a arq19 \dir19
-a \pasta1 \root
-a \pasta2 \pasta1
-a \pasta3 \pasta2
-a \pasta4 \pasta3
-a \pasta5 \pasta4
-a \pasta6 \pasta5
-a \pasta7 \pasta6
-a \pasta8 \pasta7
-a \pasta9 \pasta8
-a \pasta10 \pasta9
-a \pasta11 \pasta10
-a \pasta12 \pasta11
-a \pasta13 \pasta12
-a \pasta14 \pasta13
-a \pasta15 \pasta14
-a \pasta16 \pasta15
-a \pasta17 \pasta16
-a \pasta18 \pasta17
-a \pasta19 \pasta18
-m arq1 \pasta1
-m arq2 \pasta2
-m arq3 \pasta3
-m arq4 \pasta4
-m arq5 \pasta5
-m arq6 \pasta6
-m arq7 \pasta7
-m arq8 \pasta8
-m arq9 \pasta9
-m arq10 \pasta10
-m arq11 \pasta11
-m arq12 \pasta12
-m arq13 \pasta13
-m arq14 \pasta14
-m arq15 \pasta15
-m arq16 \pasta16
-m arq17 \pasta17
-m arq18 \pasta18
-m arq19 \pasta19
-a \novo1 \root
-a \novo2 \novo1
-a \novo3 \novo2
-a \novo4 \novo3
-a \novo5 \novo4
-a \novo6 \novo5
-a \novo7 \novo6
-a \novo8 \novo7
-a \novo9 \novo8
-a \novo10 \novo9
-a \novo11 \novo10
-a \novo12 \novo11
-a \novo13 \novo12
-a \novo14 \novo13
-a \novo15 \novo14
-a \novo16 \novo15
-a \novo17 \novo16
-a \novo18 \novo17
-a \novo19 \novo18
-m arq1 \nova1
-m arq2 \nova2
-m arq3 \nova3
-m arq4 \nova4
-m arq5 \nova5
-m arq6 \nova6
-m arq7 \nova7
-m arq8 \nova8
-m arq9 \nova9
-m arq10 \nova10
-m arq11 \nova11
-m arq12 \nova12
-m arq13 \nova13
-m arq14 \nova14
-m arq15 \nova15
-m arq16 \nova16
-m arq17 \nova17
-m arq18 \nova18
-m arq19 \nova19
-r arq1
-r arq2
-r arq3
-r arq4
-r arq5
-r arq6
-r arq7
-r arq8
-r arq9
-r arq10
-r arq11
-r arq12
-r arq13
-r arq14
-r arq15
-r arq16
-r arq17
-r arq18
-r arq19
-a arq10 \root
输出数字2应该是:
arq10 \root
正如 @CraigEstey 在
main()
中所解释的那样,函数 buscaNo()
的第二个参数是 No *
,但是你传递了它 &root
,它是 TipoRaiz *
。
正如@CraigEstey 解释的那样,你的程序会出现段错误。这是因为搜索
removeNo()
有错误。您需要从 No *q = p->primFilho;
开始搜索前一个节点,然后遍历链表 q = q->proxIrmao
。
第二个输入失败,因为您期望每行包含 3 个单词,但
-r
命令只包含 2 个。我建议您读一行然后使用 sscanf()
。
(未修复)虽然两个程序现在都返回正确的输出,但顺序错误。我把它留给你作为练习。
使用
scanf()
读取字符串时始终指定最大字段宽度。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define COMMAND_LEN 2
#define LEN 1024
#define str(s) str2(s)
#define str2(s) #s
typedef struct No {
char nome[LEN+1];
struct No *primFilho; // son
struct No *proxIrmao; // brother
struct No *pai; // far
} No;
typedef struct TipoRaiz {
No *raiz;
} TipoRaiz;
int contador = 0;
No *CriaNovoNo(char *nome) {
No *novoNo = malloc(sizeof *novoNo);
strcpy(novoNo->nome, nome);
novoNo->primFilho = NULL;
novoNo->proxIrmao = NULL;
novoNo->pai = NULL;
return novoNo;
}
void inicializa(TipoRaiz *raiz) {
raiz->raiz = CriaNovoNo("\\root");
}
void printTree(No *root, int depth) {
if (root == NULL)
return;
for (int i = 0; i < depth; i++)
printf(" ");
printf("%s\n", root->nome);
printTree(root->primFilho, depth + 1);
printTree(root->proxIrmao, depth);
}
No *buscaNo(char nome[], No *raiz) {
if(raiz == NULL)
return NULL;
if(strcmp(raiz->nome, nome) == 0)
return raiz;
No *p = raiz->primFilho;
while(p) {
No *resp = buscaNo(nome, p);
if(resp)
return resp;
p = p->proxIrmao;
}
return NULL;
}
void insere(TipoRaiz *root, char *novoNo, char *localPai) {
No *pai = buscaNo(localPai, root->raiz);
if(!pai)
return;
No *inserido = CriaNovoNo(novoNo);
inserido->pai = pai;
if(pai->primFilho)
inserido->proxIrmao = pai->primFilho;
pai->primFilho = inserido;
contador++;
}
void removeNo(No *no) {
No *p = no->pai;
if(!p)
return;
if(p->primFilho == no)
p->primFilho = no->proxIrmao;
else {
No *q = p->primFilho;
for(; q->proxIrmao != no; q = q->proxIrmao);
q->proxIrmao = no->proxIrmao;
}
free(no);
}
void printCaminho(No* no) {
No* pilha[contador];
int top = -1;
while (no) {
pilha[++top] = no;
no = no->pai;
}
while(top >= 0)
printf("%s ", pilha[top--]->nome);
}
int main() {
TipoRaiz root;
inicializa(&root);
int n;
char nome[LEN+1];
char localPai[LEN+1];
char comando[COMMAND_LEN+1];
char buscado[LEN+1];
scanf("%d", &n);
scanf("%" str(LEN) "s", buscado);
getchar();
char line[COMMAND_LEN+2*LEN+1];
for(int i = 0; i < n; i++) {
if(!fgets(line, COMMAND_LEN+2*LEN+1, stdin)) {
printf("input missing\n");
return 1;
}
sscanf(line, "%" str(COMMAND_LEN) "s %" str(LEN) "s %" str(LEN) "s", comando, nome, localPai);
if(!strcmp(comando, "-a") )
insere(&root, nome, localPai);
else if(!strcmp(comando,"-r")) {
No *noParaRemover = buscaNo(nome, root.raiz);
removeNo(noParaRemover);
}
else if (!strcmp(comando, "-m")) {
if(buscaNo(localPai, root.raiz)) {
No *noParaMover = buscaNo(nome, root.raiz);
removeNo(noParaMover);
insere(&root, nome, localPai);
}
}
}
// used for debuging purposes printTree(root.raiz, 0);
No *buscadoNo = buscaNo(buscado, root.raiz);
if(buscadoNo) {
printCaminho(buscadoNo);
printf("\n");
} else
printf("Arquivo nao encontrado!\n");
return 0;
}
示例运行:
$ ./a.out < input_1.txt
\root \dir10 file8
$ ./a.out < input_2.txt
\root arq10