我正在合并两个链接列表,第三个列表包含备用位置的元素,但合并的功能不起作用
void insert2()
{
//node ptr-pointer of first linked list<br>
//node1 ptr1-pointer of second list<br>
//node2 ptr2 -pointer of the merged linked list
node *ptr=head;
node1 *ptr1=head1;
node2 *ptr2=(node2*)malloc(sizeof(node2));
node *ptr3;
while(ptr!=NULL&&ptr1!=NULL)
{
//Entering the element of first linked list
ptr2->info=ptr->info;
if(head2==NULL)
{
ptr->next=NULL;
head=ptr;
}
else
{
ptr3=head2;
while(ptr3->next!=NULL)
{
ptr3=ptr3->next;
}
ptr3->next=ptr2;
ptr2->next=NULL;
}
//Entering the element of second linked list
ptr2->info=ptr1->info;
while(ptr3->next!=NULL)
{
ptr3=ptr3->next;
}
ptr3->next=ptr2;
ptr2->next=NULL;
}
}
答案 0 :(得分:0)
假设我们要在第二个列表中交替添加节点。所以第二个列表将成为新列表。这个想法是
保持2个指针指向当前节点。最初是原始列表p和q。
虽然它们不为空(两者都不为空),但您存储在两个节点的下一个地址中。
现在你会做什么?您将指向p的当前值和p的当前值的下一个p。
现在,指针将正确地更改为下一个节点,因为它们现在将被处理。
-------- ---------- | p_curr|------------>| |--------->NULL |-------| p_next-->|--------| -------- ---------- | q_curr|------------>| |--------->NULL |-------| q_next-->|--------| //After an iteration in the while loop. -------- ---------- | |----| --> | p_curr| --------->NULL |-------| _ |______| |--------| | | -------- | | ---------- | |_| |------->| q_curr |--------->NULL |-------| |--------|
代码将是这样的(有关更多信息,请查看link)
void merge(struct node *p, struct node **q)
{
struct node *p_curr = p, *q_curr = *q;
struct node *p_next, *q_next;
// While therre are avialable positions in p
while (p_curr != NULL && q_curr != NULL)
{
// Save next pointers
p_next = p_curr->next;
q_next = q_curr->next;
// Make q_curr as next of p_curr
q_curr->next = p_next; // Change next pointer of q_curr
p_curr->next = q_curr; // Change next pointer of p_curr
// Update current pointers for next iteration
p_curr = p_next;
q_curr = q_next;
}
*q = q_curr; // Update head pointer of second list
}
您可以按照以前的方式执行此操作。现在你需要做些什么改变?
您只需制作list A
和list B
的副本,然后将这些作为参数传递给列表,您将从上面显示的上一个函数中获取第三个列表。
但这是一个非常原始的解决方案。您还可以在函数中以线性时间格式构建列表。
struct node * getnode() { struct node *temp=(struct node*)malloc(sizeof(struct node)); if(temp==NULL) { printf("\n Error in allocation\n"); exit(0); } return temp; } void merge(struct node *p, struct node *q,struct node **n) { struct node *p_curr = p, *q_curr = q; struct node **store; struct node *n1; // While therre are avialable positions in p while (p_curr != NULL || q_curr != NULL) { if (p_curr) { if(first) { store=&n1;first=0; } n1=getnode(); n1->info=p_curr->info; n1->next = p_curr->next; n1=n1->next; p_curr=p_curr->next; } if (q_curr) { if(first) { store=&n1;first=0; } n1=getnode(); n1->info=q_curr->info; n1->next = q_curr->next; n1=n1->next; q_curr=q_curr->next; } } *n=*store; }
请记住,在这种情况下,两个
if
语句正在检查其中是否有NULL
。如果是这种情况,则在结果节点中添加其他列表的节点。store
存储第一个节点的地址。毕竟我们需要指向第三个节点的头部。
答案 1 :(得分:0)
试试这个:
NODE * AlternateListMerge(NODE *pSrc1, NODE *pSrc2)
{
NODE *pDst = NULL; /* destination head ptr */
NODE **ppDst = &pDst; /* ptr to head or prev->next */
NODE *pNode; /* ptr to node */
while(pSrc1 || pSrc2){
if(pSrc1){
pNode = malloc(sizeof(NODE));
pNode->info = pSrc1->info;
pSrc1 = pSrc1->next;
*ppDst = pNode;
ppDst = &pNode->next;
}
if(pSrc2){
pNode = malloc(sizeof(NODE));
pNode->info = pSrc2->info;
pSrc2 = pSrc2->next;
*ppDst = pNode;
ppDst = &pNode->next;
}
}
*ppDst = NULL;
return pDst;
}
或者这个(代码少,多一点时间):
NODE * AlternateListMerge(NODE *pSrc1, NODE *pSrc2)
{
NODE *pDst = NULL; /* destination head ptr */
NODE **ppDst = &pDst; /* ptr to head or prev->next */
NODE *pNode; /* ptr to node */
NODE *pSwap; /* used for swap */
while(pSrc1 || pSrc2){
if(pSrc1){
pNode = malloc(sizeof(NODE));
pNode->info = pSrc1->info;
pSrc1 = pSrc1->next;
*ppDst = pNode;
ppDst = &pNode->next;
}
pSwap = pSrc1;
pSrc1 = pSrc2;
pSrc2 = pSwap;
}
*ppDst = NULL;
return pDst;
}
答案 2 :(得分:0)
由于没有涉及类型的声明,没有关于如何初始化列表的信息,也没有关于如何输出结果的详细信息,我只能说一般性。但是,鉴于您确实表示要避免修改原始列表,可以确定需要对每个列表中的每个节点进行复制。这是你可以做到的一种方式:
struct node {
void *data;
struct node *next;
};
#define COPY(from, to, error_label) do { \
to = malloc(sizeof(struct node)); \
if (! to) { \
/* allocation error */ \
goto error_label; \
} \
to->data = from->data; \
to->next = NULL; \
} while (0)
int merge(struct node *head1, struct node *head2, struct node **result) {
struct node dummy = { NULL, NULL };
struct node *merge_tail = dummy;
int node_count = 0;
while (head1 || head2) {
if (head1) {
COPY(head1, merge_tail->next, allocation_error);
head1 = head1->next;
merge_tail = merge_tail->next;
node_count += 1;
}
if (head2) {
COPY(head2, merge_tail->next, allocation_error);
head2 = head2->next;
merge_tail = merge_tail->next;
node_count += 1;
}
}
*result = dummy->next;
return node_count;
allocation_error:
while (dummy->next) {
struct node *temp = dummy->next;
dummy->next = dummy->next->next;
free(temp);
}
return -1;
}
基本思想是您同时遍历两个输入列表,或者从一个输入和另一个输入将节点复制到输出列表中。此特定实现返回合并列表中节点总数的计数,或者出错时为-1;合并列表的头部通过第三个参数返回。如果输入列表具有不同的长度(在末尾附加了较长列表中的剩余节点),或者如果其中一个或两个输入列表为空,则不会跳闸。复制节点的大部分细节都会在COPY()
宏中计算出来。 dummy
节点避免合并列表的头部是特殊情况。
任何方式,如果构建三个列表的节点属于不同类型,则执行此操作是没有意义的。