排序算法-歸併排序

歸併排序也是一個比較快速的排序算法,其思想是運用分治的思想,先對要排序的數進行分,每次從中間分成兩部分,然後知道分成最小,然後在把他們合起來,邊合起來邊排序,最後有序,每次分的複雜度是log(n),然後合起來變成有序的複雜度O(n),總的複雜度O(n*logn),速度比較快,但是每次合併要佔用額外O(n)的空間,如果用鏈表實現的話可以避免,同時歸併排序可用來求逆序對。

比如給這樣一組數
3 5 2 10 4 6 7
首先分 3 5 2 | 10 4 6 7
繼續分 3 | 5 2 | 10 4 | 6 7
繼續分 3 | 5 | 2 | 10 | 4 | 7
然後開始合併,並排序
第一次:3 | 2 5 | 4 10 | 6 7
第二次: 2 3 5 | 4 6 7 10
第三次:2 3 4 5 6 7 10

數組實現的版本:

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
const int N = 1001000;
int a[N];
int b[N];
void Merge(int l,int r)
{
    if((r-l)==1 || l==r)
        return ;
    int mid = (l+r)/2;
    Merge(l,mid);
    Merge(mid,r);
    vector<int> tmp;
    int i = l,j = mid,cnt = 0;
    while(i<mid && j<r)
    {
        if(a[i]<=a[j])
        {
            b[cnt++] = (a[i]);
            i++;
        }
        else
        {
            b[cnt++] = (a[j]);
            j++;
        }
    }
    while(i<mid)
    {
        b[cnt++] = (a[i]);
        i++;
    }
    while(j<r)
    {
        b[cnt++] = (a[j]);
        j++;
    }
    for(int i=0;i<cnt;i++)
    {
        a[l+i] = b[i];
    }
}
int main()
{
    //freopen("Input.txt","r",stdin);
    int n,k;
    while(~scanf("%d%d",&n,&k))
    {
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        Merge(0,n);
        for(int i=0;i<n;i++)
            printf("%d ",a[i]);
        for(int i=n-1;i>=(n-k);i--)
            printf("%d%c",a[i],i==(n-k)?'\n':' ');
    }
    return 0;
}

鏈表實現的版本,不需要額外的內存:(提交到hdoj上面超時了,不知道爲什麼會慢)

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

struct ListNode
{
    int val;
    ListNode *next;
};
ListNode *Creat(int n)
{
    ListNode *head = new ListNode;
    scanf("%d",&head->val);
    head->next = NULL;
    ListNode *p = head;
    n--;
    while(n--)
    {
        ListNode *tmp = new ListNode;
        scanf("%d",&tmp->val);
        tmp->next = NULL;
        p ->next = tmp;
        p = p->next;
    }
    return head;
}
int v[1010000];
void print(ListNode *head)
{
    int cnt = 0;
    while(head!=NULL)
    {
        v[cnt++] = (head->val);
        head = head->next;
    }
}
ListNode *Merge(ListNode *head)
{
    if(head==NULL || head->next==NULL)
        return head;
    ListNode *fast = head,*flaw = head;
    while(fast->next!=NULL && fast->next->next!=NULL)
    {
        flaw = flaw->next;
        fast = fast->next;
        if(fast->next!=NULL)
            fast = fast->next;
    }
    fast = flaw->next;
    flaw->next = NULL;
    flaw = Merge(head);  //SB
    fast = Merge(fast);
    ListNode *root = new ListNode;
    ListNode *p = root;
    while(flaw!=NULL && fast!=NULL)
    {
        if(flaw->val<=fast->val)
        {
            p->next = flaw;
            flaw = flaw->next;
        }
        else
        {
            p->next = fast;
            fast = fast->next;
        }
        p = p->next;

    }
    while(flaw!=NULL)
    {
        p->next = flaw;
        flaw = flaw->next;
        p = p->next;
    }
    while(fast!=NULL)
    {
        p->next = fast;
        fast = fast->next;
        p = p->next;
    }
    p = root->next;
    delete[] root;
    return p;
}
void dele(ListNode *head)
{
    while(head!=NULL)
    {
        ListNode *tmp = head;
        head = head->next;
        delete[] tmp;
    }
}
int main()
{
//    freopen("Input.txt","r",stdin);
    int n,k;
    while(~scanf("%d%d",&n,&k))
    {
        ListNode *head = Creat(n);
        head = Merge(head);
        print(head);
        dele(head);
        for(int i=n-1;i>=(n-k);i--)
            printf("%d%c",v[i],i==(n-k)?'\n':' ');
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章