C 从双链接列表中添加和删除
我有这个结构C 从双链接列表中添加和删除,c,doubly-linked-list,C,Doubly Linked List,我有这个结构 typedef struct node { struct node *prev; void *data; struct node *next; }NODE; typedef struct head { unsigned int length; struct node *first; struct node *last; }HEAD; STATUS addNode(HEAD *head, NODE *newNode
typedef struct node
{
struct node *prev;
void *data;
struct node *next;
}NODE;
typedef struct head
{
unsigned int length;
struct node *first;
struct node *last;
}HEAD;
STATUS addNode(HEAD *head, NODE *newNode, int loc)
{
int i;
STATUS ret = SUCCESS;
NODE *curPtr;
if(head && newNode && loc && (loc <= (head->length)+1))
{
if(loc == 1)
{
newNode->prev = NULL;
newNode->next = head->first;
if(head->first)
head->first = newNode;
}
else
{
curPtr = head->first;
for(i=1; i<(loc-1); i++){
curPtr = curPtr->next;
}
newNode->prev = curPtr;
newNode->next = curPtr->next;
if(curPtr->next){
curPtr->next->prev = newNode;
}
curPtr->next = newNode;
}
head->length++;
}
else
ret = FAILURE;
return ret;
}
STATUS removeNode(HEAD *head,NODE *nodeToRemove)
{
STATUS ret = SUCCESS;
NODE *curPtr;
if(head && head->first)
{
curPtr = nodeToRemove->prev;
curPtr->next = nodeToRemove->next;
if(!(curPtr->next)){
curPtr->next = head->first;
}
head->length--;
}
else
ret = FAILURE;
return ret;
}
typedef结构节点
{
结构节点*prev;
作废*数据;
结构节点*下一步;
}节点;
typedef结构头
{
无符号整数长度;
结构节点*第一;
结构节点*last;
}头部;
状态addNode(HEAD*HEAD,NODE*newNode,int loc)
{
int i;
状态ret=成功;
节点*curPtr;
if(头和新节点和位置和位置长度)+1))
{
如果(loc==1)
{
newNode->prev=NULL;
新建节点->下一个=头部->第一个;
如果(头->第一个)
head->first=newNode;
}
其他的
{
curPtr=头->第一;
对于(i=1;不精确;
}
newNode->prev=curPtr;
newNode->next=curPtr->next;
如果(当前->下一步){
curPtr->next->prev=newNode;
}
curPtr->next=newNode;
}
头部->长度++;
}
其他的
ret=失败;
返回ret;
}
状态removeNode(头*头,节点*节点删除)
{
状态ret=成功;
节点*curPtr;
如果(头和头->第一个)
{
curPtr=nodeToRemove->prev;
curPtr->next=nodeToRemove->next;
如果(!(当前->下一步)){
curPtr->next=head->first;
}
头部->长度--;
}
其他的
ret=失败;
返回ret;
}
我知道我在“从列表中删除”中没有调用空闲(节点),此调用是在其他地方进行的
我的问题是,有时在add节点的newNode->next=curPtr->next;
行上,它会出现分段错误
您能告诉我可能发生这种情况的原因吗?可能未将
curptr->next
分配给任何不一定会使其指向NULL的对象,因此您可能会在运行时遇到分段错误。请确保在生成列表时,节点中的所有指针在出现任何错误之前都已初始化为NULL对其进行分配/操作
见此:
这是:好的,让我们从我的第一条评论开始:当你用
loc==1
调用addNode
函数时会发生什么:你初始化新节点,所以它是下一个指针指向列表的旧头,prev
指针指向NULL
。这一切都很好,但是然后问题开始了。只有当列表不为空时,才将新节点添加到列表中。您也不会更改以前的头节点prev
指针
这意味着如果列表为空(即当head->first
为NULL
)时,您将不会添加节点,并且列表将继续为空。如果列表不为空,则您有一个双链接列表,您只能单程(从(新)第一个节点到(新)第一个节点)第二个节点,你不能走相反的方向,因为你没有这样设置链接
现在来看我的第二条和第三条评论:当loc!=1
时循环。首先,如果loc==0
,它将根本不会运行,这意味着它将添加到头部(这是当loc==1
时尝试执行的操作)。如果列表为空,这将不起作用,因为curPtr
随后将为NULL
,当您取消引用该指针时,您将有
其次,假设您已成功地将一些节点添加到列表中,并将大于节点数加上列表中一个的值作为loc
(即,如果您有一个节点,并且您传递的值大于2
,或者您有五个节点,并且传递的值大于6
),然后循环将从一次迭代到多次,留下curPtr
为NULL
。您不会在任何地方检查该值,这意味着您迟早(在循环中或之后)会尝试取消引用一个NULL
指针,该指针将导致
是导致崩溃的最常见原因,例如您遇到的崩溃。下一次发生崩溃时,您应该做的第一件事是使用调试器并在其中运行程序。调试器将在崩溃位置停止,让您检查函数调用堆栈以及调用堆栈。您还可以检查值调用堆栈的每个级别上的变量数量(如果调试器具有该级别的信息)。你还应该尝试在不同场景的调试器中逐行逐行地检查代码,看看你打算发生的事情是否真的发生了。如果你仍然困惑不解,那么你可以这样做,并发布一个问题。在编译器旁边,调试器是程序员的最佳工具。哦,说到编译器,总是要构建wi启用尽可能多的警告,因为编译器非常擅长检测可疑的东西,并可能导致UB(未定义行为).如果loc==1
,旧的第一个节点prev
指针指向什么?如果列表为空,为什么不添加节点?至于分段错误,如果您想最后添加新节点呢?即当curPtr
为NULL
时?最后,如果您提供的loc
较大,会发生什么列表中是否有节点?第一个问题-应指向尾部,第二个问题将其添加到尾部,第三个问题将列表绕几圈,直到您使用该位置