排序算法
搜索是计算机中非常重要的步骤,但是从无序数据中寻找特定数字难度较大。有序数据可以提升算法效率,例如二分查找是基于有序数组搜索的
那么,有哪些常见的排序算法呢?
接下来,我们介绍两种重要的分治(Divide and Conquer )排序算法
快速排序
分治算法将大问题转换为小问题,逐个解决小问题的过程中大问题迎刃而解
基本概念
选取一个目标元素pivot
,然后将目标元素放到数组中正确的位置。然后根据排好序的元素,将数组切分为两个子数组,递归实现此过程。
过程
-
选择基准数
pivot
,这里选择排序序列最后一个元素
-
设定
lo
和hi
指针,lo
指针向右搜寻,如果寻找到第一个比pivot
大的元素停止移动;hi
指针向左搜寻,如果寻找到第一个比pivot
小的元素停止移动,然后交换这两个元素
--------->
-
重复2过程(已经交换的元素颜色突出表示)
-
此时
lo >= hi
条件满足,跳出循环,交换lo
与R
索引上的值
-
递归实现1~4过程
Java实现
private void quickSort(int[] arr, int lo, int hi) {
if (lo >= hi) return;
int key = partition(arr, lo, hi);
quickSort(arr, lo, key - 1);
quickSort(arr, key + 1, hi);
}
private int partition(int [] arr, int lo, int hi) {
int pivot = arr[hi];
int i = lo;
int j = hi - 1;
for (; ; ) {
while (i < hi && arr[i] < pivot) {
i++;
}
while (j > lo && arr[j] >= pivot) {
j--;
}
if (i >= j) break;
swap(arr, i, j);
}
swap(arr, i, hi);
return i;
}
private void swap(int [] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
归并排序
基本概念
归并排序同样基于分治算法,在归并算法中,我们将一个数组递归切分成不可再分的小数组,然后将每一对数组进行排序合并,最终得到排序后的数组。
过程
-
切分
以数组[9, -3, 5, 2, 6, 8, -6, 1, 3]
为例
-
合并
例如已经经过排序合并的序列[-3, 5, 9]
和[2, 6]
i
指针在原数组上滑动left
变量初始被赋值为左边界,right
变量初始被赋值为mid+1
,左右指针在辅助数组上滑动left
和right
进行比较,小的那一个赋值给arr[i]
,然后移动指针,若一方到达边界,则将另外一方赋值给arr[i]
-------------->
Java实现
public void sort(int[] arr) {
int[] helper = new int[arr.length];
mergeSort(arr, helper, 0, arr.length - 1);
}
private void mergeSort(int[] arr, int[] helper, int lo, int hi){
if (hi - lo < 1) return;
int mid = lo + (hi - lo) / 2;
mergeSort(arr, helper, lo, mid);
mergeSort(arr, helper, mid + 1, hi);
merge(arr, helper, lo, mid, hi);
}
private void merge(int[] arr, int[] helper, int lo, int mid, int hi) {
if (hi + 1 - lo >= 0)
System.arraycopy(arr, lo, helper, lo, hi + 1 - lo);
int left = lo, right = mid + 1;
for (int i = lo; i <= hi; i++) {
if (left > mid) {
arr[i] = helper[right++];
} else if (right > hi) {
arr[i] = helper[left++];
} else if (helper[right] < helper[left]) {
arr[i] = helper[right++];
} else {
arr[i] = helper[left++];
}
}
}
总结
- 分治:将大问题切分为小问题
- 快速排序:先排序、后切分
- 归并排序:先切分、后排序