我试图反转一个单链表,但有点扭曲。它不是将指向下一个节点的指针作为实际的下一个节点,而是指向该下一个节点中的指针。
struct _Node
{
union
{
int n;
char c;
} val;
void *ptr; /* points to ptr variable in next node, not beginning */
int var;
};
typedef struct _Node Node;
我知道如何扭转正常的单链表,我想我对如何解决这个问题有了一般性的想法,但是当我试图访问{{{}时,我会遇到段错误。 1}}我不知道为什么。
head->ptr
即使我尝试访问Node *reverse(Node *head)
{
Node * temp;
Node * prev = NULL;
while(head != NULL)
{
temp = head->ptr + 4; /* add 4 to pass union and get beginning of next node */
head->ptr = prev;
prev = head;
head = temp;
}
return prev;
}
而不添加4,我也会遇到段错误。
我对此代码的驱动程序只是一个目标文件,因此我无法查看事件的调用方式或类似内容。我要么错过一些明显的东西,要么在驱动程序中存在问题。
答案 0 :(得分:1)
首先,我将向您展示代码中的一个主要问题:
while (head) // is shorter than while(head != NULL)
{
// Where does the 4 come from?
// And even if: You have to substract it.
// so, definitively a bug:
// temp = head->ptr + 4; /* add 4 to pass union and get beginning of next node */
size_t offset_ptr = (char*)head->ptr - (char*)head;
// the line above should be moved out of the while loop.
temp = head->ptr - offset_ptr;
无论如何,你的算法可能不会像写的那样工作。如果你想要反转东西,你将不得不倒退(这在单个链接列表中是非常重要的)。有两种选择:
计算元素数,分配数组,记住该数组中的指针,然后重新分配下一个指针。
创建一个临时双链表(实际上你只需要另一个反向链表,因为两个列表一起形成一个双链表)。然后再次步行将下一个指针从临时列表复制到旧列表。请记住在返回之前释放临时列表。
答案 1 :(得分:1)
我尝试了你的代码并进行了一些调整,在我看来你的代码有一些逻辑错误。您的指针一次又一次被覆盖(从一个节点跳到另一个节点并返回:1-> 2,2-> 1),这导致了可疑的内存泄漏。在这里,您的代码的工作版本......
Node *reverse(Node *head)
{
Node *temp = 0;
//Re-ordering of your assignment statements
while (head) //No need for explicit head != NULL
{
//Here this line ensures that pointers are not overwritten
Node *next = (Node *)head->ptr; //Type casting from void * to Node *
head->ptr = temp;
temp = head;
head = next;
}
return temp;
}