归并排序算法图解分析

it2025-01-31  32

文章目录

一、归并排序介绍二、图解三、代码分析1.合并有序数组2.分的过程 三、完整代码

一、归并排序介绍

归并排序使用的方法是分治法,即将问题分解为许多类似的小问题然后递归求解。 这里不做详细分析,直接看图解过程。

二、图解

分的过程:可以直接除以二分割(这里总数是奇数也可以)。 治的过程:核心是合并两个有序的数组。

三、代码分析

1.合并有序数组

归并排序的核心就是治的过程也就是合并两个有序的数组。实现过程如下(以升序排序为例):

两指针分别指向数组的头部,并构建一个长度是两个数组之和的临时数组,用于存储数据。两指针所在位置的值比较,将值小的填入临时数组中,其所在的指针后移一位。反复进行2步骤,直到有一个数组的指针越界,将另外一个数组的所有后续元素依次填入临时数组中,合并完成。

图解: 以arr1 = {1,5,6};arr2 ={3,7,9}为例。 左右比较,填入1,左边后移一位。 左右比较,填入3,右边后移一位。 左右比较,填入5,左边后移一位。 左右比较,填入6,左边后移一位。 指针越界,将右边元素依次填入。 合并完成。

代码: 下面代码中合并的是原始数组中arr[left 到 mid]段与arr[mid+1 到 right]段,故最后将临时数组temp中的元素拷贝会arr[left 到 right]段(因为整个排序过程是还在原始数组中进行的)。left,mid,right这是进行假想的分割,详细的分的过程后面的代码。

/** * 【合并】两个有序数组 * @param arr 总数组 * @param left 左数组开始指针(arr左指针) * @param mid 右数组开始指针 * @param right 右指针(arr右指针) */ public static void merge(int[] arr, int left, int mid, int right){ int[] temp = new int[right-left+1]; int l = left;//左数组初始索引 int m = mid + 1;//右数组初始索引 int t = 0;//临时数组初始索引 //1.将左右数组元素按规则填入temp数组中 while(l <= mid && m <= right){ if(arr[l] > arr[m]){ temp[t] = arr[m]; m++; t++; } else{ temp[t] = arr[l]; l++; t++; } } //2.将数组剩余元素填入temp中 if(l > mid){ while(m <= right){ temp[t] = arr[m]; m++; t++; } } else{ while(l <= mid ){ temp[t] = arr[l]; l++; t++; } } //3.将temp数组拷贝到arr中 t = 0; l = left; while(l <= right){ arr[l] = temp[t]; l++; t++; } }

2.分的过程

代码: 使用递归进行分割,然后使用merge方法合并数组。

public static void Sort(int[] arr, int left, int right){ if(left < right){ int mid = (left+right)/2;//取中间值 Sort(arr, left, mid);//分 Sort(arr, mid+1, right);//分 merge(arr, left, mid, right); //治 } }

三、完整代码

public static void main(String[] args) { int arr[] = {4,5,8,20,6,87,12,65,0,855,12,5,78}; mergeSort(arr); System.out.println(Arrays.toString(arr)); } public static void mergeSort(int[] arr){ Sort(arr, 0, arr.length() - 1); } public static void Sort(int[] arr, int left, int right){ if(left < right){ int mid = (left+right)/2;//取中间值 Sort(arr, left, mid);//分 Sort(arr, mid+1, right);//分 merge(arr, left, mid, right); //治 } } public static void merge(int[] arr, int left, int mid, int right){ int[] temp = new int[right-left+1]; int l = left;//左数组初始索引 int m = mid + 1;//右数组初始索引 int t = 0;//临时数组初始索引 //1.将左右数组元素按规则填入temp数组中 while(l <= mid && m <= right){ if(arr[l] > arr[m]){ temp[t] = arr[m]; m++; t++; } else{ temp[t] = arr[l]; l++; t++; } } //2.将数组剩余元素填入temp中 if(l > mid){ while(m <= right){ temp[t] = arr[m]; m++; t++; } } else{ while(l <= mid ){ temp[t] = arr[l]; l++; t++; } } //3.将temp数组拷贝到arr中 t = 0; l = left; while(l <= right){ arr[l] = temp[t]; l++; t++; } } }

测试结果: [0, 4, 5, 5, 6, 8, 12, 12, 20, 65, 78, 87, 855]

最新回复(0)