我使用以下代码成功实现了 2 指针解决方案:
void list_reverse(t_list **begin_list)
{
t_list *new_root;
t_list *root;
t_list *next;
new_root = 0;
root = *(begin_list);
while (root)
{
next = root->next;
root->next = new_root;
new_root = root;
root = next;
}
*begin_list = new_root;
}
这工作正常 - 至少根据我的测试。现在我想尝试仅使用单个指针来反转链表,而不使用return
,所以我尝试将我的代码转换为void list_reverse(t_list *begin_list)
,但当然*begin_list = new_root
不起作用,因为我无法更改begin_list
。其余的似乎有效。
如何在没有双指针的情况下修改begin_list
?
编辑:结构是:
typedef struct s_list
{
struct s_list *next;
void *data;
} t_list;
您可以通过就地交换第一个和最后一个节点(浅拷贝(,然后反转列表来反转列表。这样,最后一个节点的内容将最终出现在初始节点中,头部指针已经指向该节点。
下面是一个实现:
void swap(struct node *a, struct node *b) {
struct node tmp = *a;
*a = *b;
*b = tmp;
}
void reverse(struct node *h) {
// Null list and single-element list do not need reversal
if (!h || !h->next) {
return;
}
// Find the last node of the list
struct node *tail = h->next;
while (tail->next) {
tail = tail->next;
}
// Swap the tail and the head **data** with shallow copy
swap(h, tail);
// This is similar to your code except for the stopping condition
struct node *p = NULL;
struct node *c = tail;
do {
struct node *n = c->next;
c->next = p;
p = c;
c = n;
} while (c->next != tail);
// h has the content of tail, and c is the second node
// from the end. Complete reversal by setting h->next.
h->next = c;
}
演示。
函数可以通过三种主要方式向其调用方提供计算值。
-
它可以
return
该值,或包含该值的对象,或指向此类对象的指针(前提是,在最后一种情况下,指向的对象比函数调用的寿命更长(。 -
它可以通过调用方提供的指针修改调用方可见的对象。
-
它可以将计算值记录在调用方可见的文件范围变量中。
还有其他替代方案,主要涉及I/O,但这些通常符合(3(的精神。
您不得使用 (1(。 您不能以您提议的方式使用 (2(。 可能是(3(是预期的答案,但这很丑陋,真的不应该推荐。 那怎么办?
也许你只是咬紧牙关并使用文件范围变量,但是如果你被允许寻求调用者的帮助和/或对列表的形式提出要求,那么你还有另一种可能性:让调用者传递一个在列表反转时不会改变的指针——即指向包含指向列表头的指针的结构的指针。 然后,该函数不需要修改该指针;它通过指向的对象返回新的列表头。
通常,人们使用代表整个列表的单独结构类型来做这种事情。 但是,如果您考虑一下,您将意识到您现有的列表节点类型已经具有合适的形式。 如果您无法引入新结构,则可以使用现有结构 - 只需将列表中的第一个节点视为其余元素上的非数据承载句柄即可。 这有时被称为虚拟头节点,使用虚拟头节点的列表在许多方面提供了更简单的函数实现。
看看这个:
void reverse(struct node* head) {
struct node *curr=head;
struct node *next=NULL;
struct node *prev=NULL;
while(curr) {
next=curr->next; //we're basically stashing the next element
curr->next=prev; //setting next pointer to the previous element
prev=curr; //previous is now current
curr=next; //and updating the current from the stashed value
}
}