C 需要伪代码/算法的帮助-链表合并

C 需要伪代码/算法的帮助-链表合并,c,merge,linked-list,pseudocode,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 (lis

在一篇文章中,我看到下面的代码是用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;
}

有人能把这解释成伪代码文本吗?无法在同一答案下发表评论,因此作为新问题发布。

首先有一个预处理器指令:

#定义交换ptr(a,b)do{void*t=(a);(a)=(b);(b)=t;}而(0)

这意味着,当预处理器准备编译翻译单元时,每当遇到
SWAP\u PTRS(a,b)
时,它都将替换为

do { void *t = (a); (a) = (b); (b) = t; } while (0)
让我们把它打开。它只是一个交换一对指针
a
b
的函数

因为循环是一个
do。。。当
循环时,它将在测试循环条件之前执行。在循环内部,声明了一个新的
void
指针
t
。这与任何类型的指针都兼容,因此无论
a
b
是哪种类型的指针,它们都与
t
兼容

那么这就是标准的互换:

  • a
    分配给
    t
  • b
    分配给
    a
  • t
    分配给
    b
  • 交换后,将检查循环条件。由于它是
    0
    ,因此条件的计算结果为false,
    do。。。而
    循环结束。换句话说,它将被执行一次,而且只执行一次,这是需要的,因为目标只是交换一对指针

    下面是实际的
    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
    
    这是很难遵循的逻辑。当循环时,重物都在
    循环中。下面是一个细分:

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

    开始时,
    *pNext
    指向此数据值较小的
    list1
    。第一次通过循环时,由于
    *pNext
    也是
    list
    (合并列表),
    list
    现在也将指向相同的位置

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

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

    然后循环使用这个新列表1进入下一个迭代

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


    希望这有意义!这是一个很好的解决方案,而且说实话,画出来要比用语言解释容易得多

    为什么要为如此迟钝的代码而烦恼呢?有很多实现(包括栈上溢出)清楚地表达了正在发生的事情。我对其他实现已经很清楚了,我也写了一个实现。但这一个用指针对指针的方式吸引了我的眼球,所以我想理解。。。您正在尝试交换指针?使用
    ^
    这个…是的,我希望能看到这个图表:)不管怎样,你的努力让我的头脑变得更清晰了。我认为真正难以理解和解释的部分是:如果
    pNext
    是指向列表节点的指针,那么
    *pNext
    ,即解引用值,是指向列表节点的指针。