堆(以下指最大堆):堆是一個完全二叉樹,樹中所有的非葉子節點的值均不小於其他孩子節點的值。堆排序的原理是利用堆的性質,當通過插入元素產生堆後,保證從堆頂摘除的元素(樹的根節點)是堆中最大的元素。以下實現中,首先分配一個線性數組用於堆空間,數組的存放的是串連件的指標,數組的大小是串連件的計數加1,[1…n]存放堆中的串連件指標,[0]存放出入堆的串連件指標。在插入堆的過程中,首先在數組[0]位存放串連件指標,通過比較插入位置的父節點,順次比較到根節點,直至找到大於該節點的父節點為止,然後在子位置插入該節點。在刪除堆的過程中,依次取出堆頂元素[1]位到[0]位,從堆中摘除串連件,插入串連件鏈表的首位,然後將堆底的元素拷入[0]位,重新調整堆,從根節點開始,依次尋找他的雙子節點,直至找到小於該節點的子節點,然後在父位置插入該節點。串連件值的比較通過回呼函數實現。 XDL_API void HeapSortLink(LINKPTR root,LinkSortCall pf,void* parm);
/**//*
功能:對鏈表進行堆排序
參數:root為根串連件指標,pf為排序回呼函數,param為回調參數
返回:無
*/
//入堆調整
void _AdjustInsert(LINKPTR* pa,int n,LinkSortCall pf,void* parm)
...{
while(n > 1 && (*pf)(pa[0],pa[n/2],parm) > 0)
...{
pa[n] = pa[n/2];
n /= 2;
}
pa[n] = pa[0];
}
//出堆調整
void _AdjustDelete(LINKPTR* pa,int n,LinkSortCall pf,void* parm)
...{
int i;
i = 2;
while(i <= n)
...{
if(i < n && (*pf)(pa[i],pa[i+1],parm) < 0)
i ++;
if((*pf)(pa[0],pa[i],parm) >= 0)
break;
pa[i/2] = pa[i];
i *= 2;
}
pa[i/2] = pa[0];
}
//堆排序
void HeapSortLink(LINKPTR root,LinkSortCall pf,void* parm)
...{
LINKPTR* pa;
int count,i;
LINKPTR plk;
count = LinkCount(root);
if(count < 2)
return;
//alloc heap for sorting link nodes
pa = (LINKPTR*)XdlAlloc(count + 1,sizeof(LINKPTR));
//insert into heap
plk = GetFirstLink(root);
for(i=1;i<=count;i++)
...{
pa[0] = plk;
_AdjustInsert(pa,i,pf,parm);
plk = GetNextLink(plk);
}
//delete from heap,then order insert into link list
while(count)
...{
plk = pa[1];
InsertLink(root,LINK_FIRST,DeleteLink(root,plk));
pa[0] = pa[count];
count --;
_AdjustDelete(pa,count,pf,parm);
}
//free heap
XdlFree(pa);
}
collected by barenx