C函数,使用另一个链接列表中的数字“可被3整除”创建链接列表

时间:2019-05-16 23:03:05

标签: c recursion linked-list

首先,我需要创建并显示一个以数字1000结尾的列表。效果很好。

然后,我想创建一个仅在第一个列表中被3整除的数字的列表,但这不起作用。

最糟糕的是,它甚至没有告诉我发生了什么事。它只是在执行中产生错误,但控制台什么也没说。

我将非常感谢您的帮助。

我尽力了。

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

#define CANTIDAD_NUMEROS 13
#define CANTIDAD_NUMEROS2 6
#define DESDE 1
#define HASTA 10

typedef struct lista{
    int num;
    struct lista *sig;
}nodo;


void crear (nodo *pt, int, int);
void crear2 (nodo *pt, int, nodo *pt2);
void mostrar(nodo *pt);

int main()
{
    int i=0;
    int t=0;

    nodo *prin;
    nodo *prin2;

    prin=(nodo*)malloc(sizeof(nodo));
    prin2=(nodo*)malloc(sizeof(nodo));

    crear(prin,i, t); //creates first list
    mostrar (prin); //shows first list
    crear2(prin,i, prin2); //gets 'divisible by 3' numbers
    mostrar(prin2); // shows second list

    return 0;
}

//creates list
void crear (nodo *registro, int cont, int t)
{

    scanf("%d", &t);
    registro->num = t;

    if (registro->num == 1000) 
        registro->sig=NULL;
    else
    {
        registro->sig=(nodo*)malloc(sizeof(nodo));
        cont++;
        crear (registro->sig,cont, t);
    }
    return;
}
//shows list
void mostrar (nodo *registro)
{
    if (registro->sig !=NULL)
    {
        printf ("%d\n",registro->num);
        mostrar (registro->sig);
    }else{
        printf("%d\n",registro->num);
    }
    return;
}
//creates second list with only numbers that are divisible by 3
void crear2 (nodo *registro, int cont, nodo *registroNuevo)
{
    if ((registro->num % 3) == 0){
        registroNuevo->num = registro->num;
        registroNuevo->sig = (nodo*)malloc(sizeof(nodo));
    }

    if(registro->sig != NULL){
        crear2(registro->sig,cont, registroNuevo->sig);
    }else{
        return;
    }

}

我希望显示第一个列表(正在发生),并且显示第二个列表,其中的数字可以被3整除,这不会发生。

2 个答案:

答案 0 :(得分:1)

void crear2 (nodo *registro, int cont, nodo *registroNuevo) {

   if ((registro->num % 3) == 0) {
       registroNuevo->num = registro->num;
       registroNuevo->sig = (nodo*)malloc(sizeof(nodo));
       if (registro->sig != NULL)
           crear2(registro->sig, cont, registroNuevo->sig);
   }
   else {
       if (registro->sig != NULL)
           crear2(registro->sig, cont, registroNuevo);
   }
}

这是我的方法,但是您在最后一次mostrar()调用中仍然得到最终的意外0;而且您仍然需要进行“免费”通话。我认为您应该避免递归调用,有更简单的方法可以做到。致敬。

答案 1 :(得分:0)

首先,我很佩服您对递归的奉献!

问题是在crear2中,registroNuevo->sig未初始化,这会导致段错误。我几乎总是通过检查参数node是否为null来启动对递归链接数据结构进行操作的函数。如果是这样,我可以安全地继续使用该函数的主体。按照这种防止空值的逻辑,在registroNuevo的情况下,我们需要传递registro->num % 3 != 0节点而不接触它,并确保其所有字段都已初始化。

这是更正的功能:

void crear2(nodo *registro, int cont, nodo *registroNuevo)
{
    if (registro) {
        if (registro->num % 3 == 0) {
            registroNuevo->num = registro->num;
            registroNuevo->sig = NULL;

            if (registro->sig) {
                registroNuevo->sig = malloc(sizeof(nodo));
            }

            crear2(registro->sig, cont, registroNuevo->sig);
        }
        else {
            crear2(registro->sig, cont, registroNuevo);
        }
    }
}

尽管如此,由于一些原因,此功能仍不理想。首先,名称含糊不清,可以更好地描述行为。另外,如果没有可被三整除的项目,则在调用范围中有一个malloc ed节点,它永远不会被初始化,因此这方面有点脆弱。第三,即使有一个参数,它仍然感觉像是一个非常具体的函数,没有很多可重用性因素,可以在调用范围内迭代编写,例如:

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

typedef struct nodo
{
    int num;
    struct nodo *sig;
} nodo;

nodo *crear(nodo *registro, int num)
{
    nodo *n = malloc(sizeof(nodo));
    n->num = num;
    n->sig = registro;
    return n;
}

void mostrar(nodo *registro)
{
    if (registro)
    {
        printf("%d->", registro->num);
        mostrar(registro->sig);
    }
    else puts("");
}

void free_lista(nodo *registro) 
{
    if (registro) 
    {
        free_lista(registro->sig);
        free(registro);
    }
}

int main()
{
    nodo *prin = NULL;
    nodo *prin_div_3 = NULL;

    for (int t; scanf("%d", &t) && t != 1000;) 
    {
        prin = crear(prin, t);
    }

    nodo *tmp = prin;

    while (tmp)
    {
        if (tmp->num % 3 == 0) 
        {
            prin_div_3 = crear(prin_div_3, tmp->num);
        }

        tmp = tmp->sig;
    }

    mostrar(prin);
    mostrar(prin_div_3);
    free_lista(prin);
    free_lista(prin_div_3);
    return 0;
}

这不是完美的-没有尾部节点,添加到列表中并不理想,但是消除了悬空的头部,希望它显示了组织程序逻辑和功能的另一种方法。


其他几点:

  • 始终释放已分配的内存。您可以编写一个简单的递归例程来执行此操作,如上例所示,free_lista
  • 请考虑避免使用诸如31000这样的硬编码值的高度特定的功能。设置这些参数以最大化可重用性。
  • crear2从不使用cont成员,并且您有未使用的全局常量。清理它们是一个好主意,以帮助您弄清调试工作并减少视觉混乱。
  • No need以强制转换malloc的结果。
  • if (registro->sig !=NULL),因为函数的第一行将崩溃为null。您也不需要!= NULLif (registro) { ... }最清晰,可避免使用空参数。