当我尝试从链接列表中删除元素时,出现分段错误
When I try the erase the element from the Linked List, a get a segmentation fault
我是初学者,正在尝试学习数据结构。我写了一段代码,从链表中删除一个元素。如果该元素已经存在于列表中,则在编译和 运行 期间不会出现问题。但是,当我尝试删除列表中不存在的元素时,即使我已经对这种情况进行了编码,也会发生分段错误。你能看一看并帮助我吗?
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int x;
struct node *next;
}node;
void addElement(node *r, int x)
{
for(; r->next!=NULL; r=r->next);
r->next=(node*)malloc(sizeof(node));
r->next->x=x;
r->next->next=NULL;
}
node* add_Element_inorder(node *r, int x)
{
if(r==NULL)
{
r=(node*)malloc(sizeof(node));
r->next=NULL;
r->x=x;
return r;
}
if(r->x>x)
{
node*tmp=(node*)malloc(sizeof(node));
tmp -> x = x;
tmp->next=r;
return tmp;
}
node *iter=r;
while(iter->next!=NULL && iter->next->x < x)
{
iter=iter->next;
}
node*tmp=(node*)malloc(sizeof(node));
tmp->next = iter->next;
iter->next=tmp;
tmp->x=x;
return r;
}
void print_Linked_L(node *r)
{
node* iter = r;
printf("%d ", iter->x);
iter=iter->next;
while(iter != NULL)
{
printf("%d ", iter->x);
iter=iter->next;
}
}
node* erase_Element(node *r, int x)
{
node*iter=r;
if(iter->x == x)
{
r=r->next;
free(iter);
return r;
}
while(iter->next->x != x && iter->next!=NULL)
{
iter=iter->next;
}
if(iter->next==NULL)
{
printf("Number does not exist.");
return r;
}
node *temp=iter->next;
iter->next=iter->next->next;
free(temp);
return r;
}
int main()
{
node *root = (node*)malloc(sizeof(node));
root=NULL;
root= add_Element_inorder(root, 400);
root= add_Element_inorder(root, 40);
root= add_Element_inorder(root, 4);
root= add_Element_inorder(root, 450);
root= add_Element_inorder(root, 50);
node *iter=root;
print_Linked_L(root);
root =erase_Element(root,45);
printf("\n");
print_Linked_L(root);
return 0;
}
while(iter->next->x != x && iter->next!=NULL)
在此代码中首先 运行 iter->next->x 然后 iter->next!=NULL
您取消引用 null。
解决方案是:
while(iter->next!=NULL && iter->next->x != x )
其实所有函数都不正确。
例如在这个函数中
void addElement(node *r, int x)
{
for(; r->next!=NULL; r=r->next);
r->next=(node*)malloc(sizeof(node));
r->next->x=x;
r->next->next=NULL;
}
不检查 t 是否等于 NULL。该函数至少应定义为
node * addElement( node *head, int x )
{
node *new_node = malloc( sizeof( node ) );
new_node->x = x;
if ( head == NULL )
{
new_node->next = head;
head = new_node;
}
else
{
node *current = head;
while ( current->next != NULL ) current = current->next;
new_node->next = NULL;
current->next = new_node;
}
return head;
}
函数add_Element_inorder
中有两处重复代码。函数可以定义的更简单。
node * add_Element_inorder( node *head, int x)
{
node *new_node = malloc( sizeof( node ) );
new_node->x = x;
if ( head == NULL || x < head->x )
{
new_node->next = head;
head = new_node;
}
else
{
node *current = head;
while ( current->next != NULL && !( x < current->next->x ) )
{
current = current->next;
}
new_node->next = current->next;
current->next = new_node;
}
return head;
}
当指向头节点的指针等于 NULL 时,函数 print_Linked_L
可以为空列表调用未定义的行为。
void print_Linked_L(node *r)
{
node* iter = r;
printf("%d ", iter->x);
//...
函数可以这样定义
void print_Linked_L( const node *head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ", head->x );
}
puts( "null" );
}
由于 while 语句中的条件顺序不正确,当没有具有目标值的节点时,函数 erase_Element
再次可以调用未定义的行为
while(iter->next->x != x && iter->next!=NULL)
也就是说首先你需要检查是否iter->next != NULL
然后才检查它的值是否不等于x。
函数可以这样定义
node * erase_Element( node *head, int x )
{
if ( head != NULL )
{
if ( head->x == x )
{
node *tmp = head;
head = head->next;
free( tmp );
}
else
{
node *current = head;
while ( current->next != NULL && current->next->x != x )
{
current = current->next;
}
if ( current->next != NULL )
{
node *tmp = current->next;
current->next = current->next->next;
free( tmp );
}
else
{
printf( "Number %d does not exist in the list.\n", x );
}
}
}
return head;
}
函数 main 以内存泄漏开始
int main()
{
node *root = (node*)malloc(sizeof(node));
root=NULL;
首先分配内存,然后由于覆盖指针 root 而立即返回地址丢失。
这是一个展示更新函数定义的演示程序。
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int x;
struct node *next;
} node;
node * addElement( node *head, int x)
{
node *new_node = malloc( sizeof( node ) );
new_node->x = x;
if ( head == NULL )
{
new_node->next = head;
head = new_node;
}
else
{
node *current = head;
while ( current->next != NULL ) current = current->next;
new_node->next = NULL;
current->next = new_node;
}
return head;
}
node * add_Element_inorder( node *head, int x)
{
node *new_node = malloc( sizeof( node ) );
new_node->x = x;
if ( head == NULL || x < head->x )
{
new_node->next = head;
head = new_node;
}
else
{
node *current = head;
while ( current->next != NULL && !( x < current->next->x ) )
{
current = current->next;
}
new_node->next = current->next;
current->next = new_node;
}
return head;
}
void print_Linked_L( const node *head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ", head->x );
}
puts( "null" );
}
node * erase_Element( node *head, int x )
{
if ( head != NULL )
{
if ( head->x == x )
{
node *tmp = head;
head = head->next;
free( tmp );
}
else
{
node *current = head;
while ( current->next != NULL && current->next->x != x )
{
current = current->next;
}
if ( current->next != NULL )
{
node *tmp = current->next;
current->next = current->next->next;
free( tmp );
}
else
{
printf( "Number %d does not exist in the list.\n", x );
}
}
}
return head;
}
int main(void)
{
node *root = NULL;
root = add_Element_inorder( root, 400 );
root = add_Element_inorder( root, 40 );
root = add_Element_inorder( root, 4 );
root = add_Element_inorder( root, 450 );
root = add_Element_inorder( root, 50 );
print_Linked_L( root );
root = erase_Element( root, 45 );
print_Linked_L(root);
root = erase_Element( root, 400 );
print_Linked_L(root);
root = erase_Element( root, 40 );
print_Linked_L(root);
root = erase_Element( root, 4 );
print_Linked_L(root);
root = erase_Element( root, 450 );
print_Linked_L(root);
root = erase_Element( root, 50 );
print_Linked_L(root);
return 0;
}
程序输出为
4 -> 40 -> 50 -> 400 -> 450 -> null
Number 45 does not exist in the list.
4 -> 40 -> 50 -> 400 -> 450 -> null
4 -> 40 -> 50 -> 450 -> null
4 -> 50 -> 450 -> null
50 -> 450 -> null
50 -> null
null
我是初学者,正在尝试学习数据结构。我写了一段代码,从链表中删除一个元素。如果该元素已经存在于列表中,则在编译和 运行 期间不会出现问题。但是,当我尝试删除列表中不存在的元素时,即使我已经对这种情况进行了编码,也会发生分段错误。你能看一看并帮助我吗?
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int x;
struct node *next;
}node;
void addElement(node *r, int x)
{
for(; r->next!=NULL; r=r->next);
r->next=(node*)malloc(sizeof(node));
r->next->x=x;
r->next->next=NULL;
}
node* add_Element_inorder(node *r, int x)
{
if(r==NULL)
{
r=(node*)malloc(sizeof(node));
r->next=NULL;
r->x=x;
return r;
}
if(r->x>x)
{
node*tmp=(node*)malloc(sizeof(node));
tmp -> x = x;
tmp->next=r;
return tmp;
}
node *iter=r;
while(iter->next!=NULL && iter->next->x < x)
{
iter=iter->next;
}
node*tmp=(node*)malloc(sizeof(node));
tmp->next = iter->next;
iter->next=tmp;
tmp->x=x;
return r;
}
void print_Linked_L(node *r)
{
node* iter = r;
printf("%d ", iter->x);
iter=iter->next;
while(iter != NULL)
{
printf("%d ", iter->x);
iter=iter->next;
}
}
node* erase_Element(node *r, int x)
{
node*iter=r;
if(iter->x == x)
{
r=r->next;
free(iter);
return r;
}
while(iter->next->x != x && iter->next!=NULL)
{
iter=iter->next;
}
if(iter->next==NULL)
{
printf("Number does not exist.");
return r;
}
node *temp=iter->next;
iter->next=iter->next->next;
free(temp);
return r;
}
int main()
{
node *root = (node*)malloc(sizeof(node));
root=NULL;
root= add_Element_inorder(root, 400);
root= add_Element_inorder(root, 40);
root= add_Element_inorder(root, 4);
root= add_Element_inorder(root, 450);
root= add_Element_inorder(root, 50);
node *iter=root;
print_Linked_L(root);
root =erase_Element(root,45);
printf("\n");
print_Linked_L(root);
return 0;
}
while(iter->next->x != x && iter->next!=NULL)
在此代码中首先 运行 iter->next->x 然后 iter->next!=NULL 您取消引用 null。 解决方案是:
while(iter->next!=NULL && iter->next->x != x )
其实所有函数都不正确。
例如在这个函数中
void addElement(node *r, int x)
{
for(; r->next!=NULL; r=r->next);
r->next=(node*)malloc(sizeof(node));
r->next->x=x;
r->next->next=NULL;
}
不检查 t 是否等于 NULL。该函数至少应定义为
node * addElement( node *head, int x )
{
node *new_node = malloc( sizeof( node ) );
new_node->x = x;
if ( head == NULL )
{
new_node->next = head;
head = new_node;
}
else
{
node *current = head;
while ( current->next != NULL ) current = current->next;
new_node->next = NULL;
current->next = new_node;
}
return head;
}
函数add_Element_inorder
中有两处重复代码。函数可以定义的更简单。
node * add_Element_inorder( node *head, int x)
{
node *new_node = malloc( sizeof( node ) );
new_node->x = x;
if ( head == NULL || x < head->x )
{
new_node->next = head;
head = new_node;
}
else
{
node *current = head;
while ( current->next != NULL && !( x < current->next->x ) )
{
current = current->next;
}
new_node->next = current->next;
current->next = new_node;
}
return head;
}
当指向头节点的指针等于 NULL 时,函数 print_Linked_L
可以为空列表调用未定义的行为。
void print_Linked_L(node *r)
{
node* iter = r;
printf("%d ", iter->x);
//...
函数可以这样定义
void print_Linked_L( const node *head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ", head->x );
}
puts( "null" );
}
由于 while 语句中的条件顺序不正确,当没有具有目标值的节点时,函数 erase_Element
再次可以调用未定义的行为
while(iter->next->x != x && iter->next!=NULL)
也就是说首先你需要检查是否iter->next != NULL
然后才检查它的值是否不等于x。
函数可以这样定义
node * erase_Element( node *head, int x )
{
if ( head != NULL )
{
if ( head->x == x )
{
node *tmp = head;
head = head->next;
free( tmp );
}
else
{
node *current = head;
while ( current->next != NULL && current->next->x != x )
{
current = current->next;
}
if ( current->next != NULL )
{
node *tmp = current->next;
current->next = current->next->next;
free( tmp );
}
else
{
printf( "Number %d does not exist in the list.\n", x );
}
}
}
return head;
}
函数 main 以内存泄漏开始
int main()
{
node *root = (node*)malloc(sizeof(node));
root=NULL;
首先分配内存,然后由于覆盖指针 root 而立即返回地址丢失。
这是一个展示更新函数定义的演示程序。
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int x;
struct node *next;
} node;
node * addElement( node *head, int x)
{
node *new_node = malloc( sizeof( node ) );
new_node->x = x;
if ( head == NULL )
{
new_node->next = head;
head = new_node;
}
else
{
node *current = head;
while ( current->next != NULL ) current = current->next;
new_node->next = NULL;
current->next = new_node;
}
return head;
}
node * add_Element_inorder( node *head, int x)
{
node *new_node = malloc( sizeof( node ) );
new_node->x = x;
if ( head == NULL || x < head->x )
{
new_node->next = head;
head = new_node;
}
else
{
node *current = head;
while ( current->next != NULL && !( x < current->next->x ) )
{
current = current->next;
}
new_node->next = current->next;
current->next = new_node;
}
return head;
}
void print_Linked_L( const node *head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ", head->x );
}
puts( "null" );
}
node * erase_Element( node *head, int x )
{
if ( head != NULL )
{
if ( head->x == x )
{
node *tmp = head;
head = head->next;
free( tmp );
}
else
{
node *current = head;
while ( current->next != NULL && current->next->x != x )
{
current = current->next;
}
if ( current->next != NULL )
{
node *tmp = current->next;
current->next = current->next->next;
free( tmp );
}
else
{
printf( "Number %d does not exist in the list.\n", x );
}
}
}
return head;
}
int main(void)
{
node *root = NULL;
root = add_Element_inorder( root, 400 );
root = add_Element_inorder( root, 40 );
root = add_Element_inorder( root, 4 );
root = add_Element_inorder( root, 450 );
root = add_Element_inorder( root, 50 );
print_Linked_L( root );
root = erase_Element( root, 45 );
print_Linked_L(root);
root = erase_Element( root, 400 );
print_Linked_L(root);
root = erase_Element( root, 40 );
print_Linked_L(root);
root = erase_Element( root, 4 );
print_Linked_L(root);
root = erase_Element( root, 450 );
print_Linked_L(root);
root = erase_Element( root, 50 );
print_Linked_L(root);
return 0;
}
程序输出为
4 -> 40 -> 50 -> 400 -> 450 -> null
Number 45 does not exist in the list.
4 -> 40 -> 50 -> 400 -> 450 -> null
4 -> 40 -> 50 -> 450 -> null
4 -> 50 -> 450 -> null
50 -> 450 -> null
50 -> null
null