链表堆排序

本文介绍了一种使用堆排序算法对链表进行排序的方法。首先,通过分配线性数组创建堆空间,然后将连接件指针插入堆中,并通过比较调整堆结构。在删除过程中,取出堆顶元素并重新调整堆。连接件的比较通过回调函数实现,整个过程包括入堆调整和出堆调整两个关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值