我有一个双重链表,
struct node
{
int data;
struct node *prev;
struct node *next;
};
和我实施的deleteEnd
功能,
bool deleteEnd(struct node **head, int* value) {
if (*head == NULL) return false;
struct node* end = *head;
while (end->next != NULL) {
end = end->next;
}
if (end == *head) *head = NULL;
else end->prev->next = NULL;
*value = end->data;
free(end);
return true;
}
这给了我一个分段错误,但我无法弄清楚原因。此时,我的列表中有3个元素(1<->2<->5
)和5
应该被删除。
list.h
#pragma once
#include <stdbool.h>
/* doubly linked list structure */
struct node
{
int data;
struct node *prev;
struct node *next;
};
struct node* create(int value);
bool insertAtBeginning(struct node **head, int value);
bool insertAtEnd(struct node **head, int value);
bool insertAfter(struct node **head, int value, int preVal);
bool deleteBeginning(struct node **head, int* value);
bool deleteEnd(struct node **head, int* value);
bool deleteSpecific(struct node **head, int value);
void display(struct node *head);
list.c
#include "list.h"
#include <stdlib.h>
#include <stdio.h>
struct node* create(int value) {
struct node* n = malloc(sizeof(struct node));
if (n == NULL) return NULL;
n->data = value;
n->prev = NULL;
n->next = NULL;
return n;
}
bool insertAtBeginning(struct node **head, int value) {
struct node* old_head = *head;
*head = create(value);
if (*head == NULL) return false;
(*head)->next = old_head;
return true;
}
bool insertAtEnd(struct node **head, int value) {
// Get last node
struct node* last = *head;
while (last->next != NULL) {
last = last->next;
}
// Insert after
last->next = create(value);
if (last->next == NULL) return false;
else return true;
}
bool insertAfter(struct node **head, int value, int preVal) {
// Get previous
struct node* prev = *head;
while (prev->data != preVal && prev->next != NULL) {
prev = prev->next;
}
// Not founnd ?
if (prev->next == NULL && prev->data != preVal) return false;
// Insert in between
struct node* nxt = prev->next;
struct node* insert = create(value);
if (insert == NULL) return false;
prev->next = insert;
insert->next = nxt;
return true;
}
bool deleteBeginning(struct node **head, int* value) {
struct node* hd = *head;
*value = hd->data;
*head = (*head)->next;
free(hd);
return true;
}
bool deleteEnd(struct node **head, int* value) {
if (*head == NULL) return false;
struct node* end = *head;
while (end->next != NULL) {
end = end->next;
}
if (end == *head) *head = NULL;
else end->prev->next = NULL;
*value = end->data;
free(end);
return true;
}
bool deleteSpecific(struct node **head, int value) {
// Find node
struct node* n = *head;
while (n->data != value && n->next != NULL) {
n = n->next;
}
// Not found ?
if (n->next == NULL && n->data != value) return false;
// Deleting head ?
if (n == *head) {
*head = (*head)->next;
free(n);
}
// Delete in between
else {
struct node* nxt = n->next;
struct node* prev = n->prev;
prev->next = nxt;
free(n);
}
return true;
}
void display(struct node *head) {
if (head == NULL) {
printf("List is Empty!!!");
}
else {
printf("\nList elements are:\n");
do {
printf("%d ", head->data);
head = head->next;
}
while(head != NULL);
printf("\n\n");
}
}
的main.c
#include <stdio.h>
#include "list.h"
int main()
{
int value, preVal, retVal;
struct node *head = NULL;
/* insert data */
value = 2;
printf("insert %d %s\n", value, insertAtBeginning(&head, value) ? "OK":"NOK");
display(head);
value = 5;
printf("insert %d %s\n", value, insertAtEnd(&head, value) ? "OK":"NOK");
display(head); // printf("blabla");
value = 3;
printf("insert %d %s\n", value, insertAtBeginning(&head, value) ? "OK":"NOK");
display(head);
value = 3;
preVal = 0;
printf("insert %d after %d %s\n", value, preVal, insertAfter(&head, value, preVal) ? "OK":"NOK");
display(head);
value = 1;
preVal = 3;
printf("insert %d after %d %s\n", value, preVal, insertAfter(&head, value, preVal) ? "OK":"NOK");
display(head);
/* delete data */
retVal = deleteBeginning(&head, &value);
printf("delete %d %s\n", value, retVal ? "OK": "NOK");
display(head);
retVal = deleteEnd(&head, &value);
printf("delete %d %s\n", value, retVal ? "OK": "NOK");
display(head);
value = 3;
retVal = deleteSpecific(&head, value);
printf("delete %d %s\n", value, retVal ? "OK":"NOK");
display(head);
return 0;
}
答案 0 :(得分:1)
如果end等于head this statement
end->prev->next = NULL; // <- segfault
导致未定义的行为,因为end->prev
等于NULL;
我会按以下方式定义函数
bool deleteEnd(struct node **head, int *value )
{
bool success = *head != NULL;
if ( success )
{
while ( ( *head )->next != NULL ) head = &( *head )->next;
*value = ( *head )->data;
struct node *last = *head;
*head = NULL;
free( last );
}
return success;
}
编辑:显示其他代码后,至少已经看到这个函数
bool insertAtBeginning(struct node **head, int value) {
struct node* old_head = *head;
*head = create(value);
if (*head == NULL) return false;
(*head)->next = old_head;
return true;
}
错误,因为它未设置prev
的数据成员old_head
。
或在此功能
bool insertAtEnd(struct node **head, int value) {
// Get last node
struct node* last = *head;
while (last->next != NULL) {
last = last->next;
}
// Insert after
last->next = create(value);
if (last->next == NULL) return false;
else return true;
}
没有检查* head是否等于NULL。而且,新创建的节点的数据成员prev
也未正确设置。
这就是数据成员prev的值为NULL是函数deleteEnd
的错误工作的原因。
您应该修改所有功能。
答案 1 :(得分:0)
你必须检查end元素是否有前一个元素。如果没有,则不能将下一个元素写入前一个元素。
if语句缺少。
if (end->prev)
end->prev->next = NULL; // <- segfault