0

I try to understand the following algorithm for merging two sorted linked-lsits into one sorted linked-list (taken from here).

I don't understand completly how this code works and be glad for an explanation.

Code:

#define SWAP_PTRS(a, b) do { void *t = (a); (a) = (b); (b) = t; } while (0)

Node* MergeLists(Node* list1, Node* list2) 
{
  Node *list = NULL, **pnext = &list;

  if (list2 == NULL)
    return list1;

  while (list1 != NULL)
  {
    if (list1->data > list2->data)
      SWAP_PTRS(list1, list2);

    *pnext = list1;
    pnext = &list1->next;
    list1 = *pnext;
  }

  *pnext = list2;
  return list;
}
Community
  • 1
  • 1
eggbaz
  • 81
  • 4

3 Answers3

2

At the beggining there are standard tests for NULL parameters which corresponds to the basic case that one list is blank so the other is ordered by default.

The writter does a trick here, each time the next item will be added from the pointer to Node named list1, this happends in the line: *pnext = list1;, whats left is to understand how is it possible to always add from one list, this is done using the SWAP_PTRS macro which plants the list startig with the lower value at list1.

After an update has accured the next Node which should be updated is found using: pnext = &list1->next;. the reason it works is also interesting, since the current updated node has pointed to the current item of list1, the value in its next field is the pointer to the location which should be updated next, by passing the address of this pointer (using &) we are able to change the content of this next item.

This process goes on and on until the item added was the last one on a list. An interesting point here is that there is no edge condition since the removed items are always from list1 which means that list2 cant be empty before list1. When the last item of list1 is added the while loop terminates and the rest of list2 is added to the end of the result list.

antonpuz
  • 3,256
  • 4
  • 25
  • 48
  • Thank you.. it really is confusing and briliant at the same time! – eggbaz Aug 09 '15 at 15:01
  • @eggbaz np. yes it has some neat tricks. I suggest you look closely and make sure u understand all of them and exactly why and how they work – antonpuz Aug 09 '15 at 15:07
1

The algorithm goes as follows:

If list2 is empty, which means that there is only one list, then the algorithm will return list1, which is the merged list. The same test should be done if list1 is empty...

Next, we are looping through both lists together, until we reach the end of list1 or list2. Starting from the first item in each list, We compare the items and add the smaller one to the merged list, and advance in the corresponding list. In the next iteration will compare the first item in one list to the second in the other and so on until we reach the end of one of lists.

After that we simply add the items of the list we didn't reach its end to the merged list

Zachi Shtain
  • 826
  • 1
  • 13
  • 31
1

This example without the swap may be easier to follow.

Node * MergeLists(Node *pSrc1, Node *pSrc2)
{
Node *pDst = NULL;                      /* destination head ptr */
Node **ppDst = &pDst;                   /* ptr to head or prev->next */
    if(pSrc1 == NULL)
        return pSrc2;
    if(pSrc2 == NULL)
        return pSrc1;
    while(1){
        if(pSrc2->data < pSrc1->data){  /* if src2 < src1 */
            *ppDst = pSrc2;
            pSrc2 = *(ppDst = &(pSrc2->next));
            if(pSrc2 == NULL){
                *ppDst = pSrc1;
                break;
            }
        } else {                        /* src1 <= src2 */
            *ppDst = pSrc1;
            pSrc1 = *(ppDst = &(pSrc1->next));
            if(pSrc1 == NULL){
                *ppDst = pSrc2;
                break;
            }
        }
    }
    return pDst;
}

Either of the MergeList functions shown in this thread can be used by this merge sort function that sorts a list using an array of pointer to nodes:

#define NUMLISTS 32                     /* size of array */
Node * SortList(Node *pList)
{
Node * aList[NUMLISTS];                 /* array of lists */
Node * pNode;
Node * pNext;
int i;
    if(pList == NULL)                   /* check for empty list */
        return NULL;
    for(i = 0; i < NUMLISTS; i++)       /* zero array */
        aList[i] = NULL;
    pNode = pList;                      /* merge Nodes into aList[] */
    while(pNode != NULL){
        pNext = pNode->next;
        pNode->next = NULL;
        for(i = 0; (i < NUMLISTS) && (aList[i] != NULL); i++){
            pNode = MergeLists(aList[i], pNode);
            aList[i] = NULL;
        }
        if(i == NUMLISTS)
            i--;
        aList[i] = pNode;
        pNode = pNext;
    }
    pNode = NULL;                       /* merge array into one list */
    for(i = 0; i < NUMLISTS; i++)
        pNode = MergeLists(aList[i], pNode);
    return pNode;
}
rcgldr
  • 27,407
  • 3
  • 36
  • 61