我查找双链表中最后一个元素的代码是抛出分段错误 我对编程很熟悉,我在路上学习C。我正在尝试构建一个全功能的双链表模块,但是在获取最后一个元素时,我得到了一个分割错误。
我的功能相同我查找双链表中最后一个元素的代码是抛出分段错误 我对编程很熟悉,我在路上学习C。我正在尝试构建一个全功能的双链表模块,但是在获取最后一个元素时,我得到了一个分割错误。,c,segmentation-fault,doubly-linked-list,C,Segmentation Fault,Doubly Linked List,我的功能相同 void get_last(struct Node *node) { if (node) { while (node->next) { node = node->next; } } printf("%d",node->prev->value); } 现在,每次我运行它时,它都会抛出一个分段错误,我无法成功地调试它,尽管我发现这在概念上是正确的,因为当循环结
void get_last(struct Node *node)
{
if (node)
{
while (node->next)
{
node = node->next;
}
}
printf("%d",node->prev->value);
}
现在,每次我运行它时,它都会抛出一个分段错误,我无法成功地调试它,尽管我发现这在概念上是正确的,因为当循环结束时,节点最终将指向NULL,我的代码将打印上一项的值。
如果我的观念错了,请纠正我。
谢谢
编辑:我在printf()
中使用了“%d”
,因为这些值在我创建的链接列表中是整数值
编辑1:以下是创建链表的代码:
void create_list(struct Node *node)
{
int i;
first.next=NULL;
first.prev=NULL;
node=&first;
for(i=1;i <=10;i++)
{
node->next=(struct Node *)malloc(sizeof(struct Node));
node->next->prev=node;
node=node->next;
node->value=rand()%20;
node->next=NULL;
}
}
void创建列表(结构节点*Node)
{
int i;
first.next=NULL;
第一,prev=NULL;
node=&first;
对于(i=1;i next=(结构节点*)malloc(sizeof(结构节点));
节点->下一步->上一步=节点;
节点=节点->下一步;
节点->值=rand()%20;
节点->下一步=空;
}
}
将printf语句移动到if(node)
块内,否则,如果使用空指针调用,则会出现保证segfault
接下来,这可能意味着打印列表中最后一个条目的值,而不是获取最后一个条目
从您的代码中,您选择在最后一个条目中将next
设置为NULL
(这可能意味着您在列表头中将prev
设置为NULL
)。如果这样,您就失去了双链接列表相对于单链接列表的主要优势之一(不必遍历列表以查找最后一项
相反,如果您有一个固定的“head”节点,并且在next
中最后一个项目指向它,并且head的prev
指向最后一个项目,那么您可以使用一条语句获取最后一个项目:
last = head.prev;
迭代(例如线性搜索)可以在节点->下一步==&head
时终止
但是,您的代码将按如下方式退出
- 如果列表为空(
),它将在node==NULL
printf
- 如果
为非空,但node
则假定node->next==null
,因此它将再次出现故障node->prev==null
- 如果列表中有一些条目,并且
正确终止,则只有当while
为节点->prev
时,它才会segfault(这表明您的错误也可能存在于NULL
方法中)添加
- 列表中的节点由两个指针(
和next
)和一个有效负载组成prev
- 每个列表都有一个众所周知的节点,称为
头
- 头部节点没有有效负载(关联值)
- 对于列表中的所有节点,
(prev!=NULL)&(next!=NULL)
- 对于任何节点
,n
和n->prev->next==n
n->next->prev==n
- 在一个空列表中,
(head->next==head->prev)&&(head->next==head)
// Forward declaration so the structure can point to itself
struct dll_links;
// The actual overhead of a DLL
typedef struct dll_links
{
struct dll_links *next;
struct dll_links *prev;
struct dll_links *head;
} dll_links, dll_head;
// A simple macro to cast linkable datastructures as a set of links.
#define AS_LINKS(n) ((dll_links *) n)
并使用它定义您自己的节点
数据结构
evry节点中的head。这允许实现检测违反不变量的尝试(例如删除head
元素)
现在,给定一个节点*n
,您可以通过n->link.prev
和n->link.next
访问链接
因此,鉴于上述情况,初始化新列表的函数将是
void dll_init(dll_head *list)
{
list->next = list.prev = list;
list->head = list;
}
并将用于:
...
dll_head myList;
dll_init(&myList);
...
请注意,这将强制执行所有不变量
对双链接列表执行的其他操作只有插入和删除
// Insert a new node in front of an existing one
void dll_insert(dll_links *newNode, dll_links *before)
{
dll_links *orignalPrevious = before->prev;
// First set up the links in the new node
newNode->prev = originalPrevious;
newNode->next = before;
newNode->head = before->head;
// Now link it in by adjusting the pointers of the surrounding nodes
before->prev = newNode;
originalPrevious->next = newNode;
}
// Remove a specified node from a list (and return it)
dll_links *dll_remove(dll_links *node)
{
// Check the assertion that you can not remove the head element
assert (node->head != node);
dll_links *successor = node->next;
dll_links *predecessor = node->prev;
// Remove the element from the list
predecessor->next = successor;
successor->prev = predecessor;
// Ensure no dangling pointers in the removed element
node->next = node->prev = node->head = NULL;
return node;
}
使用这三个函数,您的create_list
函数如下所示:
void create_list(dll_head *list)
{
int i;
dll_init(list);
for(i=1;i <=10;i++)
{
Node *node = malloc(sizeof(struct Node));
node->value=rand()%20;
dll_insert(AS_LINKS(node), list); // Append the new node to the list
}
}
...
{
dll_head myList;
create_list(&myList);
...
}
void创建列表(dll头*列表)
{
int i;
dll_init(列表);
对于(i=1;i值=rand()%20;
dll_insert(作为链接(节点),列表);//将新节点附加到列表中
}
}
...
{
dll_头myList;
创建_列表(&myList);
...
}
迭代遍历列表,提取第一个或最后一个条目等,作为练习。 追加条目是在标题之前插入,在前面插入是在
标题->下一步之前插入,
head
元素立即知道哪些节点位于列表的开头和结尾,依此类推
而使用dll\u链接
方法意味着所有操作都不需要知道任何关于实际操作的信息
节点结构和负载。这些函数可以链接任何东西(包括异构列表)。不要使用这种语法printf(“%d”,node->prev->value);
这样做不好
struct Node *previous = node->prev;
if (previous != NULL)
printf("%d\n", previous->value);
更好,因为当node
是第一个节点时,node->prev==NULL
,您将遇到问题
另外,您的最后一个元素是node
,因为您一直在迭代,直到node->next==NULL
,这应该发生在最后一个元素,但是您的代码无法解释您描述的行为,需要更多的解释,因为没有足够的代码来说明。我们如何知道node->prev
不是NULL?请进行更多的调试,并找出确切的原因seg错误来自。不要使用这种语法printf(“%d”,node->prev->value);
这样做不好,struct node*previous=node->prev;if(previous)printf(“%d\n”,previous->value);
更好。最后一个元素是node
be
struct Node *previous = node->prev;
if (previous != NULL)
printf("%d\n", previous->value);