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

    归并排序

      归并排序是采用分治法的一个非常典型的应用。归并排序的思想就是先递归分解数组,再合并数组。

      将数组分解最小之后,然后合并两个有序数组,基本思路是比较两个数组的最前面的数,谁小就先取谁,取了后相应的指针就往后移一位。然后再比较,直至一个数组为空,最后把另一个数组的剩余部分复制过来即可。

    归并排序的分析

    这里写图片描述

    归并排序的实现

    Java版

    public class MergeSort {
     
        /**
         *  * <pre>
         *  * 二路归并
         *  * 原理:将两个有序表合并和一个有序表
         *  * </pre>
         *  *
         *  * @param a
         *  * @param s
         *  * 第一个有序表的起始下标
         *  * @param m
         *  * 第二个有序表的起始下标
         *  * @param t
         *  * 第二个有序表的结束小标
         *  *
         */
        private static void merge(int[] a, int s, int m, int t) {
            int[] tmp = new int[t - s + 1];
            int i = s, j = m, k = 0;
            while (i < m && j <= t) {
                if (a[i] <= a[j]) {
                    tmp[k] = a[i];
                    k++;
                    i++;
                } else {
                    tmp[k] = a[j];
                    j++;
                    k++;
                }
            }
            while (i < m) {
                tmp[k] = a[i];
                i++;
                k++;
            }
            while (j <= t) {
                tmp[k] = a[j];
                j++;
                k++;
            }
            System.arraycopy(tmp, 0, a, s, tmp.length);
        }
     
        public static void mergeSort(int[] a, int s, int len) {
            int size = a.length;
            int mid = size / (len << 1);
            int c = size & ((len << 1) - 1);
            // -------归并到只剩一个有序集合的时候结束算法-------//
            if (mid == 0)
                return;
            // ------进行一趟归并排序-------//
            for (int i = 0; i < mid; ++i) {
                s = i * 2 * len;
                merge(a, s, s + len, (len << 1) + s - 1);
            }
            // -------将剩下的数和倒数一个有序集合归并-------//
            if (c != 0)
                merge(a, size - c - 2 * len, size - c, size - 1);
            // -------递归执行下一趟归并排序------//
            mergeSort(a, 0, 2 * len);
        }
     
        public static void main(String[] args) {
            int[] a = new int[]{ 54,26,93,17,77,31,44,55,20 };
            mergeSort(a, 0, 1);
            System.out.println(Arrays.toString(a));
    
        }
    }
    

    Python版

    def merge_sort(alist):
        if len(alist) <= 1:
            return alist
        # 二分分解
        num = len(alist)/2
        left = merge_sort(alist[:num])
        right = merge_sort(alist[num:])
        # 合并
        return merge(left,right)
    
    def merge(left, right):
        '''合并操作,将两个有序数组left[]和right[]合并成一个大的有序数组'''
        #left与right的下标指针
        l, r = 0, 0
        result = []
        while l<len(left) and r<len(right):
            if left[l] < right[r]:
                result.append(left[l])
                l += 1
            else:
                result.append(right[r])
                r += 1
        result += left[l:]
        result += right[r:]
        return result
    
    alist = [54,26,93,17,77,31,44,55,20]
    sorted_alist = mergeSort(alist)
    print(sorted_alist)
    
    

    时间复杂度

    • 最优时间复杂度:O(nlogn)
    • 最坏时间复杂度:O(nlogn)
    • 稳定性:稳定
  • 相关阅读:
    ubuntu qtcreator 硬件权限问题
    关于LuCi
    npm 使用记录
    ubuntu 下简单录音
    qthread 使用 signal 方法通信
    线程安全笔记一则
    ubuntu 设置 NAT 转发
    debian 中新建或调整 swap 空间
    关于 htonl 和 ntohl 的实现
    shell 调试手段总结
  • 原文地址:https://www.cnblogs.com/yangliguo/p/8320019.html
Copyright © 2011-2022 走看看