C 在链表末尾插入
我编写了一个函数,用于在链表末尾插入一个节点。当我运行程序,调用这个函数时,程序停止工作 以下是函数:C 在链表末尾插入,c,linked-list,C,Linked List,我编写了一个函数,用于在链表末尾插入一个节点。当我运行程序,调用这个函数时,程序停止工作 以下是函数: void insert(node **head, int x) { node *new = malloc(sizeof(node)); new->data = x; new->next = NULL; node *temp = *head; while (temp != NULL) { temp = temp->ne
void insert(node **head, int x) {
node *new = malloc(sizeof(node));
new->data = x;
new->next = NULL;
node *temp = *head;
while (temp != NULL) {
temp = temp->next;
}
temp->next = new;
}
谁能告诉我哪里出了问题
while
循环终止时temp
为NULL
。因此temp->next
将生成分段错误
您应该使用while(temp->next!=NULL)
而不是while(temp->next!=NULL)
head
为NULL
,该怎么办?(空链接列表)为此,请检查
head
是否为NULL
malloc
失败怎么办
void insert(node **head, int x)
{
node *new = (node *)malloc(sizeof(node));
if(!new)
{
printf("Memory allocation failed!\n");
exit(1);
}
new->data = x;
new->next = NULL;
node *temp = *head;
if(!temp)
*head = new;
else
{
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = new;
}
return ;
}
while
循环终止时temp
为NULL
。因此temp->next
将生成分段错误
您应该使用while(temp->next!=NULL)
而不是while(temp->next!=NULL)
head
为NULL
,该怎么办?(空链接列表)为此,请检查
head
是否为NULL
malloc
失败怎么办
void insert(node **head, int x)
{
node *new = (node *)malloc(sizeof(node));
if(!new)
{
printf("Memory allocation failed!\n");
exit(1);
}
new->data = x;
new->next = NULL;
node *temp = *head;
if(!temp)
*head = new;
else
{
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = new;
}
return ;
}
使用
节点**
进行迭代。因此,列表是否为空并不重要。迭代,直到找到其next
为NULL
的节点。您可以按目标分配内存
void insert( node **head, int x){
node **ptr_new = head;
while( *ptr_new != NULL ){
ptr_new = &((*ptr_new)->next);
}
// now temp refers either to head or to next of the last node.
*ptr_new = malloc( sizeof(node) );
if ( *ptr_new != NULL )
{
(*ptr_new)->next = NULL;
(*ptr_new)->data = x;
}
}
与原始代码不同,您有一个指向存储新节点地址的指针的指针。在原始版本中,当temp
不是NULL
时,您进行了迭代
while (temp != NULL) {
temp = temp->next;
}
在此之后
而循环temp==NULL
,因为这是循环的终止条件。因此,您的程序在这里停止工作temp->next=new代码>使用节点**
进行迭代。因此,列表是否为空并不重要。迭代,直到找到其next
为NULL
的节点。您可以按目标分配内存
void insert( node **head, int x){
node **ptr_new = head;
while( *ptr_new != NULL ){
ptr_new = &((*ptr_new)->next);
}
// now temp refers either to head or to next of the last node.
*ptr_new = malloc( sizeof(node) );
if ( *ptr_new != NULL )
{
(*ptr_new)->next = NULL;
(*ptr_new)->data = x;
}
}
与原始代码不同,您有一个指向存储新节点地址的指针的指针。在原始版本中,当temp
不是NULL
时,您进行了迭代
while (temp != NULL) {
temp = temp->next;
}
在此之后而循环temp==NULL
,因为这是循环的终止条件。因此,您的程序在这里停止工作temp->next=new代码>您的代码有两个问题:
temp
指针被推到列表的末尾,直到它变为NULL
,此时将新指针存储到它的下一个成员并尝试调用未定义的行为(系统上的分段错误
)为时已晚
- 如果列表为空,则即使在
temp->next==NULL
时停止循环,也无法以这种方式存储新项
<> P>在C代码中避免使用C++关键字来命名变量,因为如果需要的话,这会使代码迁移到C++更困难。
此外,如果测试malloc
是否失败,并在失败时返回指向新节点的指针或NULL
,则更为正确
以下是更正的版本:
node *insert(node **head, int x) {
node *new_node = malloc(sizeof(node));
if (new_node != NULL) {
new_node->data = x;
new_node->next = NULL;
node *temp = *head;
if (temp == NULL) {
*head = new_node;
} else {
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = new_node;
}
}
return new_node;
}
您还可以使用指向指针的指针来迭代列表:它稍微复杂一些,但比较短,因为您只有一个测试来找到存储新
指针的位置:
node *insert(node **head, int x) {
node *new_node = malloc(sizeof(node));
if (new_node != NULL) {
new_node->data = x;
new_node->next = NULL;
node **np = head;
while (*np) {
np = &(*np)->next;
}
*np = new_node;
}
return new_node;
}
您的代码有两个问题:
temp
指针被推到列表的末尾,直到它变为NULL
,此时将新指针存储到它的下一个成员并尝试调用未定义的行为(系统上的分段错误
)为时已晚
- 如果列表为空,则即使在
temp->next==NULL
时停止循环,也无法以这种方式存储新项
<> P>在C代码中避免使用C++关键字来命名变量,因为如果需要的话,这会使代码迁移到C++更困难。
此外,如果测试malloc
是否失败,并在失败时返回指向新节点的指针或NULL
,则更为正确
以下是更正的版本:
node *insert(node **head, int x) {
node *new_node = malloc(sizeof(node));
if (new_node != NULL) {
new_node->data = x;
new_node->next = NULL;
node *temp = *head;
if (temp == NULL) {
*head = new_node;
} else {
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = new_node;
}
}
return new_node;
}
您还可以使用指向指针的指针来迭代列表:它稍微复杂一些,但比较短,因为您只有一个测试来找到存储新
指针的位置:
node *insert(node **head, int x) {
node *new_node = malloc(sizeof(node));
if (new_node != NULL) {
new_node->data = x;
new_node->next = NULL;
node **np = head;
while (*np) {
np = &(*np)->next;
}
*np = new_node;
}
return new_node;
}
您还应该检查malloc()
是否成功,但这项技术很有趣。史蒂夫·马奎尔(Steve Maguire)也用“编写可靠的代码”来描述它。它的优点是避免了特殊情况,因此有助于减少代码膨胀。您还应该检查malloc()
是否成功,但这项技术很有趣。史蒂夫·马奎尔(Steve Maguire)也用“编写可靠的代码”来描述它。它的优点是避免了特殊情况,因此有助于减少代码膨胀。欢迎使用堆栈溢出。一般来说,“只是停止工作”并不是对问题的适当描述。它是否进入无限循环;它是否因分段故障或等效故障而崩溃;还是别的什么?一个需要考虑的问题是“调试器显示了什么?”另一个是“打印语句在添加到代码中时显示了什么?”这些技术中的一个或另一个是解决错误的必要步骤。考虑创建一个MCVE()欢迎堆栈溢出。一般来说,“只是停止工作”并不是对问题的适当描述。它是否进入无限循环;它是否因分段故障或等效故障而崩溃;还是别的什么?其中一个要考虑的问题是“调试器显示了什么?”另一个是“打印语句在添加时显示了什么?”