删除链接列表中的节点

问题描述:

经过很多努力,我已经设法将一个从我的链接列表中删除某个节点的函数拼凑在一起。但是,出于纯粹的兴趣,我想了解如何从列表中删除第一个节点,即头部。删除链接列表中的节点

我的程序要求删除一个字母,例如。 你好存储在列表中,用户输入H进行删除,所以现在列表是ello 现在用我的代码,程序崩溃了,就好像H被删除一样,没有头,程序也没有'不知道去哪里寻找名单。

下面是我目前的实现,任何线索或提示如何修改此代码(我想保持它类似于我的),以允许头节点删除将不胜感激!

编辑:在回答下面

FullList DeleteNode(FullList temp, char c) { 
FullList remember; 
FullList ptr; 
while (temp.head->c != c) { 
    remember.head = temp.head; 
    temp.head = temp.head->next; 
} 
ptr.head = temp.head->next; 
free(temp.head); 
remember.head->next = ptr.head; 
return temp; 
} 

int main(void) { 
FullList List; 
char c, s; 
List.head = NULL; 

while ((c=getchar()) != '.') { 
    List = addToEnd(List, c); 
} 
scanf(" %c", &s); 
List = DeleteNode(List, s); 
while (List.head != NULL) { 
    printf("%c", List.head->c); 
    List.head = List.head->next; 
} 
return 0; 
} 

typedef struct List { 
char c; 
struct List *next; 
}List; 

typedef struct { 
List *head; 
List *tail; 
}FullList; 

List *insertList(char c, List *t1) { 
    List *t = (List*)calloc(1, sizeof(List)); 
    t->c = c ; 
    t->next = t1; 
return t; 
} 

FullList addToEnd(FullList c, char element) { 
if (c.head == NULL) { 
    c.head = c.tail = insertList(element, NULL); 
}else { 
    c.tail->next = insertList(element, NULL); 
    c.tail = c.tail->next; 
} 
return c; 
} 

void DeleteNode(FullList temp, char c) { 
FullList remember; 
FullList ptr; 
while (temp.head->c != c) { 
    remember.head = temp.head; 
    temp.head = temp.head->next; 
} 
ptr.head = temp.head->next; 
free(temp.head); 
remember.head->next = ptr.head; 
} 


int main(void) { 
FullList List; 
char c, s; 
List.head = NULL; 

while ((c=getchar()) != '.') { 
    List = addToEnd(List, c); 
} 
scanf(" %c", &s); 
DeleteNode(List, s); 
while (List.head != NULL) { 
    printf("%c", List.head->c); 
    List.head = List.head->next; 
} 
return 0; 
} 

如果不更改现有的代码,则无法执行此操作。

您正在将FullList结构传递给您的DeleteNode()函数。这意味着对该结构的任何更改在main中都不可见 - 函数获得副本

你需要改变DeleteNode()接受指针:调用它时

void DeleteNode(FullList *temp, char c) 

然后main()你会怎么做:

DeleteNode(&List, s); 

通过这样做,你可以改变的temp->head的价值你的功能将会回到main()

temp->head = temp->head->next; 

编辑:你需要的逻辑是:

  • 检查,看是否temp->head->c == c
  • 如果是的话,有temp->head->next
  • 其他分配temp->head更换temp->head到一个临时指针*previous。将temp->head->next分配给指针*current。遍历列表,移动两个指针。当您在current->c中找到匹配项时,将current->next指定为previous->nextfree(),current节点。
+0

我按照您的建议修改了代码,但是现在,它会删除所有内容,直到输入的字母为止。即Abcde,输入c,de打印 – PnP

+0

如果可能,请参阅我的编辑,我已返回FullList而不是使用指针,但得到相同的结果,它会删除所有内容,直到我输入的字母为止。 – PnP

+0

@ user1048116 - 我现在解释了改变'temp-> head'的值,我没有为你做功课;)你需要构建从头部开始寻找匹配的逻辑。作为一个提示,你将需要两个指针 - “* previous”和“* current”。您需要从头开始,跟踪前一个和当前节点,并在'current-> c'中查找您的匹配项。当你找到你想要删除的节点时,你必须将'current-> next'分配给'previous-> next',然后''free''当前'节点。没有必要从这个函数中返回任何东西 - 你正在通过指针修改结构体 –

现在是,里面DeleteNode的方式,当你改变的说法,它只是改变了局部变量,而不是外面的一个功能。

您可能已通过指针FullList传递给DeleteNode,这样做是为了它的修改将是可见的来电,或修改本地一个并返回,调用者必须将返回FullList其名单。

无论采用哪种方式,DeleteNode所做的更改都必须对调用者可见。

+0

请看我的编辑和评论在上面的答案。 :) – PnP

+0

@ user1048116正如布赖恩罗奇所说的,你必须有两个指针(一个指向当前指针,一个指向前一指针,其下一个指针必须修复),或者只执行'temp.head-> next-> c'而不是'temp.head-> c',并且有一个特殊情况,其中'head-> c'是所需的字符。 –

+0

感谢您的建议,事实上,我设法通过添加一条IF语句来处理当前代码,如果搜索到的内容碰巧是头节点,并将其余代码放入ELSE子句中。 – PnP