答案 0 :(得分:2)
在开始时,有一些NULL参数的标准测试,这些测试对应于一个列表为空白而另一个列表默认排序的基本情况。
写入器在这里做了一个技巧,每次下一个项目将从指向节点名为list1的指针添加,这发生在行textSize
,剩下的是了解如何始终添加从一个列表中,这是使用SWAP_PTRS宏完成的,该宏在onDraw
处设置了较低值的列表startig。
更新完成后,使用以下内容找到应更新的下一个节点:*pnext = list1;
。它工作的原因也很有趣,因为当前更新的节点已指向list1的当前项,其下一个字段中的值是指向下一个应该更新的位置的指针,方法是传递该指针的地址(使用& ;)我们可以更改下一个项目的内容。
此过程一直持续到添加的项目是列表中的最后一项。这里有一个有趣的观点是没有边缘条件,因为删除的项总是来自list1,这意味着list2在list1之前不能为空。当添加list1的最后一项时,while循环终止,list2的其余部分被添加到结果列表的末尾。
答案 1 :(得分:1)
算法如下:
如果list2
为空,这意味着只有一个列表,则算法将返回list1
,这是合并列表。如果list1
为空,则应进行相同的测试...
接下来,我们将两个列表一起循环,直到我们到达list1
或list2
的末尾。从每个列表中的第一个项目开始,我们比较项目并将较小的项目添加到合并列表,并在相应的列表中前进。在下一次迭代中,将比较一个列表中的第一个项目与另一个列表中的第二个项目,依此类推,直到我们到达其中一个列表的末尾。
之后,我们只需添加列表中的项目,但我们没有达到合并列表的结尾
答案 2 :(得分:1)
这个没有交换的例子可能更容易理解。
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;
}
此线程中显示的任何一个MergeList函数都可以由此合并排序函数使用,该函数使用指向节点的指针数组对列表进行排序:
#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;
}