java 归并排序数组_归并排序就这么简单

归并排序就这么简单

从前面已经讲解了冒泡排序、选择排序、插入排序,快速排序了,本章主要讲解的是归并排序,希望大家看完能够理解并手写出归并排序快速排序的代码,然后就通过面试了!如果我写得有错误的地方也请大家在评论下指出。

归并排序的介绍

来源百度百科:

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

过程描述:

归并过程为:比较a[i]和b[j]的大小,若a[i]≤b[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1;否则将第二个有序表中的元素b[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。

原理:

归并操作的工作原理如下:

第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列

第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置

第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置

重复步骤3直到某一指针超出序列尾

将另一序列剩下的所有元素直接复制到合并序列尾

下面我就来做个小小的总结:

将两个已排好序的数组合并成一个有序的数组,称之为归并排序

步骤:遍历两个数组,比较它们的值。谁比较小,谁先放入大数组中,直到数组遍历完成

一、演算归并排序过程

现在我有两个已经排好顺序的数组:int[] arr1 = {2, 7, 8}和int[] arr2 = {1, 4, 9},我还有一个大数组来装载它们int[] arr = new int[6];

1.1

那么,我将两个数组的值进行比较,谁的值比较小,谁就放入大数组中!

首先,拿出arr1[0]和arr2[0]进行比较,显然是arr2[0]比较小,因此将arr2[0]放入大数组中,同时arr2指针往后一格

所以,现在目前为止arr = {1}

1.2

随后,拿arr1[0]和arr2[1]进行比较,显然是arr1[0]比较小,将arr1[0]放入大数组中,同时arr1指针往后一格

所以,现在目前为止arr = {1,2}

1.3

随后,拿arr1[1]和arr2[1]进行比较,显然是arr2[1]比较小,将arr2[1]放入大数组中,同时arr2指针往后一格

所以,现在目前为止arr = {1,2,4}

........

遍历到最后,我们会将两个已排好序的数组变成一个已排好序的数组arr = {1,2,4,7,8,9}

二、归并排序前提分析(分治法)

从上面的演算我们就直到,归并排序的前提是需要两个已经排好顺序的数组,那往往不会有两个已经排好顺序的数组给我们的呀(一般是杂乱无章的一个数组),那这个算法是不是很鸡肋的呢??

其实并不是的,首先假设题目给出的数组是这样子的:int[] arr = {2, 7, 8, 1, 4, 9};

当我们要做归并的时候就以arr[3]也就元素为1的那个地方分开。是然后用一个指针L指向arr[0],一个指针M指向arr[3],用一个指针R指向arr[5](数组最后一位)。有了指针的帮助,我们就可以将这个数组切割成是两个有序的数组了(操作的方式就可以和上面一样了)

可是上面说了,一般给出的是杂乱无章的一个数组,现在还是达不到要求。比如给出的是这样一个数组:int[] arrays = {9, 2, 5, 1, 3, 2, 9, 5, 2, 1, 8};

此时,我们就得用到分治的思想了:

那么我们也可以这样想将int[] arr = {2, 7, 8, 1, 4, 9};数组分隔成一份一份的,arr[0]它是一个有序的"数组",arr[1]它也是一个有序的"数组",利用指针(L,M,R)又可以像操作两个数组一样进行排序。最终合成{2,7}.......再不断拆分合并,最后又回到了我们的arr = {1,2,4,7,8,9},因此归并排序是可以排序杂乱无章的数组的

这就是我们的分治法--->将一个大问题分成很多个小问题进行解决,最后重新组合起来

三、归并代码实现

实现步骤:

拆分

合并

........

public static void main(String[] args) {

int[] arrays = {9, 2, 5, 1, 3, 2, 9, 5, 2, 1, 8};

mergeSort(arrays, 0, arrays.length - 1);

System.out.println("公众号:Java3y" + arrays);

}

/**

* 归并排序

*

* @param arrays

* @param L 指向数组第一个元素

* @param R 指向数组最后一个元素

*/

public static void mergeSort(int[] arrays, int L, int R) {

//如果只有一个元素,那就不用排序了

if (L == R) {

return;

} else {

//取中间的数,进行拆分

int M = (L + R) / 2;

//左边的数不断进行拆分

mergeSort(arrays, L, M);

//右边的数不断进行拆分

mergeSort(arrays, M + 1, R);

//合并

merge(arrays, L, M + 1, R);

}

}

/**

* 合并数组

*

* @param arrays

* @param L 指向数组第一个元素

* @param M 指向数组分隔的元素

* @param R 指向数组最后的元素

*/

public static void merge(int[] arrays, int L, int M, int R) {

//左边的数组的大小

int[] leftArray = new int[M - L];

//右边的数组大小

int[] rightArray = new int[R - M + 1];

//往这两个数组填充数据

for (int i = L; i < M; i++) {

leftArray[i - L] = arrays[i];

}

for (int i = M; i <= R; i++) {

rightArray[i - M] = arrays[i];

}

int i = 0, j = 0;

// arrays数组的第一个元素

int k = L;

//比较这两个数组的值,哪个小,就往数组上放

while (i < leftArray.length && j < rightArray.length) {

//谁比较小,谁将元素放入大数组中,移动指针,继续比较下一个

if (leftArray[i] < rightArray[j]) {

arrays[k] = leftArray[i];

i++;

k++;

} else {

arrays[k] = rightArray[j];

j++;

k++;

}

}

//如果左边的数组还没比较完,右边的数都已经完了,那么将左边的数抄到大数组中(剩下的都是大数字)

while (i < leftArray.length) {

arrays[k] = leftArray[i];

i++;

k++;

}

//如果右边的数组还没比较完,左边的数都已经完了,那么将右边的数抄到大数组中(剩下的都是大数字)

while (j < rightArray.length) {

arrays[k] = rightArray[j];

k++;

j++;

}

}

我debug了一下第一次的时候,就可以更容易理解了:

将大数组的前两个进行拆分,然后用数组装载起来

c33cc759eff30f64621d8d26723ab633.png

比较小数组的元素哪个小,哪个小就先放入大数组中

7bee251dbc78199fdc67dd3f8ed292b5.png

上面的两个步骤不断循环,最后得出有序的数组:

b8aa405a44ef10d253eb4f7dc6ebe290.png

四、归并排序的优化

我这里整理一下要点,有兴趣的同学可到上面的链接上阅读:

当递归到规模足够小时,利用插入排序

归并前判断一下是否还有必要归并

只在排序前开辟一次空间

如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章,想要获取更多的Java资源的同学,可以关注微信公众号:Java3y

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
归并排序是一种基于分治思想的排序算法,它将一个大的问题分解成两个或多个小的问题来解决,然后将这些小问题的解决方案合并起来得到大问题的解决方案。在归并排序中,字符串数组被分解成较小的字符串子数组,然后对子数组进行排序,最后将排序后的子数组合并成一个有序的字符串数组。 下面是使用Java实现归并排序字符串数组的示例代码: ```java public class MergeSort { public static void main(String[] args) { String[] strArray = {"apple", "banana", "cherry", "dragonfruit", "elderberry"}; mergeSort(strArray); for (String str : strArray) { System.out.println(str); } } public static void mergeSort(String[] strArray) { if (strArray == null || strArray.length < 2) { return; } int mid = strArray.length / 2; String[] leftArray = Arrays.copyOfRange(strArray, 0, mid); String[] rightArray = Arrays.copyOfRange(strArray, mid, strArray.length); mergeSort(leftArray); mergeSort(rightArray); merge(leftArray, rightArray, strArray); } public static void merge(String[] leftArray, String[] rightArray, String[] result) { int i = 0, j = 0, k = 0; while (i < leftArray.length && j < rightArray.length) { if (leftArray[i].compareTo(rightArray[j]) <= 0) { result[k++] = leftArray[i++]; } else { result[k++] = rightArray[j++]; } } while (i < leftArray.length) { result[k++] = leftArray[i++]; } while (j < rightArray.length) { result[k++] = rightArray[j++]; } } } ``` 在这个示例代码中,我们首先定义了一个字符串数组 `strArray`,包含了五个需要排序的字符串。然后我们调用 `mergeSort` 方法对字符串数组进行排序。在 `mergeSort` 方法中,我们首先判断输入的字符串数组是否为空或者长度小于2,如果是,则直接返回。否则,我们将字符串数组分成左右两个子数组,并递归地对它们进行排序。最后,我们调用 `merge` 方法将排序后的左右子数组合并成一个有序的字符串数组。在 `merge` 方法中,我们使用字符串的 `compareTo` 方法比较两个字符串的大小关系,将较小的字符串放入结果数组中。最后,我们遍历结果数组,将所有字符串输出到控制台上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值