需要有关伪代码/算法的帮助 - 链接列表合并

时间:2013-08-15 05:34:27

标签: c merge linked-list pseudocode

我在下面的代码之一中看到下面的代码作为在C中合并两个已排序列表的答案。

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

任何人都可以向我解释这个伪代码文本吗?无法在相同答案下发表评论,因此发布为新问题。

1 个答案:

答案 0 :(得分:0)

首先是预处理器指令:

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

这意味着,当预处理器正在准备翻译单元进行编译时,只要遇到SWAP_PTRS(a, b),它就会用

替换它。
do { void *t = (a); (a) = (b); (b) = t; } while (0)

让我们打开它。它只是交换一对指针ab的函数。

由于循环是do ... while循环,它将在测试循环条件之前执行。在循环内部,声明了一个新的void指针t。这与任何类型的指针都兼容,因此无论指针ab是什么类型,它们都与t兼容。

然后是标准交换:

  1. a分配给t
  2. b分配给a
  3. t分配给b
  4. 交换后,检查循环条件。由于它是0,因此条件的计算结果为false,do ... while循环结束。换句话说,它只会被执行一次,这就是所需要的,因为目标只是交换一对指针。

    这是实际MergeLists函数的伪代码。

    Algorithm MergeLists
    Receives: pointer to head node of linked list list1
        pointer to head node of linked list list2
    Returns: pointer to head node of merged list
    
    1. Declare pointer list for merged list and initialize to NULL
    2. Declare pointer to pointer pNext and initialize it to the address of the merged list
    3. if (list2 is NULL)  // empty list
        3.1 return list1   // nothing to merge
    4. loop while list1 is not NULL
        4.1 if (data in list1 is greater than data in list2)
            4.1.1 swap list1 and list2
        4.2 set dereferenced value of pNext to list1
        4.3 set pNext to the address of the next node in list1
        4.4 set list1 to the dereferenced value of pNext // same as list1 = list1->next
    5. end loop for list1
    6. set the dereferenced value of pNext to list2
    7. return list
    

    这是一个相当困难的逻辑。繁重的一切都在while循环中。这是一个细分:

    链接列表节点有两个指针,list1list2。 while循环中的第一步将具有较小数据值的节点设置为list1,将另一个节点设置为list2。如果需要,可以使用SWAP_PTRS宏设置。

    开始时,*pNext指向具有较小数据值的list1。第一次循环,因为*pNext也是list(合并列表),list现在也指向同一个地方。

    下一步将pNext重置为list1中下一个节点的地址。但是,这不会改变list指向的位置(pNext是一个两级指针,在此步骤中我们正在改变pNext所指向的位置,即不是* pNext指向的位置) 。

    然后list1设置为*pNext,即list1->next

    然后循环进入下一次迭代,使用这个新的list1。

    所以基本上它只是不断检查列表头部节点的数据值,并将具有较小数据值的节点添加到合并列表的末尾。当它到达任一列表的末尾时,循环将终止,而另一个列表中的其余节点将附加到合并列表的末尾。

    希望这是有道理的!这是一个非常漂亮的解决方案,老实说,它比用文字解释要容易得多。