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

来源:互联网 发布:诺梵面膜 知乎 编辑:程序博客网 时间:2024/05/14 11:35

快排大法好,不说日常数据处理的巨大优势,面试时能手写快排更是装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;}
0 0
原创粉丝点击