对数组进行排序,用时间复杂度最小的排序算法
这个题目是要求对一个数组Array进行排序,要求用时间复杂度最小的排序算法 ---- 我们一般选用 快速排序,它的时间复杂度是 O(N LogN)
快速排序采用分区法Partition, 分区法包含如下一些因素:
基准值 -- 我们在数组中选择一个基准值(一般选择数组的最后一个值),把数组分成2个区:
小于等于基准区域 -- 左边区的元素的值都小于基准值(但是左边区的元素本身是无序的,只是它们的值都比基准值要小).
大于基准区域 -- 右边区的元素的值都大于基准值(同样,右边区的元素本身也是无序的).
基准值 ---- 在上面2个区域(【"小于等于基准区域"】 和 【”大于基准区域“】)中间的,就是基准值
边界位置 i --- 边界位置i 是 【"小于基准区域"】 的最后一个元素的位置 => 由此可以推断出, 基准值的位置就是 i + 1
好了,现在我们按照这个要求来写分区发Partition的代码
private static int Partition(int[] arr, int left, int right) { // 为简单起见,直接选择数组最后一个元素作为基准值 // 比如数组 [3, 1, 4, 2],基准就是 2。 var pivot = arr[right]; // i 指向【"小于等于基准区域"】最后一个元素的位置, 刚开始这个区域还没有建立,所以i = left -1,表示目前【"小于等于基准区域"】为空 var i = left - 1; //开始遍历数组,最后一个元素arr[right]是基准值,所以不需要遍历它,它不参与数组的遍历 for(int k = left; k < right; k++) { //如果当前元素比基准值小,那就把它放入【"小于等于基准区域"】 if(arr[k] <= pivot) { i++; //扩大【"小于等于基准区域"】的区域下标 swap(arr,i,k); //把比基准值小的当前元素,放入【"小于等于基准区域"】的区域尾部 } } //遍历完数组后,i指向【"小于等于基准区域"】最后一个元素的位置 //然后我们要把基准值pivot,也就是arr[right]放到【"小于等于基准区域"】的最后一个位置,也就是i+1的位置 swap(arr,i+1,right); return i + 1; //返回基准值的最终位置 }
现在我们来写里面用到的swap 工具方法
// 交换辅助方法
private static void swap(int[] arr, int x, int y)
{
var temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
好了,分区Partition方法写好了,我们就可以写递归方法了 --- 递归方法,就是在方法自己内部调用自己
public static void QuickSort(int[] arr, int left, int right) { if(left < right) {
// 1. 分区操作,获取基准值的最终位置 var pivotPos = Partition(arr,left,right);
// 2. 递归排序左半部分 QuickSoft(arr,left, pivotPos - 1);
// 3. 递归排序右半部分 QickSort(arr, pivotPos + 1, right); } }
所以,最后对数组进行快速排序代码,就是
public static void Sort(int[] arr) { if(arr == null || arr.Length == 1) return; QuickSort(arr, 0, arr.Length - 1); }
浙公网安备 33010602011771号