1、简单的介绍
1、归并排序的核心思想:我们将把数组中的元素分成两部分,对左边元素进行排序,对右边元素进行排序。然后对左右两边元素,进行归并操作。
1、归并排序是稳定的。归并的过程,如果两个元素相等,先把左边的元素进行归并。
2、归并排序不是原地排序,需要额外的内存空间。O(n)
T(N)=2T(N/2)+O(N);
3、
master公式的使用
T(N) = a*T(N/b) + O(N^d)
1) log(b,a) > d -> 复杂度为O(N^log(b,a))
2) log(b,a) = d -> 复杂度为O(N^d * logN)
3) log(b,a) < d -> 复杂度为O(N^d)
归并排序的执行效率与要排序的原始数组的有序程度无关,所以其时间复杂度是非常稳定的,不管是最好情况、最坏情况,还是平均情况,时间复杂度都是 O(nlogn)。
2、快速排序核心思想:如果要排序数组中下标从 p 到 r 之间的一组数据,我们选择 p 到 r 之间的任意一个数据作为 pivot(分区点)。
我们遍历 p 到 r 之间的数据,将小于 pivot 的放到左边,将大于 pivot 的放到右边,将 pivot 放到中间。
经过这一步骤之后,数组 p 到 r 之间的数据就被分成了三个部分,前面 p 到 q-1 之间都是小于 pivot 的,
中间是 pivot,后面的 q+1 到 r 之间是大于 pivot 的。
1、快速排序是原地排序,不需要额外的内存空间。
2、但是快速排序不是稳定的排序。
3、快速的排序最坏情况是原本有序,O(n^2)
4、最好的情况是分布均匀,O(nlogn)
5、平均时间复杂度是O(n*logn)
二、代码实现
/**
* 进行归并排序 基本思想是:我们把一个数组分成两个部分,左边排好序,然后右边的排好序,最后把两个进行归并。
*
* @param array
*/
public static void MergeSort(int[] array) {
if (array.length <= 1) { //如果元素的个数小于等于1 不需要排序
return;
}
MergeSort(array, 0, array.length - 1);
}
/**
* l 表示的是要排序的下标最左边和最右边
*
* @param array
* @param l
* @param r
*/
private static void MergeSort(int[] array, int l, int r) {
if (l == r) { //如果相等就表示排序到最后一个了。
return;
}
int mid = l + ((r - l) >> 1);
MergeSort(array, l, mid); //左边排好序
MergeSort(array, mid + 1, r); //右边排好序
merge(array, l, mid, r); //然后进行归并
}
/**
* 进行归并的操作
*
* @param array
* @param l
* @param mid
* @param r
*/
private static void merge(int[] array, int l, int mid, int r) {
int arr[] = new int[r - l + 1]; //定义一个等长的数组
int p = l;
int q = mid + 1;
int index = 0;
while (p <= mid && q <= r) { //就是进行两个数组之间的元素进行比较
if (array[p] <= array[q]) {
arr[index++] = array[p++];
} else {
arr[index++] = array[q++];
}
}
while (p <= mid) { //如果右边数组已经排序完
arr[index++] = array[p++];
}
while (q <= r) { //如果左边的数组排序完
arr[index++] = array[q++];
}
for (int i = 0; i < arr.length; i++) {
array[l + i] = arr[i];
}
}
/**
* 快速排序的基本思想:
* 取数组中的第一个数或者最后一个数,或者说,是随机的一个数,作为值。
* 把小于它的数,放在左边。大于它的数放在右边。
* 后面的递归实现
*
* @param data
*/
public static void quickSort(int[] data) {
if (data.length <= 1) { //如果元素的个数小于等于1 不需要排序
return;
}
quickSort(data, 0, data.length - 1);
}
/**
* @param data
* @param l
* @param r
*/
private static void quickSort(int[] data, int l, int r) {
if (l < r) {
int index = (int) Math.random() * (r - l + 1);
swap(data, l + index, r); //和最后一个元素进行交换。
int[] p = partition(data, l, r); //进行划分操作
quickSort(data, l, p[0] - 1);
quickSort(data, p[1] + 1, r);
}
}
/**
* 进行数据的划分,以最后一个元素为 基准 小于它的元素 放在左边
* 大于它的放在右边
*
* @param data
* @param l
* @param r
* @return
*/
private static int[] partition(int[] data, int l, int r) {
int less = l - 1; //less 表示的是包裹着比它小的元素
int more = r;
while (l < more) {
if (data[l] > data[r]) { //如果这个元素比较大,我们就进行交换
swap(data, l, --more); //最后一个元素,我们是不动的。
} else if (data[l] < data[r]) { //如果这个元素比较小,我们就放到前面来
swap(data, ++less, l++);
} else { //相等的情况。
l++;
}
}
swap(data, more, r);
return new int[]{less + 1, more};
}
/**
* 进行数据的交换、
*
* @param data
* @param i
* @param j
*/
private static void swap(int[] data, int i, int j) {
int temp = data[i];
data[i] = data[j];
data[j] = temp;
}