部分文章内容为公开资料查询整理,原文出处可能未标注,如有侵权,请联系我,谢谢。邮箱地址:gnivor@163.com ►►►需要气球么?请点击我吧!

*LeetCode-148.Sort List(链表排序)

Sort a linked list in O(n log n) time using constant space complexity.

对链表排序,要达到 O(n log n)的时间复杂度,可使用归并排序

过程分为两部分:1.递归的进行排序;  2. 合并

有一个问题:怎么找链表的中点? 采用快慢指针的方法。快指针一次移动两个位置,慢指针一次移动1个位置。 当快指针或快指针的下一位指向空时,慢指针就指向中间。

将前后两段链表断开,然后分别对 head开始到slow 和slow.next开始到最后的两个链表进行排序,然后合并

//对链表进行排序,采用归并排序
public static ListNode sortList(ListNode head) {
    if(head == null||head.next == null)
        return head;
    ListNode fast = head.next; //注意fast初始就要比slow快,因为后半部分是从slow.next开始的,而不是slow
    ListNode slow = head;
    while(fast!=null &&  fast.next != null){
        fast = fast.next.next;
        slow = slow.next;
    }    
    ListNode sh = sortList(slow.next);
    slow.next  = null;
    return merge(sortList(head),sh);
}

//将两部分合并
public static ListNode merge(ListNode h1, ListNode h2) { //合并两个部分
    ListNode head = new ListNode(0);
    ListNode p = head;
    while(h1!=null&&h2!=null){
        if(h1.val<h2.val){
            p.next = h1;
            h1 = h1.next;
        }else{
            p.next = h2;
            h2 = h2.next;
        }
        p = p.next;
    }
    if(h1!=null){
        p.next = h1;
    }
    if(h2!=null){
        p.next = h2;
    }
    return head.next;
}

 

补充

(算法课堂作业:)

归并-最长无逆序子序列划分-链表-无递归

/*归并排序
划分时按最长无逆序子序列
链表实现
无递归*/

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;

typedef struct Node{    //带头结点的链表
    int data;
    struct Node* next;
} LNode, *Linklist;


//划分函数,获得一个有序的序列
void Mdivide(Linklist kaishi,LNode* &st,LNode* &en){    //st指向第一个 en指向最后一个
    LNode *p=kaishi;        //移动的指针
    if(kaishi!=NULL){
        st=kaishi; en=kaishi;
    }
    else{    //如果开始点就为空,则这部分的起始与结束均为空
        st=NULL;en=NULL;
        return;
    }
    p=kaishi->next;
    while(p!=NULL&&(p->data>=en->data)){    //寻找无逆序子序列的结束点
        en=p;
        p=p->next;
    }
}


//Merge函数将两个有序部分合并
void Merge(LNode* &pre,LNode* st1,LNode* en1,LNode* st2,LNode* en2 ){
    LNode temp ;
    LNode t_en1,t_en2;     //停止标记
    t_en1.next=en1->next;    //
    t_en2.next=en2->next;    //
    temp.next=en2->next;    //临时存放第二组的结束节点,就是下组要合并的pre指针

    while(st1!=t_en1.next && st2!=t_en2.next){
        if(st1->data < st2->data){
            pre->next = st1;
            pre=pre->next;
            st1 = st1->next;
        }else{
            pre->next = st2;
            pre=pre->next;
            st2 = st2->next;
        }
    }

    while(st1!=t_en1.next){    //合并剩余部分
        pre->next=st1;
        pre=pre->next;
        st1=st1->next;
    }

    while(st2!=t_en2.next){    //合并剩余部分
        pre->next=st2;
        pre=pre->next;
        st2=st2->next;
    }
    pre->next=temp.next;    //与后面的节点连接

}


//排序函数
void Mergesort(Linklist l ){
    LNode *st1, *en1, *st2, *en2;
    LNode *templ;    //指向每一部分的开始
    LNode *pre;
    int flag=0;
    while(flag!=1){    //结束条件
        templ = l->next;
        pre = l;    //指向头指针(带头结点)
        while(pre->next!=NULL){
            templ=pre->next;
            Mdivide(templ,st1,en1);//获得第一个划分
            if(templ==l->next&&en1->next==NULL){    //如果本次划分开始前节点为首节点,尾结点的next为空,结束排序
                flag=1;break;
            }

            templ=en1->next;    //指向第二部分的开始
            Mdivide(templ,st2,en2);//获得第二个部分


            //对两种不同的划分状况进行不同方式的合并
            if(st1!=NULL&&st2!=NULL){    //有两组无逆序子序列
                Merge(pre,st1,en1,st2,en2);
            }else {//只有一组无逆序子序列
                break;

            }
        }
    }
}

int main(){
    Linklist l;
    //创建并初始化链表
//    int num[]={1,2,3,4,5,6,7,8,9};
    int num[] = {34,5, 20, 7,2,1, 8, 17,19,11,90,18, 28};
    int i;
    l = (LNode*)malloc(sizeof(struct Node));
    LNode* p = l;
    for(i=0;i<sizeof(num)/sizeof(int);i++){
        LNode* n = (LNode*)malloc(sizeof(Node));
        n->next = NULL;
        n->data = num[i];
        p->next = n;
        p = n;
    }

    //打印初始链表
    LNode *pri=l->next;
    while(pri!=NULL){
        cout<<pri->data<<endl;
        pri=pri->next;
    }
    cout<<"原始元素输出完毕!"<<endl;

    Mergesort(l);    //归并排序

    cout<<"输出排序后的元素"<<endl;
    pri=l->next;
    while(pri!=NULL){
        cout<<pri->data<<endl;
        pri=pri->next;
    }
    return 0 ;
}

 

posted @ 2015-09-17 13:47  流了个火  阅读(127)  评论(0)    收藏  举报
►►►需要气球么?请点击我吧!►►►
View My Stats