归并排序

图示

算法描述

把待排序序列分为若干个有序的子序列,再把有序的子序列合并为整体有序序列

  • 申请空间,使其大小为两个已经排好序的数组的长度之和
  • 把两个有序的数组通过比较桉顺序放到申请的空间中
  • 把在申请空间上存放的元素复制到原数组相应的位置上

参考代码

void merge(int *a, int beg, int mid, int end)
{
    int *p = new int[end - beg + 1];
    int i = beg, j = mid+1, k = 0;
    for (; i <= mid && j <= end;)
    {
        if (a[i] < a[j])
        {
            p[k++] = a[i++];
        }
        else
        {
            p[k++] = a[j++];
        }
    }
    while (i <= mid)
        p[k++] = a[i++];
    while (j <= end)
        p[k++] = a[j++];
    for (i = 0; i < k; ++i)
        a[beg + i] = p[i];
    delete []p;
}

void mergeSort(int *a, int beg, int end)
{
    if (a == NULL || beg >= end)
        return;
    else if (beg + 1 == end)
    {
        if (a[beg] > a[end])
            swap(a[beg], a[end]);
    }
    else
    {
        int mid = beg + (end - beg) / 2;
        mergeSort(a, beg, mid);
        mergeSort(a, mid + 1, end);
        merge(a, beg, mid, end);
    }
}

测试

#include <iostream>
using namespace std;

void merge(int *a, int beg, int mid, int end)
{
    int *p = new int[end - beg + 1];
    int i = beg, j = mid+1, k = 0;
    for (; i <= mid && j <= end;)
    {
        if (a[i] < a[j])
        {
            p[k++] = a[i++];
        }
        else
        {
            p[k++] = a[j++];
        }
    }
    while (i <= mid)
        p[k++] = a[i++];
    while (j <= end)
        p[k++] = a[j++];
    for (i = 0; i < k; ++i)
        a[beg + i] = p[i];
    delete []p;
}

void mergeSort(int *a, int beg, int end)
{
    if (a == NULL || beg >= end)
        return;
    else if (beg + 1 == end)
    {
        if (a[beg] > a[end])
            swap(a[beg], a[end]);
    }
    else
    {
        int mid = beg + (end - beg) / 2;
        mergeSort(a, beg, mid);
        mergeSort(a, mid + 1, end);
        merge(a, beg, mid, end);
    }
}

void tranverse(int *a, int len)
{
    for(int i = 0; i < len; ++i)
    {
        cout << a[i] << " ";
    }
    cout << endl;
}
int main()
{
    int a[] = {3, 9, 0, 1, 3, 2, 2, 7};
    int len =  sizeof(a) / sizeof(int);
    tranverse(a, len);
    mergeSort(a, 0, len-1);
    tranverse(a, len);
}
View Code

复杂度

  • 空间复杂度:O(n)
  • 时间复杂度: 最好 最坏 平均 统统O(nlogn)

稳定性

   稳定

应用

数组中的逆序对。例如{7,5,6,4}的逆序对有(7,5)(7,6)(7,4)(5,4)(6,4)总共5个

思路

其实就是归并排序中,两个数字交换的次数 + 归并有序数组时后一个数组元素大于前一个数字元素的个数之和。

参考代码

数组

#include <iostream>
using namespace std;
int num = 0;
void Merge(int *a, int left, int mid, int right)
{
    int *tmp = new int[right - left + 1];
    int i, j, k;
    for(i = left, j = mid+1, k = 0; i <= mid && j <= right;)
    {
        if(a[i] <= a[j])
            tmp[k++] = a[i++];
        else
        {
            tmp[k++] = a[j++];
            num += (mid - i + 1);
        }
    }
    while(i <= mid)
        tmp[k++] = a[i++];
    while(j <= right)
        tmp[k++] = a[j++];
    for(i = 0; i < right - left + 1; ++i)
        a[left + i] = tmp[i];
    delete []tmp;
}

void MergeSort(int *a, int left, int right)
{
    if(left == right)
        return;
    if(left + 1 == right)
    {
        if(a[left] > a[right])
        {
            int tmp = a[left];
            a[left] = a[right];
            a[right] = tmp;
            ++num;
        }
    }
    else
    {
        int mid = left + (right - left) / 2;
        MergeSort(a, left, mid);
        MergeSort(a, mid + 1, right);
        Merge(a, left, mid, right);
    }
}

int main()
{
    int a[] = {8, 3, 3, 4, 1};
    int size = sizeof(a) / sizeof(*a);
    MergeSort(a, 0, size - 1);
    for(int i = 0; i < size; ++i)
    {
        cout << a[i] << endl;
    }
    cout << "num:" << num << endl;
}

链表

#include <iostream>
using namespace std;
struct ListNode 
{
    int val;
    ListNode *next;
    ListNode(int v) : val(v), next(NULL) {};
};
    
void Traverse(ListNode *root)
{
    while (root != NULL)
    {
        cout << root->val << " ";
        root = root->next;
    }
    cout << endl;
}

ListNode *Merge(ListNode *pa, ListNode *pb)
{
    if (pa == NULL)
        return pb;
    if (pb == NULL)
        return pa;
    ListNode *rev = NULL;
    if (pa->val < pb->val)
    {
        rev = pa;
        rev->next = Merge(pa->next, pb);
    }
    else
    {
        rev = pb;
        rev->next = Merge(pa, pb->next);
    }
    return rev;
}

void FrontBackSplit(ListNode *root, ListNode *&pa, ListNode *&pb)
{
    ListNode *fast;
    ListNode *slow;
    if (root == NULL || root->next == NULL)
    {
        pa = root;
        pb = NULL;
    }
    fast = root->next;
    slow = root;
    while (fast != NULL)
    {
        fast = fast->next;
        if (fast != NULL)
        {
            fast = fast->next;
            slow = slow->next;
        }
    }
    pa = root;
    pb = slow->next;
    slow->next = NULL;
}

void Mergesort(ListNode *&root)
{
    if (root == NULL || root->next == NULL)
        return;
    ListNode *pa;
    ListNode *pb;
    FrontBackSplit(root, pa, pb);
    Mergesort(pa);
    Mergesort(pb);
    root = Merge(pa, pb);
}

int main()
{
    ListNode *root = new ListNode(0);    
    ListNode *p1 = new ListNode(1);    
    ListNode *p2 = new ListNode(0);    
    ListNode *p3 = new ListNode(3);    
    ListNode *p4 = new ListNode(4);    
    ListNode *p5 = new ListNode(8);    
    ListNode *p6 = new ListNode(6);    
    ListNode *p7 = new ListNode(7);    
    ListNode *p8 = new ListNode(2);    
    ListNode *p9 = new ListNode(2);    
    root->next = p1;
    p1->next = p2;
    p2->next = p3;
    p3->next = p4;
    p4->next = p5;
    p5->next = p6;
    p6->next = p7;
    p7->next = p8;
    p8->next = p9;
    Traverse(root);
    Mergesort(root);
    Traverse(root);
}

 

posted @ 2014-04-03 22:45  jihite  阅读(473)  评论(0编辑  收藏  举报