虽然@VladFromMoscow 的答案显示了交换列表中的节点以实现您的目标的正确方法,但如果您无法传递单个指针,并且函数返回类型固定为void,那么还有另一种方法解决方法。
您只需在节点之间交换int 成员值,而不是交换节点。以这种方式处理问题,第一个节点的地址永远不会改变,因此无需将列表的地址作为参数传递。
方法很简单。取当前节点,在当前节点和下一个节点之间交换整数值,然后越过持有交换整数的节点。为此,您从当前节点前进到下一个节点并检查下一个节点是否为NULL(标记列表的末尾)。如果是NULL,你就完成了。如果不是NULL,则再次前进并重复。您可以使用while() 循环编写函数,例如
void reverse_pairs (listelem *head)
{
while (head && head->next) {
int tmp = head->a;
head->a = head->next->a;
head->next->a = tmp;
head = head->next;
if (head->next)
head = head->next;
}
}
或者,可读性稍差,使用for() 循环和三元,例如
void reverse_pairs (listelem *head)
{
for (; head && head->next;
head = head->next->next ? head->next->next : NULL) {
int tmp = head->a;
head->a = head->next->a;
head->next->a = tmp;
}
}
使用/输出示例
对于最后一个指针为NULL 的普通列表,您的输出打印原始列表,调用reverse_pairs(),然后输出修改后的列表如下所示:
$ ./bin/lls_revpairs
1 2 3 4 5
2 1 4 3 5
完整的测试代码
完整的测试代码如下。正常编译将使用上面的for() 循环,或者将定义-DUSEWHILE 添加到您的编译字符串将导致使用函数的while() 循环形式:
#include <stdio.h>
#include <stdlib.h>
typedef struct _listelem {
int a;
struct _listelem* next;
} listelem;
/** add node at end of list, update tail to end */
listelem *add (listelem **head, int v)
{
listelem **ppn = head, /* pointer to pointer to head */
*pn = *head, /* pointer to head */
*node = malloc (sizeof *node); /* allocate new node */
if (!node) { /* validate allocation */
perror ("malloc-node");
return NULL;
}
node->a = v; /* initialize members values */
node->next = NULL;
while (pn) {
ppn = &pn->next;
pn = pn->next;
}
return *ppn = node; /* add & return new node */
}
#ifdef USEWHILE
/** reverse node pairs in list - while loop */
void reverse_pairs (listelem *head)
{
while (head && head->next) {
int tmp = head->a;
head->a = head->next->a;
head->next->a = tmp;
head = head->next;
if (head->next)
head = head->next;
}
}
#else
/** reverse node pairs in list - for loop + ternary */
void reverse_pairs (listelem *head)
{
for (; head && head->next;
head = head->next->next ? head->next->next : NULL) {
int tmp = head->a;
head->a = head->next->a;
head->next->a = tmp;
}
}
#endif
/** print all nodes in list */
void prn_list (listelem *l)
{
if (!l) {
puts ("list-empty");
return;
}
size_t i = 0;
for (listelem *n = l; n && i < 10; n = n->next, i++)
printf (" %d", n->a);
putchar ('\n');
}
int main (void) {
listelem *list = NULL;
for (int i = 1; i <= 5; i++)
add (&list, i);
prn_list (list);
reverse_pairs (list);
prn_list (list);
}