C 链表上自底向上的合并排序
自底向上的合并排序处理大小为1的每个元素的列表,并反复地前后合并子列表,直到它们按顺序排序。这使得使用自下而上的合并排序对链表进行排序非常有吸引力,因为它们已经“分离” 我试图用C语言实现自底向上的合并排序,并意识到有多种方法可以实现自底向上的合并排序;特别是,我正在使用这种方法:C 链表上自底向上的合并排序,c,algorithm,sorting,merge,C,Algorithm,Sorting,Merge,自底向上的合并排序处理大小为1的每个元素的列表,并反复地前后合并子列表,直到它们按顺序排序。这使得使用自下而上的合并排序对链表进行排序非常有吸引力,因为它们已经“分离” 我试图用C语言实现自底向上的合并排序,并意识到有多种方法可以实现自底向上的合并排序;特别是,我正在使用这种方法: 将单个列表插入队列 将前两个列表出列并合并它们 将合并的列表排队(合并的项目转到末尾) 重复步骤1-3,直到它们按顺序排列 然而,我正在努力实现以下目标: 合并链接列表而不使用额外的O(n)空间(如果可能) 因此
- 合并链接列表而不使用额外的O(n)空间(如果可能)
- 如何在C语言中正确实现这一点?(特别是:重复出列和入列过程直到完全排序的处理过程)如何知道整个队列是否处于排序顺序?我正在考虑在列表中跟踪*头指针
- 在这种情况下,合并排序是否稳定?为什么?
- 自下而上合并排序的运行时间仍然是O(nlogn)。但是,这种自底向上的合并排序是否使用O(n)空间?假设我们实现的链表已经是一个队列李>
- 额外问题:是否有更好的替代方案在链表上实现自底向上的合并排序李>
有一个聪明的方法,它使用一个固定大小的数组(通常是26或32个大小)指向节点的指针数组,一些指向节点的工作本地指针,以及一个标准的mergelists()函数,该函数合并两个已排序的列表,并且需要处理空列表以简化主代码。将节点合并到数组中,然后将数组合并到单个排序列表中。这一逻辑的第一部分是:
// initialize array[] to all NULLs
while(plist != NULL){
pmerge = plist;
plist = plist->next;
pmerge->next = NULL;
for(i = 0; i < array size; i++){
if(array[i] == NULL)
break;
pmerge = mergelists(array[i], pmerge);
array[i] = NULL;
}
if(i == array size)i--;
array[i] = pmerge;
}
//将数组[]初始化为所有空值
while(plist!=NULL){
pmerge=plist;
plist=plist->next;
pmerge->next=NULL;
对于(i=0;i<数组大小;i++){
if(数组[i]==NULL)
打破
pmerge=mergelists(数组[i],pmerge);
数组[i]=NULL;
}
如果(i==数组大小)i--;
数组[i]=pmerge;
}
列表的大小随着i的增加而加倍,数组[i]要么为NULL,要么指向一个包含2个幂i节点的列表
然后数组被合并到一个列表中,同样只需一个循环和对mergelists()的调用。看看你是否能理解这一部分。我对(4)的工作原理很感兴趣。当您不知道列表A的长度时,如何在第二关中找到列表B?@sp2danny:通过将
item->data
与item->next->data
进行比较,与合并中使用的函数相同。谢谢您的回答@CiaPan,我只是想知道你的描述是否是自然合并排序的修改版本?如果我错了,请更正。@sp2danny(编辑失败后重复),方法是将item->data
与item->next->data
与合并中使用的相同函数进行比较。只需扫描列表,比较每两个连续项,找到第一个子列表的结尾,然后取消链接(拆分列表)。然后重复此操作以获取第二个子列表。合并商店。重复此操作以取消第三和第四个子列表的链接。合并,存储。依此类推,直到输入耗尽。重复,直到只有一个子列表。@Arial是的,它是。见维基百科。