递归添加有序元素

时间:2015-05-22 17:47:38

标签: c recursion

为什么我会在此代码中出现分段错误?

void inserord(Lint *li, int x, Lint *k){

    if(((*li)->value) > x){
        Lint New;
        New = (Lint) calloc(1,sizeof(Nodo));
        New->value= x;
        New->next = (*li);
        (*k)->next = New;
        return;

    }else if(*li == NULL){
        return;
    }
    *k = *li;
    inserord( &((*li)->next), x, &(*k));
}

问题似乎是当我制作* k = * li时,它们是相同类型的指针,Lint。

这是数据结构:

typedef struct slist *Lint;

typedef struct slist {
    int value;
    Lint next;
} Nodo;

* k上的想法是将前一个节点传递给下一个递归调用,因此我可以将这个旧结构链接到新结构,将新结构链接到下一个。

编辑:

这是完整的代码:

typedef struct slist *Lint;

typedef struct slist {
    int value;
    Lint next;
} Nodo;

void inserord(Lint *li, int x, Lint *k){
    if(((*li)->value) > x){
        Lint New;
        New = (Lint) calloc(1,sizeof(Nodo));
        New->value= x;
        New->next = (*li);
        (*k)->next = New;
        return;

    }else if(*li == NULL){
        return;
    }
    *k = *li;
    inserord( &((*li)->next), x, &(*k));
}

void insertend(Lint *l, int x){
    Lint new, aux;

    new = (Lint) calloc(1,sizeof(Nodo));
    new->value = x;
    new->next = NULL;

    if(*l==NULL){
        *l=new;
        return;
    }
    else
    {
        for(aux=*l; aux!=NULL ; aux = aux->next){
            if(aux->next == NULL){
                aux->next = new;
                return;
            }
        }
    }
}

int main(){
    Lint listinha;

    printf("\n");

    insertend(&listinha, 1);
    insertend(&listinha, 2);
    insertend(&listinha, 3);
    insertend(&listinha, 4);
    insertend(&listinha, 5);
    insertend(&listinha, 7);

    listVal(&listinha);

    Lint k = NULL;

    inserord(&listinha, 4, &k);

    listVal(&listinha);

    return 0;
} 

2 个答案:

答案 0 :(得分:3)

您可以通过以下方式更简单地编写函数

Lint inserord( Lint li, int x )
{
    if ( ( li == NULL ) || !( li->value < x ) )
    {
        Lint new_li = malloc( sizeof( Nodo ) );
        new_li->value = x;
        new_li->next = li;

        return new_li;
    }

    li->next = inserord( li->next, x );

    return li;
}

并将其称为

Lint listinha = NULL;

listinha = inserord( listinha, 1 );

如果要使用你的方法,那么函数可以用以下方式编写(我使用自己的变量名,因为它对我来说很容易)

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

struct Nodo
{
    int value;
    struct Nodo *next;
};

void inserord( struct Nodo **current, int x, struct Nodo **prev )
{
    if ( ( *current == NULL ) || !( ( *current )->value < x ) )
    {
        struct Nodo *nodo = malloc( sizeof( struct Nodo ) );

        nodo->value = x;
        nodo->next = *current;

        if ( *prev == *current ) *current = nodo;
        else ( *prev )->next = nodo;

        return;
    }

    prev = current;
    current = &( *current )->next;

    inserord( current, x, prev );
}

void display( struct Nodo *current )
{
    for ( ; current != NULL; current = current->next )
    {
        printf( "%d ", current->value );
    }
}

int main(void) 
{
    struct Nodo *head = NULL;

    for ( int i = 10; i != 0;  ) inserord( &head, --i, &head );

    display( head );
    printf( "\n" );

    return 0;
}

程序输出

0 1 2 3 4 5 6 7 8 9 

或者如果你想用第三个参数调用它,比如指向NULL的指针,那么函数可能看起来像

void inserord( struct Nodo **current, int x, struct Nodo **prev )
{
    if ( ( *current == NULL ) || !( ( *current )->value < x ) )
    {
        struct Nodo *nodo = malloc( sizeof( struct Nodo ) );

        nodo->value = x;
        nodo->next = *current;

        if ( *prev == NULL ) *current = nodo;
            //   ^^^^^^^^^^^^^ 
        else ( *prev )->next = nodo;

        return;
    }

    prev = current;
    current = &( *current )->next;

    inserord( current, x, prev );
}

并被称为

struct Nodo *head = NULL;
struct Nodo *prev = NULL;


for ( int i = 10; i != 0;  ) inserord( &head, --i, &prev );

答案 1 :(得分:1)

错误可能是这样的情况* li是NULL。确实,你测试了它,但是只有在检查((*li)->value) > x)之后才会进行测试,这将会扩展到(NULL->value > x),这会导致段错误。

你需要做的只是交换if / else if,如下所示:

void inserord(Lint *li, int x, Lint *k){

/* This check must be done before attempting any other attempt to dereference (*li) */
if(*li == NULL){
    return;
}
else if(((*li)->value) > x){
    Lint New;
    New = (Lint) calloc(1,sizeof(Nodo));
    New->value= x;
    New->next = (*li);
    (*k)->next = New;
    return;

}
*k = *li;
inserord( &((*li)->next), x, &(*k));

}

尝试访问(*k)->next时也可能发生Segfault,如果* k为NULL,则会出现段错误。

请提供一个主要或一些片段,您实际上会在lik的声明中打电话。