title: 归并排序与快速排序
date: 2020-03-04 17:21:53
categories:
- 数据结构与算法
tags: - 排序
分治|递归思想
分治,即分而治之,将大的问题分割成小的问题,一一解决,有的问题需要汇总,有的并不需要。
归并:要排序一个数组,就是将这个数组,均分成两部分,然后继续对两部分进行均分至不能分割,最后将分割的各个部分排好序,组合起来。
递推公式:mergeSort(array , begin , end) = merge(mergeSort(array , begin , mid) + mergeSort(array , mid + 1 , end))
代码实现:
public class Merge {
public void mergeSort(int[] a , int begin , int end){
if(begin >= end){
return;
}
int mid = (begin + end) / 2;
mergeSort(a , begin , mid);
mergeSort(a , mid + 1 , end);
merge(a , begin, end , mid);
}
//merge函数,将前后两部分(相当于两个数组)进行组合,新开辟一个数组空间,遍历比较两个子数组,
public void merge(int[] a , int begin , int end , int mid){
int i = begin;
int j = mid + 1;
int k = 0;
int[] tmp = new int[a.length];
while(i <= mid && j <= end){
if(a[i] <= a[j]){
tmp[k++] = a[i++];
}else{
tmp[k++] = a[j++];
}
}
while(i <= mid){
tmp[k++] = a[i++];
}
while(j <= end){
tmp[k++] = a[j++];
}
for (int l = 0; l <= end - begin; l++) {
a[begin + l] = tmp[l];
}
}
public static void main(String[] args) {
Merge merge = new Merge();
int[] a = {1 , 4, 3, 5 ,2};
merge.mergeSort(a , 0 , a.length - 1);
for (int i = 0; i < a.length; i++) {
System.out.println(a[i]);
}
}
}
快排:与归并排序均分不同,快排十要先找一个分区点,将比分区点小的元素排在分区点之前,大的排在分区点之后,根据分区点,将数组分割为前后两个部分,对这两部分重复进行分区操作,直至区间为1为止。
递推公式:quickSort(array , begin , end) = quickSort(array , begin , partition - 1) + quickSort(array , partition + 1 , end)
代码实现:
public class Quick {
public void qucikSort(int[] array , int begin , int end){
if(begin >= end) return;
int p = partition(array , begin , end);
//分成三部分,begin->(p-1),分区点p,(p+1)->end。
qucikSort(array , begin , p - 1);
qucikSort(array , p + 1 , end);
}
//区分点取末尾元素
//处理操作:将小的置于分区点左边,大的置于分区点右边。
//通过游标i将数组分为*已处理区间(全为小于等于区分点的元素)*和*未处理区间*,将循环元素与分区点比较,若小,就将元素通过交换加入到已处理区间末尾,即array[i]元素。
//最后,将区分点与处理区间划分点a[i]交换
public int partition(int[] array , int begin , int end){
int i = begin;
int pivot = array[end];
int k = i;
for (; k < end ; k++) {
if(array[k] <= pivot){
swap(array , i , k);
i++;
}
}
swap(array , i , end);
return i;
}
public void swap(int[] a , int i , int j){
int tmp = a[j];
a[j] = a[i];
a[i] = tmp;
}
public static void main(String[] args) {
Quick quick = new Quick();
int[] a = {1 , 4, 3};
quick.quickSort(a , 0 , a.length - 1);
for (int i = 0; i < a.length; i++) {
System.out.println(a[i]);
}
}
}
区别
归并排序,可以看成是自下而上的,先处理子问题,然后将各个部分组合起来;快速排序,可以看成是自上而下的,先进行分区,再处理子问题。
归并排序在merge时,需要开辟新的内存空间,不是原地排序算法。
快排在分区时,需要交换元素,不是稳定的排序算法。