栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

归并排序和快速排序Java

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

归并排序和快速排序Java

递归

定义方法时,在方法内部调用方法本身,称为递归。
递归能够将一个大型复杂的问题,转换为一个与原问题相似的,规模较小的问题来求解。
注意:在递归中,不能无限制地调用自己,必须要有边界条件,能够让递归结束,因为每一次递归调用都会在栈内存开辟新的空间,重新执行方法,如果递归的层级太深,很容易造成栈内存溢出。

归并排序

归并原理:

定义三个指针,其中指针index1指向左子组第一个元素,指针index2指向右子组第一个元素,指针index3指向辅助数组assist。
package sort;

import java.util.Arrays;

public class MergeSort {
    public static void main(String[] args) {
        int[] arr = new int[]{12,2,2,323,42,342,341};
        sort(arr);
        System.out.println(Arrays.toString(arr));
    }

    private static int[] assist;

    public static void sort(int[] arr) {
        //1.初始化辅助数组assist
        assist = new int[arr.length];
        //2.定义一个low变量和一个high变量分别记录数组中最小的索引和最大的索引
        int low = 0;
        int high = arr.length-1;
        //3.调用sort重载方法完成数组中从low索引到索引high的元素的排序
        sort(arr,low,high);
    }

    private static void sort(int[] arr,int low,int high) {
        //安全性校验
        if(high <= low) {
            return;
        }

        //对low到high之间的数据分为两个组
        int mid = low + (high - low)/2;
        //分别对每一组数据进行排序
        sort(arr,low,mid);
        sort(arr,mid+1,high);

        //再把两个组中的数据进行归并
        merge(arr,low,mid,high);
    }

    //对数组中从low到mid为一组,从mid+1到high为一组的两组数据进行归并
    private static void merge(int[] arr,int low,int mid,int high) {
        //定义三个指针
        int index1 = low;
        int index2 = mid+1;
        int index3 = low;

        //遍历,移动index1指针和index2指针,比较对应索引处的值,找出小的那一个,放到对应辅助数组的对应索引处
        while(index1 <= mid && index2 <= high) {
            if (arr[index1] <= arr[index2]) {
                assist[index3++] = arr[index1++];
            } else {
                assist[index3++] = arr[index2++];
            }
        }

        //遍历,如果index1处的指针没有走完,将对应元素放到辅助索引数组的对应索引处
        while(index1 <= mid) {
            assist[index3++] = arr[index1++];
        }

        //遍历,如果index2处的指针没有走完,将对应元素放到辅助索引数组的对应索引处
        while(index2 <= high) {
            assist[index3++] = arr[index2++];
        }

        //将辅助数组中的元素拷贝到原数组中
        for (int i = low;i <= high;i++) {
            arr[i] = assist[i];
        }

    }
}

时间复杂度分析


因此其时间复杂度为:O(nlogn)

空间复杂度分析

需要申请额外的数组空间,空间复杂度为O(n)

快速排序

快速排序是对冒泡排序的一种改进。
通过一趟排序将待排序的数据分割成独立的两个部分,其中一部分的所有数据都比另一部分的所有数据都要小。再根据这样的方法对这两部分数据做同样的操作,最后达到整个数据有序的情况。

1.
package sort;

public class QuickSort {
    public static void main(String[] args) {
        int[] arr = new int[]{2,34,235,52};
        quickSort(arr,0,arr.length-1);
        for (int i = 0;i < arr.length;i++) {
            System.out.println(arr[i]);
        }
    }
    public static void quickSort(int[] arr,int low,int high) {
        if (low > high) {
            return;
        }
        int i = low,j = high;
   //     int tmp = arr[(int)(Math.random()*arr.length)];
       int tmp = arr[low];
        while(i < j) {
            while(i < j && tmp <= arr[j]) {
                j--;
            }
            while(i < j && tmp >= arr[i]) {
                i++;
            }
            if (i < j) {
                int tempNum = arr[i];
                arr[i] = arr[j];
                arr[j] = tempNum;
            }
        }
        arr[low] = arr[i];
        arr[i] = tmp;
        quickSort(arr,low,i-1);
        quickSort(arr,i+1,high);
    }
}

2.
package sort;

import java.util.Arrays;

public class QuickSort2 {
    public static void main(String[] args) {
        int[] arr = new int[]{12,45,342,42,424,342};
        sort(arr);
        System.out.println(Arrays.toString(arr));
    }
    public static void sort(int[] arr) {
        int low = 0;
        int high = arr.length-1;
        sort(arr,low,high);
    }
    public static void sort(int[] arr,int low,int high) {
        //安全性校验
        if (high <= low) {
            return;
        }

        int partition = partition(arr, low, high);
        sort(arr,low,partition-1);
        sort(arr,partition+1,high);
    }
    public static int partition(int[] arr,int low,int high) {
        //确定分界值
        int key = arr[low];

        //定义两个指针,分别指向待切分元素的最小索引处和最大索引处的下一个位置
        int left = low;
        int right = high+1;

        //切分
        while (true) {
            //先从右向左扫描,移动right指针,找到一个比分界值小的元素,停止
            while (arr[--right] > key) {
                if (right == low) {
                    break;
                }
            }

            //再从左向右扫描,移动left指针,找到一个比分界值大的元素,停止
            while (arr[++left] < key) {
                if (left == high) {
                    break;
                }
            }

            //判断left >= right,如果是,则证明元素扫描完毕,就要结束循环;如果不是,交换元素即可
            if (left >= right) {
                break;
            } else {
                int tmp = arr[left];
                arr[left] = arr[right];
                arr[right] = tmp;
            }
        }

        //交换分界值 和 两指针指向的元素
        int tmpNum = arr[low];
        arr[low] = arr[right];
        arr[right] = tmpNum;

        //返回分界值所在索引,即left或者right
        return right;
    }

}

快速排序时间复杂度分析

快速排序的一次切分从两头开始交替搜索,直到left和right重合,因此,一次切分算法的时间复杂度为O(n),但整个快速排序的时间复杂度和切分的次数相关。
最优情况:每一次切分选择的基准数字刚好将当前序列等分,因此最优情况下快速排序的时间复杂度为O(nlogn)。
最坏情况:每一次切分选择的基准数字是当前序列中最大数或者最小数,这使得每次切分都会有一个子组,那么总共就得切分n次,所以最坏情况下,快速排序的时间复杂度为O(n^2)。
平均情况:每一次切分选择的基准数字不是最大值和最小值,也不是中值。时间复杂度为O(nlogn)。

快速排序和归并排序对比 区别:
快速排序是另外一种分治的排序算法,它将一个数组分为两个子数组,将两部分独立地排序。

快速排序和归并排序是互补的:
1.归并排序是将数组分成两个子数组分别进行排序,并将有序的子数组归并,从而将整个数组排序(分别排序然后归并);快速排序是当两个数组都有序的时候,整个数组就有序了(没有归并动作)。
2.在归并排序中,一个数组被等分为两半,归并调用发生在处理整个数组之前;在快速排序中,切分数组的位置取决于数组的内容,递归调用发生在处理整个数组之后。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/353403.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号