归并排序(java实现)

1.在讲归并排序之前,我们先复习一下数据结构的基础知识

       1.数据元素是数据的基本单位,一个数据元素可以是一个不可分割的原子项,也可由多个数据项组成。

      2. 数据的逻辑结构主要可分为3种:线性结构(定义数据元素之间是线性关系),树结构(定义数据元素(结点)之间是层次关系),图结构(则通过图形顶点与边构成的一种结构)。

     3.算法的5个基本特性:有穷性,确定性,可行性,有输入,有输出。

     4.算法应满足的5个目标:正确性,健壮性,高时间效率性(根据执行算法的时间来判断程序的执行效率),高空间性(根据执行算法占用的空间,来判断程序的执行效率) ,可读性。 

     5.算法的优劣主要从时间代价和空间代价来判断:

        时间复杂度关系: O(1)<O(log2^n)<O(n)<O(nlog2^n)<O(n^2)<O(n^3)<O(2^n),时间复杂度越小代表该算法执行的效率高,反之亦然,我们在解决的问题当中,不要选择for循环暴力破解,通过那种方式虽然能解决问题,但是占用的时间太多,我们应该通过别的方式去解决,用空间换时间 用时间换空间都是在不停的更替来使用,目的就是为了追求程序的最优解,就就是算法的魅力所在吧。

        空间复杂程度我在这里就不一一讲解了。

2.接下来我们步入今天的正题,归并排序:

        归并排序的思想是:分而治之,分通俗的讲就是将问题分成一个个小的问题,然后通过递归的方式求解,让每的一个元素按照规则出到栈顶;治是归并排序的最重要一步,将分的阶段得到的结果整理放在一起。归并排序的时间复杂度是:nlog2^n

 简单的图示:

3.下面就是归并排序的代码实现:

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: chenxiky
 * @Date: 2022/02/16/0:14
 * @Description: 归并排序
 */
public class MergetSort {
    public static void main(String[] args) {
        int arr[] = {8,4,5,7,1,3,6,2};
        // 归并排序需要一个额外的空间
        int temp[] = new int[arr.length];
        mergeSort(arr,0,arr.length-1,temp);

        System.out.println("归并排序="+ Arrays.toString(arr));
    }

    // 分+合方法
    public static void mergeSort(int[]arr,int left,int right
                                ,int[] temp){
        if (left < right){
            int mid = (left + right)/2;  // 中间的索引
            // 向左递归进行分解
            mergeSort(arr, left, mid, temp);
            // 向右递归进行分解
            mergeSort(arr, mid+1, right, temp);
            //合并
            merge(arr,left,mid,right,temp);
        }
    }

    /**
     * 合并的方法
     * @param arr 原始数组
     * @param left 左边有序序列的初始索引
     * @param mid  中间索引
     * @param right 右边索引
     * @param temp  做中转的数组
     */
    public static void merge(int[] arr,int left,int mid,
                             int right,int[] temp){

        // 计算进行了多少次归并
        System.out.println("xxxx");

        int i = left;  // 初始化i,左边有序序列的初始索引
        int j = mid+1; // 初始化j,右边有序序列的初始索引
        int t = 0;     //指向temp数组的当前索引

        // 第一步
        // 先把左右两边(有序)的数据按照规则填充到temp数组
        // 直到左右两边的有序序列,有一边处理完毕为止
        while (i <= mid && j <= right){
            // 如果左边有序序列的当前元素 小于等于右边有序序列的当前元素
            // 即将左边的当前元素拷贝到temp数组
            // t++;i++;  +1操作
            if (arr[i] <= arr[j]){
                temp[t] = arr[i];
                t++;  //
                i++;
            } else {  // 反之将右边的有序序列的当前元素,填充到temp
                temp[t] = arr[j];
                t++;
                j++;
            }
        }
        //第二步
        //把有剩余的数据的一边的数据依次全部填充到temp
        while (i <= mid){ //左边的有序序列还有剩余的元素,就全填充到temp
            temp[t] = arr[i];
            t++;
            i++;
        }
        while (j <= right){ //右边的有序序列还有剩余的元素,就全填充到temp
            temp[t] = arr[j];
            t++;
            j++;
        }
        //第三步
        //将temp数组的元素拷贝到arr
        // 注意,并不是每次到拷贝所有的
        t =0;
        int tempLeft = left;
        // 第一次合并时tempLeft=0,right = 3;
        while (tempLeft <= right){
            arr[tempLeft] = temp[t];
            t++;
            tempLeft++;
        }
    }
}

文中若有错的地方,请大家多多见谅。如果大家觉得我的内容有收获可以点击关注哦,同时也可以关注我的公众号: 晨溪

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值