在nlog(n)时间里对单链表排序

两个思路:

    快速排序(逻辑是自顶向下)。先划分排序(一次确定一个位置),再对左边右边分别排序,一直到最小粒度;

    归并排序(逻辑自下而上) 先一直到最小粒度,然后两两合并排序,最合合成排序好的链表;

1,快速排序

        1)根据划分位置将链表 分成两部分(左边小于,右边大于),递归:QuickSort(head,end),时间复杂度logn

                void QuickSort(ListNode *head ,ListNode *end){

                    if (head!=end){

                            ListNode *pivot=Getpartion(head , end);

                            QuickSort(head,pivot);

                            QuickSort(pivot->next,end);

                    }

                }

         调用    QuickSort(head, NULL)   呼应后面的j!=end,方便处理最后一个节点

        2)得到划分的位置:Getpartion(head,end),这里取第一个节点作为默认的划分节点,划分之后,右边全小于该节点,左边全大于该节点,时间复杂度o(n)

                pivot x x x x x x x x x x x x

                左边   <=  pivot   <= 右边

                ListNode *Getpartion(ListNode *head, ListNode *end){

                        ListNode *i,*j;

                        if (head ==Null || end == Null) return;

                        else{     #思想:i,j。i前面的节点包含该节点 都<= pivot , j与i之间的都是>pivot

                            int key=head->vaule;    i=head;    j=head-<next;

                            while (j!=end){

                                if (j->vaule<key){    

                                    i=i->next;                #从第二个节点开始,首节点(这里指的划分节点)不动,最后和i交换

                                    swap(i->vaule,j->vaule);

                                }

                                j=j->next;

                            }

                            swap(i->vaule,key);        #将首节点放在应有的位置上

               }

2,归并排序

    1)将链表均分成两部分,关键是找到中间节点(两个指针,一个走一步,一个走两步);

        ListNode* Merge(ListNode *head){            #这里必须返回节点,因为原来的链表的节点被打乱了重新排序了,区别上面只是交换值,如果这里对两个链表合并排序用交换值得办法,必须牺牲空间o(n),有序链表合并排序不至于这样做

                ListNode *i,*j;

                i=head;

                h-head;

                if (head == end) return;

                while(j!=end){i=i->next;j=j->next; j=j->next; }

                j=i->next;

                i->next=Null;                                    #这里使右边节点的最后一个节点指向Null,左边的节点默认指向Null

                                                                            会方便 后面是两个尾部指向Null的链表合并

                ListNode *left=Merge(head);

                ListNode *right=Merge(j);

                ListNode *sortlist=MergeSort(left,right);   #将两条有序的链表合并,返回一条排好序的链表

                return sortlist

        }   

    2)两个有序链表的合并排序;

        ListNode* MergeSort(ListNode *right ,ListNode *left){

            ListNode *i,*j,*a;

            i=right;

            j=left;

            if (i>value>j->value) { a=left ;  j=j->next;}

            else{a=right;i=i->next;  }

            while(i!=Null && j!=Null}{

                if (i->value>j->value)  {a->next=j ; a=a->next ; j=j->next;}

                else{ a->next=i ; a=a->next ; i=i->next; }

            if (i==Null) while(j!=Null) { a->next=j ; a=a->next ; j=j->next;}

            else(j==Null) while(i!=Null) {a->next=i;a=a->next;i=i->next;}

            return a;

    }

                    

猜你喜欢

转载自blog.csdn.net/asdasdasdasasd1111/article/details/80784937