链接列表中元素的成对交换(通过更改指针)
Pairwise swapping of elements in a linked list (by changing pointers)
问题语句如下:
给定一个单链接列表,写一个函数以成对交换元素。例如,如果链接列表为1-> 2-> 3-> 3-> 4-> 5-> 6-> 7,则该功能应将其更改为2-> 1-> 1-> 4-> 3-> 3-> 6-> 5 -> 7,如果链接列表为1-> 2-> 3-> 3-> 4-> 5-> 6,则该功能应将其更改为2-> 1-> 1-> 4-> 3-> 3-> 6-> 5 <</p>
这是我的解决方案:
void swapPairs(Node* head) {
if (!head->next || !head)return head;
Node* current = head->next;
Node*prev = head;
while (true) {
Node* next = current->next;
current->next = prev;
if (!next || !next->next) {
prev->next = next;
break;
}
prev->next = next->next;
prev = next;
current = prev->next;
}
}
解决方案的问题是,当它到达函数的末尾时,由于当前和上一个已移动了函数,因此头部不再指向列表的开始。我已经在网上看到了其他解决方案,这些解决方案与我在这里做的事情相同,但是也许由于它们是在C而不是C 实现的,因此它们的代码有些方面可以使头保持指向开始列表。
我意识到这可能是一个非常简单的问题,但是我目前没有看到该解决方案。在整个算法中维护列表开始的最佳方法是什么?
一旦您经历了轻微的范式,手头的任务将变得更加简单。一开始这似乎更复杂,但是在考虑一下之后,它的简单性应该很明显。
简单地说:与其携带一个指针 - 到每对列表元素的第一个 - 当您浏览列表时,请携带指向指针指向每对列表元素的第一个指针。从表面上看,这听起来很复杂。但是,一旦尘埃落定,这将大大简化手头的任务。
您必须单独存储头部指针,然后将其传递给swapPairs()
:
Node *head;
// The list gets populated here, then ...
swapPairs(head);
这就是您现在正在做的事情。但是不要这样做,而是将指针传递给头节点:
swapPairs(&head);
// ...
void swapPairs(Node **ptr)
{
while ( (*ptr) && (*ptr)->next)
{
// swap the next two elements in the list
// ...
// Now, advance by two elements, after swapping them.
ptr= &(*ptr)->next->next;
}
}
while循环的主体将交换列表中的下两个元素,让我们暂时跳过该部分,然后专注于通过此链接列表迭代的逻辑,这是一对元素时间。这里发生了什么?
好吧,您正在尝试浏览列表,一次是两个元素。
请记住,ptr
不再是指向该对的第一个元素的指针。这是指向两人的第一个元素的指针恰好活着的指针。因此,最初的ptr
指向您的原始head
指针。
一旦理解,下一个心理飞跃就是要了解您要循环遍及迭代,只要列表中剩下两个元素:
while ( (*ptr) && (*ptr)->next)
*ptr
是列表的下一个元素,该对的第一个元素,(*ptr) ->接下来是对第二个中第二个的指针。由于我们的迭代方式,可以通过合同从不成为NULL
来证明ptr
。因此,如果*ptr
为null,则到达列表的末尾。但是,如果*ptr
不是零,则至少剩下一个元素,(*ptr) ->接下来是"下一个第二个元素"。如果(*ptr)->next
为null,则原始列表中有奇数元素,因此在最后一次迭代中,您最终以*ptr
指向奇数鸭。在这种情况下,您也不需要进一步走。
最后:
ptr= &(*ptr)->next->next;
这只是通过列表的两个元素来推进ptr
。请记住,ptr
是指向列表"碰巧活着"的下两个元素的指针的指针,现在将ptr
设置为指向*** Next ***的第一个指针的位置*列表中的两个元素恰好存在。拿一张纸,画一些图表,然后自己弄清楚。不要通过"去",不要收取200美元,直到陷入困境。
一旦您将大脑包裹起来,唯一剩下的就是交换对。就是这样。循环的主体可以简单地为:
Node *first=*ptr;
Node *second=first->next;
Node *next=second->next;
*ptr=second;
second->next=first;
first->next=next;
就是这样。你完成了。你猜怎么着?您的原始head
现在自动指向交换列表的右头节点。
现在,这不是简单吗?
将函数的签名更改为
Node* swapPairs(Node* head)
并在第一次交换后保存新的头,然后在while
Loop关闭}
之后的结尾,返回该新的头,以替换呼叫者持有的旧列表头,它将使用此内容,例如:
list = swapPairs(list);
您可以在功能开始时将指针保留到新的头部,并在功能结束时更新head
。请注意,我将参数从Node*
更改为Node **
,因为我们想更新指针值,以便当我们更新head
时,我们写入传递给此功能的同一内存位置。结果,当我们返回该功能时,将在此功能的呼叫者中可用。
void swapPairs(Node **head) {
if (!(*head)->next || !(*head))
return;
Node *new_head = (*head)->next; // the new_head
Node *current = (*head)->next;
Node *prev = (*head);
while (true) {
Node *next = current->next;
current->next = prev;
if (!next || !next->next) {
prev->next = next;
break;
}
prev->next = next->next;
prev = next;
current = prev->next;
}
*head = new_head; // now update the head
}
- 共享指针的复制和交换效率
- 如何在单个链表中交换两个节点的位置,只修改指针
- 以原子方式交换指针与 nullptr
- 使用指针交换整数
- 使用指针 c++ 交换结构数组中的元素
- 使用指针交换数组的内容
- 无法使用指针写入交换
- 使用指针交换而不引用数组C++
- 共享指针交换方法标识更改
- 为什么基于指针交换两个值在函数范围之外不起作用?
- 将指针交换为指针
- 使用双向链表中的指针交换节点
- 使用指针交换字符变量
- 通过 xor 运算符使用引用或指针交换两个变量的值
- 指针交换怪异
- 当数组是类的数据成员时,如何使用指针交换数组
- 使用公用指针交换指向已分配内存的指针
- 使用指针交换两个字符串会输出奇怪的输出
- 仅通过操作指针交换链表中的相邻节点
- 使用指针交换两个变量