C 递归添加有序元素
为什么我会在这段代码中出现分段错误C 递归添加有序元素,c,recursion,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;
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;
}
该错误可能是在*li为空的情况下发生的。实际上,您可以对它进行测试,但只有在检查
((*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
时也可能发生SEGFULT,如果*k为空,则会出现SEGFULT
请提供一个main或某个片段,在其中您实际调用inserord,并声明
li
和k
您可以用以下方法编写更简单的函数
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;
}
如果使用您的方法,那么函数可以按以下方式编写(我使用自己的变量名,因为这对我来说很容易)
或者,如果希望使用第三个参数(如指向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 );
}
如果要在堆栈展开时重建列表,则必须返回一个值(node);插入错误(&list,4,&k);-->列表不是空的,只有kSo什么是
&list
?是指向结构的指针,k和list是指向结构的指针请举例说明传递到该函数的Lint
,以及它包含的内容,以便有人可以在需要时运行它并重现问题。此外,如果“这样我可以将旧结构与新结构联系起来,将新结构与新结构联系起来”是主要目标,那么您可能需要重新考虑您的方法。递归的好处是它将返回到第i个调用,这就是你如何将新旧链接的方式。不幸的是,他们似乎知道*li
*不是null
?它不是null。事实上,代码仍然会导致分段错误。我编辑了答案,添加了关于(*k)->下一步的部分。感谢您提供的主要信息。我现在正在查看它。@clement\u frndz如果函数通过条件if(*li==NULL)立即退出,您将如何在空列表中插入新值{return;?@VladfromMoscow确实,我的解决方案不提供此功能,但op的也不提供此功能。我对您的解决方案进行了优化,它实际上似乎符合op的需要。但请注意否定,li->value>x!(li->value<=x)。lldb告诉我您的程序在这一行上收到了SEGFULT:if(aux->next==NULL)在你的插入函数中,做得很好!非常有意义。虽然我想知道我的代码中发生了什么,但我觉得它很令人沮丧。但是我想有时候最好绕过一个问题,放开旧的解决方案。注意:考虑<代码>;。毫无疑问,要求的大小正确,信息隐藏更好,维护更容易。
#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
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 );