在备用位置合并两个链接列表

时间:2015-03-26 17:49:29

标签: c data-structures linked-list

我正在合并两个链接列表,第三个列表包含备用位置的元素,但合并的功能不起作用

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;
    }
}

3 个答案:

答案 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 Alist 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节点避免合并列表的头部是特殊情况。

任何方式,如果构建三个列表的节点属于不同类型,则执行此操作是没有意义的。