堆(以下指最大堆):堆是一个完全二叉树,树中所有的非叶子节点的值均不小于其他孩子节点的值。
堆排序的原理是利用堆的性质,当通过插入元素生成堆后,保证从堆顶摘除的元素(树的根节点)是堆中最大的元素。
以下实现中,首先分配一个线性数组用于堆空间,数组的存放的是连接件的指针,数组的大小是连接件的计数加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