定义:归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
思路:
将排序分为俩步,分别为“分”和“治”。
①.“分”:将完整的序列进行对半拆分成子序列,可采用递归的方式进行拆分;
②.“治“,将有序的俩个子序列,合并成一个新的有序序列。
可采用临时数组方式存放合并之后的序列,设定俩个指针,最初位置分别为两个已经排序序列的起始位置,比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置。再进行重复比较,如下图对(5,13,21,33)和(3,11,19,66)俩个序列进行了合并操作。
总结:快速排序是对冒泡排序的一种改进,其之所比较快,是因为较于冒泡排序,每次交换是跳跃式的。每次排序的时候设置一个基准点,将小于等于基准点的数全部放到基准点的左边,将大于等于基准点的数全部放到基准点的右边。这样在每次交换的时候就不会像冒泡排序一样每次只能在相邻的数之间进行交换,交换的距离就大的多了,因此总的比较和交换次数就少了,速度自然就提高了。
代码实现:
/**
* 对arr数组索引[left,right]区间的元素进行归并排序
* @param arr
* @param left 起始位置
* @param right 终止位置
*/
public static void mergeSort(int[] arr, int left, int right){
if (left < right){
int mid = (left + right)/2;
// 对[left,mid]区间,即左边序列进行归并排序
mergeSort(arr, left, mid);
// 对[mid+1,right]区间,即右边序列进行归并排序
mergeSort(arr, mid+1, right);
// 将[left,right]区间排好序的俩个集合进行合并操作
merge(arr, left, mid, right);
}
}
/**
* 对arr数组中,索引[left,mid]区间,与索引[mid+1,right]区间的俩区间数据进行合并操作
* @param arr
* @param left 第一个区间起始位置
* @param mid 第一个区间的结束位置
* @param right 第二个区间的结束位置
*/
private static void merge(int[] arr, int left, int mid, int right) {
// 创建临时数组
int[] temp = new int[right-left+1];
int i = left; //第一个区间起始索引
int j = mid+1; //第二个区间起始索引
int t = 0; //临时数组索引值
// 将俩个区间的元素,按照大小顺序放入临时数组中
while (i<=mid && j<=right){
if (arr[i] <= arr[j]){
temp[t] = arr[i];
i++;
}else {
temp[t] = arr[j];
j++;
}
t++;
}
// 如果左边序列中有剩余元素,则将剩余元素填充进temp中
while (i <= mid){
temp[t++] = arr[i++];
}
// 如果右边序列中有剩余元素,则将剩余元素填充进temp中
while (j <= right){
temp[t++] = arr[j++];
}
t=0;
//将temp中的元素全部拷贝到原数组中
while(left <= right){
arr[left++] = temp[t++];
}
}