我正在尝试编写一个生成有序随机链表的程序。
问题是输出有时只有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;
}
}
答案 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)
有两个问题。
在lastPtr == NULL
时,您忘记将newPtr->nextPtr
设置为currPtr
。您需要无条件设置newPtr->nextPtr = currPtr
。
每次循环时,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;
}