c语言快速排序实现方法
快排的逻辑其实很简单,
递归分治代码如下:
public static void quickSort(int[] array) { //待排序区间为[0, array.length - 1] quickSortIternal(array, 0, array.length - 1);}private static void quickSortIternal(int[] array, int left, int right) { if(left >= right) return; //这里的就选择最左边的元素作为基准值来操作 //index表示基准值停留的下标 int index = partition(array, left, right); quickSortIternal(array, left, index - 1); quickSortIternal(array, index + 1, right);}
非递归分治通过使用栈实现,将数组的左右下标放入栈中每次取出判断left和right的关系,如果left >= right 表示该小区间排序完毕存入每个区间的左右两下标,依次循环,当栈为空时,表示排序结束
代码如下:
public static void quickSort2(int[] array) { Stack<Integer> stack = new Stack<>(); stack.push(array.length - 1); stack.push(0); while(!stack.isEmpty()) { int left = stack.pop(); int right = stack.pop(); if(left >= right) { continue; } int index = partition(array, left, right); stack.push(right); stack.push(index + 1); stack.push(index - 1); stack.push(left); } }
重点是partition的实现
实现方法一: Hoare法使用双引用的的方式,一个指向区间的最左边,一个指向区间的最右边,两个引用向中间遍历的靠拢如果左引用指向的值小于等于基准值就移动如果右引用指向的值大于等于基准值就移动当左引用遇到大于基准值的数据且右引用遇到小于基准值的数据时,交换这两个引用处的数据当两个引用相遇时说明本次partition结束,返回基准值的下标代码如下:
public int partition(int[] array, int left, int right) { int pivot = array[left]; int l = left; int r = right; while(l < r) { while(l < r && array[r] >= pivot) { r--; } while(l < r && array[l] <= pivot) { l++; } swap(array, l, r); } swap(array, left, l); return l; } private static void swap(int[] array, int i, int j) { int tmp = array[i]; array[i] = array[j]; array[j] = tmp; }
实现方法二:填坑法同样需要双引用,指定一个变量保存基准值,假象基准值的位置是一个“坑”右引用遇到大于等于基准值的数值就向左移动,直到遇到第一个小于基准值的数值,将该数值填到“坑”中,此处的位置是一个新的“坑”开始移动左引用,只有遇到一个大于基准值的数值时,填到“坑”中直到左引用和右引用相遇时说明只剩最后一个坑了,将基准值填到“坑”中,返回基准值的下标,本次partition结束
代码如下:
public int partition(int[] array, int left, int right) { int pivot = array[left]; int l = left; int r = right; while(l < r) { while(l < r && array[r] >= pivot) { r--; } array[l] = array[r]; while(l < r && array[l] <= pivot) { l++; } array[r] = array[l]; } array[l] = pivot; return l;}
实现方法三:前后遍历法同样是使用双引用slow和fast,起初同时指向基准值的后一个元素left + 1引用fast向后遍历,如果遍历到的数值大于基准值就向后移动遇到小于基准值的数值时,交换slow引用和fast引用指向的值,slow向后移动一位始终保证slow之前的值都是小于基准值的数值,slow和fast之间的是大于等于基准值的数值,当fast移动到区间最右端right时,遍历结束此时show - 1处的数值为最遍历结束后最后一个小于基准值的数值交换left和slow - 1两位置处的数值,slow - 1表示下标即是基准值的下标,返回slow - 1
代码如下:
private int partition(int[] array, int left, int right) { int pivot = array[left]; int slow = left + 1; int fast = left + 1; while(fast <= right) { if(array[fast] < pivot) { swap(array, slow, fast); slow++; } fast++; } swap(array, left, slow - 1); return slow - 1; }
基准值的选择两边取其一(左或者右)随机选择几数取中(例三数取中:array[left], array[mid], array[right] 大小是中间的为基准值 )性能分析时间复杂度:最好的情况:O(N*logN)平均情况:O(N*logN)最坏的情况:O(N^2)空间复杂度:O(1)最好的情况:O(logN)平均情况:O(logN)最坏的情况:O(N)稳定性:不稳定
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。