试图生成有序链接列表的意外输出

时间:2019-01-22 15:58:15

标签: c linked-list

我正在尝试编写一个生成有序随机链表的程序。 问题是输出有时只有4个数字,有时是 无限的数字序列。我认为问题出在gen函数中,我该如何解决?

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 5

struct node{
    int v;
    struct node *nextPtr;
};

typedef struct node Node;
typedef Node *NodePtr;

void gen(NodePtr *startPtr);
void print(NodePtr start);

int main()
{
    NodePtr startPtr;
    startPtr = NULL;
    gen(&startPtr);
    print(startPtr);
    return 0;
}

void gen(NodePtr *startPtr)
{
    NodePtr currPtr, lastPtr, newPtr;
    int r;
    lastPtr = NULL;
    srand(time(NULL));


    for(int i = 0; i < N; i++){
        currPtr = *startPtr;
        r = rand()%101;
        while(currPtr != NULL && r > currPtr->v){
            lastPtr = currPtr;
            currPtr = currPtr->nextPtr;
        }
        newPtr = malloc(sizeof(Node));
        newPtr->v = r;
        newPtr->nextPtr = NULL;
        if(lastPtr == NULL){
            *startPtr = newPtr;
        }
        else{
            lastPtr->nextPtr = newPtr;
            newPtr->nextPtr = currPtr;
        }
    }
}

void print(NodePtr start)
{
    while(start != NULL){
        printf("%d ", start->v);
        start = start->nextPtr;
    }
}

3 个答案:

答案 0 :(得分:3)

lastPtr必须在for循环中初始化为null。

&& r > currPtr->v循环的第二次(3rd ...)迭代中考虑for为假。考虑到在先前的迭代中,while循环执行了一次或多次,因此lastPtr有一个值。

然后在&& r > currPtr->v为假的此迭代中,lastPtr的旧值将在else部分中使用,该值应为null。

所以:

    for(int i = 0; i < N; i++){
        lastPtr = NULL;
        currPtr = *startPtr;

...然后我在调试器中运行它,还发现:

    newPtr = malloc(sizeof(Node));
    newPtr->v = r;
    newPtr->nextPtr = currPtr;     // set it here
    if(lastPtr == NULL){
        *startPtr = newPtr;        // because here it is needed too
    }
    else{
        lastPtr->nextPtr = newPtr; // and no lomger needed here
    }

我发现的情况是rand()返回零并且必须在前面插入新节点。

答案 1 :(得分:0)

有两个问题。

  1. lastPtr == NULL时,您忘记将newPtr->nextPtr设置为currPtr。您需要无条件设置newPtr->nextPtr = currPtr

  2. 每次循环时,lastPtr变量都需要重新初始化为NULL

原始代码:

    for(int i = 0; i < N; i++){
        currPtr = *startPtr;
        r = rand()%101;
        while(currPtr != NULL && r > currPtr->v){
            lastPtr = currPtr;
            currPtr = currPtr->nextPtr;
        }
        newPtr = malloc(sizeof(Node));
        newPtr->v = r;
        newPtr->nextPtr = NULL;
        if(lastPtr == NULL){
            *startPtr = newPtr;
        }
        else{
            lastPtr->nextPtr = newPtr;
            newPtr->nextPtr = currPtr;
        }
    }

新代码:

    for(int i = 0; i < N; i++){
        currPtr = *startPtr;
        lastPtr = NULL; // <-- (re-)initialize lastPtr
        r = rand()%101;
        while(currPtr != NULL && r > currPtr->v){
            lastPtr = currPtr;
            currPtr = currPtr->nextPtr;
        }
        newPtr = malloc(sizeof(Node));
        newPtr->v = r;
        if(lastPtr == NULL){
            *startPtr = newPtr;
        }
        else{
            lastPtr->nextPtr = newPtr;
        }
        newPtr->nextPtr = currPtr; // <<-- set newPtr->nextPtr unconditionally
    }

更强大的解决方案还应检查malloc的结果。

答案 2 :(得分:-1)

您的代码毫无用处。而不是在每次迭代时都遍历列表,而使用头和尾指针。如果需要排序,则可以首先对值数组进行排序。

int comp( const void* a, const void* b)
{
     int a_int = * ( (int*) a );
     int b_int = * ( (int*) b );   
     if ( a_int == b_int ) return 0;
     else if ( a_int < b_int ) return -1;
     else return 1;
}

void gen(NodePtr *startPtr)
{
    NodePtr head, tail;
    int a[N] ;
    for(int i = 1; i < N; i++)
      a[i]=rand()%101;
    qsort(a,N,sizeof(N),comp);

    int i=0;
    // first node
    head = malloc(sizeof(Node));
    head->nextPtr=NULL;
    head->v=a[i];
    tail=head;        
    for(i = 1; i < N; i++){
      tail->nextPtr= malloc(sizeof(Node));
      tail=tail->nextPtr;
      tail->v=a[i];
      tail->nextPtr=NULL;
    }
    *startPtr=head;
}