zoukankan      html  css  js  c++  java
  • 归并排序

    图示

    算法描述

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

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

    参考代码

    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);
    }
  • 相关阅读:
    Spark的Shuffle机制
    Map Reduce的代码学习
    本地IDEA跑阿里云服务器Word Count
    HDFS的类学习和API基本操作
    本地IDEA(Windows)访问ECS服务器HBase
    本地IDEA访问ECS服务器HDFS
    阿里云ECS大数据环境搭建
    学会使用vue ui搭建项目
    用vue封装视频预览组件(手机端)
    项目中的部门使用级联选择器,编辑时初始化选中部门解决方案
  • 原文地址:https://www.cnblogs.com/kaituorensheng/p/3644064.html
Copyright © 2011-2022 走看看