基于单链表快排的优化算法

快排大法好,不说日常数据处理的巨大优势,面试时能手写快排更是装X一大利器。
不过传统的快排有一大缺陷:当出现大量相同值或数据已经有序时,由于对相同值的重复递归,排序效率会急剧降低乃至O(N^2)。
为避免此情况笔者编写了快排PRO 优化算法(三明治法):

将传统快排的二分法(小于中点值、大于等于中点值)更改为三分(小于中点值、等于中点值、大于中点值)。且对等于中点值部分不再递归,因此即使存在大量重复数据依然能保持O(nlogn)的时间复杂度。

代码实现如下:

#define NODE 要排序的结构体名字
#define ATTR 这里填要排序的属性
#define NEXT 这里填存储下一个结点的变量名
/**
   参数一为待排序的链表头结点
   参数二返回的为排序以后的尾节点地址
*/
NODE* QUICK_SORT (NODE* SOUR,NODE **REAR)
{
    if(SOUR==NULL)  //为空结点
    {
        //此情况只有一种可能:要排序的链表是一个空链表
        return NULL;
    }
    NODE *MID=SOUR,*L=NULL,*R=NULL;    //中点\左侧\右侧
    NODE *RR,*LR,*MR=SOUR;  //左侧尾结点,右侧尾结点,中点链
    NODE *TEMP,*P=SOUR->NEXT;   //定位主串剩余串
    while(P)                //循环拆解原串
    {
        TEMP=P->NEXT;
        if(P->ATTR<MID->ATTR) /**这里填排序规则(默认字符串排序strcmp(P->ATTR,MID->ATTR)<0)*/
        {
            if(L==NULL)     //L为空串
            {
                L=LR=P;
                L->NEXT=NULL;
            }else
            {
                P->NEXT=L;
                L=P;
            }
        }else if(P->ATTR>MID->ATTR) //排序规则+1,说明排在MID后
        {
            if(R==NULL)
            {
                R=RR=P;
                R->NEXT=NULL;
            }else
            {
                P->NEXT=R;
                R=P;
            }
        }else   //说明值与MID相同
        {
            P->NEXT=MR;
            MR=P;
        }
        P=TEMP;
    }
    MID->NEXT=NULL; //防止排序结束后尾结点不为空
    //拆解完毕,进行递归拆解
    if(L!=NULL&&R!=NULL)
    {
        L=QUICK_SORT(L,&LR);
        R=QUICK_SORT(R,&RR);
        //合并已有序的链表
        LR->NEXT=MR;
        MID->NEXT=R;
        *REAR=RR;   //上传尾结点
        return L;
    }else if(R!=NULL)
    {
        R=QUICK_SORT(R,&RR);
        MID->NEXT=R;
        *REAR=RR;
        return MR;
    }else if(L!=NULL)
    {
        L=QUICK_SORT(L,&LR);
        LR->NEXT=MR;
        *REAR=MID;
        return L;
    }
    //说明只有MID一个元素
    *REAR=MID;
    return MID;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值