歸併排序也是一個比較快速的排序算法,其思想是運用分治的思想,先對要排序的數進行分,每次從中間分成兩部分,然後知道分成最小,然後在把他們合起來,邊合起來邊排序,最後有序,每次分的複雜度是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;
}