如何在不使用递归的情况下将链接列表复制到另一个列表
没有递归===使用迭代。 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;
}
,但如果你不想使用递归,那么你必须手动,复制每个不被清空列表使用循环,直到你得到(节点) - >下一个= NULL作为检查。
如何使用
声明两个指针:一个
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,因为它是当前在next
中保存的dst
的地址。返回作为函数结果的
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
。
这看起来很有趣的代码!我不明白'next =&(* next) - > next;'虽然。你能解释一下那条线路在做什么吗? – 2013-03-11 07:47:57
@AnishRam当然。它是一个指针指针。即它包含一个指针变量的地址。它开始保存我们将返回的头指针的地址。当一个节点被添加时,它被分配了刚刚添加的节点的下一个指针的地址。换句话说,它总是保存将接收* next *分配节点的指针地址。在开始时,这是'&dst'。之后,它的'&(* next) - > next'。完成后,我们将它指向的指针设置为NULL,确保列表以NULL结尾(最后一个“next”设置为NULL)。 – WhozCraig 2013-03-11 08:21:10
哦谢谢你的解释!我现在明白了。但是,OP是否需要一个指定列表的_copy_?在你的例子中,每个节点都不会指向原始列表的下一个节点吗?如我错了请纠正我。 – 2013-03-11 08:30:30
一个简单的,重复的逻辑的伪代码将是:在原来的列表头,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.
- 停止。
为什么你需要专门复制一个链表而不递归? – 2013-03-11 06:12:00
面试官问我.. so – nagaradderKantesh 2013-03-11 06:12:44