我正在研究数据结构和链表,但我没有得到如何在没有递归的情况下制作链表副本的概念。有人可以解释一下吗。
5 回答
一个简单的迭代逻辑的伪代码是:
- 从原始列表的开头开始,
origHead
。 - 设置一个临时指针指向原始列表的头部,
tempNode = origHead
. - 如果
tempNode
=NULL
,则转到第 17 步。 - 如果
tempNode != origHead
,则转到第 10 步。 - 为复制列表的头部分配内存,
copyListHead
. - 设置
copyListHead->next
为NULL
。 - 设置一个临时指针指向复制列表的头部,
copyListTempNode = copyListHead
. tempNode = tempNode->next
.- 转到第 3 步。
- 为节点分配内存
newCopyNode
。 - 复制
tempNode->data
到newCopyNode->data
. - 设置
newCopyNode->next
为 NULL。 - 指向。
copyListTempNode->next
_newCopyNode
copyListTempNode = newCopyNode
.tempNode = tempNode->next
.- 转到第 3 步。
- 停止。
这个怎么运作
声明两个指针:一个
dst
指针,它将是最终的函数结果,以及next
指向指针的指针,它始终保存将接收下一个节点分配的指针的地址。next
指针指向指针最初保存 的地址dst
。虽然我们仍有要复制的节点 (
src != NULL
),但请执行以下操作:- 分配一个新节点,将结果指针分配给
*next
. - 将节点数据从 复制
src
到*next
。 - 分配
next
来保存node->next
我们刚刚分配的成员的地址。该成员可以使用&(*next)->next
. - 将输入源指针前进到其下一个节点:
src = src->next
. - 重复(2)。
- 分配一个新节点,将结果指针分配给
一旦完成,总是
*next
的值NULL
。这确保添加到列表中的最终节点(如果有)具有NULL
它的next
指针。如果根本没有节点添加到列表中(例如,何时src
调用NULL
我们的函数),则会将 的值设置dst
为 NULL,因为它是dst
当前保存在 中的地址next
。将 的值
dst
作为函数结果返回。
该算法的代码如下所示:
typedef struct Node
{
int data;
struct Node *next;
} Node;
Node* CopyList(const Node* src)
{
Node *dst = NULL, **next = &dst;
while (src)
{
// allocate new node
*next = malloc(sizeof(**next));
if (*next)
{
// copy_node() for complex duplication
(*next)->data = src->data;
// reposition our next-link to the address of ptr->next
// of the node we just added.
next = &(*next)->next;
// and finally, advance the source pointer
src = src->next;
}
else
{
perror("Failed to allocate node.");
exit(EXIT_FAILURE);
}
}
*next = NULL;
return dst;
}
注意:这也是从串行输入文件构建前向链接列表的好方法。它确保头部只初始化一次,并且每个后续节点总是附加到最后一个节点的next
指针。
没有递归 === 使用迭代。P码:
LinkedList *l1 = (the_head), *l2 = copy_node(l1);
for (tmp l1->next; tmp != NULL; tmp = tmp->next, l2 = l2->next) {
l2->next = copy_node(tmp);
}
完全没有理由为此使用递归——简单的迭代效果很好。复制一个节点。如果指向下一个节点的指针不为空,则对下一个节点重复该过程(并将next
刚刚复制的节点中的链接设置为指向您复制的下一个节点)。
将链表复制到空列表的简单方法是使用递归,如下所示,
struct Node {
int value;
Node* next;
};
Node* copy_list(Node* list) {
if (list == NULL) return NULL;
Node* result = new Node;
result->value = list->value;
result->next = copy_list(list->next);
return result;
}
但是如果你不想使用递归,那么你必须手动复制每个不为空的列表,方法是使用循环,直到你得到 (node)->next = NULL 作为检查。