【发布时间】:2020-10-21 00:28:05
【问题描述】:
我编写了一个程序,可以将 char 字符添加到双向链表的开头。现在,一旦我有了这个列表,我的程序的目的就是从列表中完全删除某些 char 字符。例如(仅出于代表性目的使用大括号):如果列表由 { a, b, b, a, c } 组成,那么我的程序可以从列表中删除所有“b”以使其成为{ a, a, c}。此外,如果我的列表是 {b, a, c, a} 或 {a, c, a, b} 并且如果我想删除“b”,那么程序在这两种情况下都可以正常工作并给我 {a, c, a}。
但是有很多问题(对于所有情况,假设我想删除“b”):
- 如果我的列表是 {b, a, b, a, c}(“b”在前面,中间某处),我会遇到分段错误(我认为这与使用光标在while循环中,但我不知道究竟是为什么以及如何修复它)
- 如果我的列表是 {a, b, b, a, c, b}(中间最后是“b”),那么输出会给我奇怪的符号(我假设它是内存故障,不知道为什么)
这是我正在使用的代码:
#include<stdio.h>
#include<stdlib.h>
struct list
{
int data;
struct list* next;
struct list* prev;
};
struct list* head; // global variable - pointer to head node of list.
struct list* last; // global variable - pointer to last node of list
//Creates a new list and returns pointer to it.
struct list* GetNewNode(char x)
{
struct list* newNode
= malloc(sizeof(struct list));
newNode->data = x;
newNode->prev = NULL;
newNode->next = NULL;
return newNode;
}
//Inserts a list at head of doubly linked list
void InsertAtHead(char x)
{
struct list* newNode = GetNewNode(x);
if(head == NULL)
{
head = newNode;
return;
}
head->prev = newNode;
newNode->next = head;
head = newNode;
struct list* temp = head;
while (temp->next != NULL) temp = temp->next;
last = temp;
}
void remove_element (char character)
{
struct list * cursor, *previous, *store_el;
//int boolean = 0;
if (head == NULL) return;
else
{
cursor = head;
while(cursor != NULL)
{
if (cursor->data == character)
{
if (cursor->prev == NULL)
{
// printf("deleting from front\n");
previous = head;
head = head->next;
head->prev = NULL;
//boolean = 1;
//free(previous);
}
if (cursor->next == NULL)
{
//printf("deleting from back\n");
previous = last;
last = last->prev;
last->next = NULL;
//boolean = 1;
//free(previous);
}
else
{
// printf("deleting from middle\n");
previous = cursor;
cursor = cursor->next;
cursor->prev = previous->prev;
store_el = previous->prev;
store_el->next = cursor;
cursor = head;
}
free(previous);
//printf("head data = %c\n", cursor->data);
}
cursor = cursor->next;
}
}
}
//Prints all the elements in linked list in forward traversal order
void Print()
{
struct list* temp = head;
printf("Forward: ");
while(temp != NULL)
{
printf("%c ",temp->data);
temp = temp->next;
}
printf("\n");
}
int main()
{
char character;
/*Driver code to test the implementation*/
head = NULL; // empty list. set head as NULL.
// Calling an Insert and printing list before and after deletion of character
InsertAtHead('c');
InsertAtHead('a');
InsertAtHead('b');
InsertAtHead('b');
InsertAtHead('a');
Print();
printf("After deletion:\n");
remove_element ('b');
Print();
}
【问题讨论】:
-
7-8 小时是一个很长的时间来寻找这样的问题而没有找到任何东西。你究竟是如何接近它的?你只是在猜测吗?还是您使用的是调试器?
-
我立即注意到的一件事是,当您删除头部的元素时,您的
cursor不会被修改。您将替换磁头,释放旧磁头(存储在cursor和previous中),然后继续使用带有cursor = cursor->next的无效指针。您可以通过删除尾部的项目来执行类似的操作。当您删除一个元素时,您应该不跟随next指针前进光标。相反,您已经知道更改链接时接下来会发生什么(正如您在列表中间删除时明确处理的那样),因此您只需要更新它。 -
我打错了,我现在已经正确编辑了我的帖子。我的意思是说我花了 7-8 个小时试图完成代码,但仍然花了 3 个小时左右才找到问题,没有任何运气。我用笔和纸尝试可视化双向链表并熟悉数据结构(我已经浏览了 15 页或其他内容)。我一直在尝试不同的方法来解决问题,但没有任何运气。不幸的是,我不知道如何使用调试器,也许您可以将我链接到教如何使用调试器的好资源。谢谢!
-
您是否阅读了我对实际问题的评论? (或至少一个问题)
-
是的,我阅读了您的评论,这是有道理的。不幸的是,我住的地方太晚了,所以我需要签字。非常感谢您的评论,我将在明天晚些时候尝试实施解决方案,并在此处报告。
标签: c doubly-linked-list