- 时间复杂度:O(nlogn)
- 无论是递归的还是非递归的快速排序,其关键都是partition方法,每一次partition后,都会找到原序列的pivot(枢轴)索引,且位于pivot索引上的元素一定处于整个最终有序序列它应该位于的正确位置上,显然partition后找到的pivot索引会将原序列不断分裂成两个子序列。如此:所有元素都会找到自己最终应该处于的正确位置,这样整个序列便会有序。
- 算法导论版快速排序实现思想
- 每次partition尝试找到每个子序列第一个元素的最终正确位置,且将该元素交换到该位置,并且该最终位置(pivot索引)会将该序列分裂成两个子序列(上面已经说过了哈),如此不断进行,直至序列有序
- 具体来说:设置最初ultimateIndex=子序列leftIndex,遍历除leftIndex外的子序列,每当找到一个比leftIndex大的元素ultimateIndex加1,如此便可以得到ultimateIndex的值,交换leftIndex元素到ultimateIndex处。在各子序列上不断运行该方法,便可以使整个序列有序。
/* * How to record where the pivot value is? * * Can you give another solution? */ private static int partition(int[] array, int leftIndex, int rightIndex) { int ultimateIndex = leftIndex; for (int i = leftIndex + 1; i <= rightIndex; i ++) { if (array[i] < array[leftIndex]) { ultimateIndex ++; if (ultimateIndex != i) { swap(array, ultimateIndex, i); } } } if (ultimateIndex != leftIndex) { swap(array, leftIndex, ultimateIndex); } return ultimateIndex; }
public static void quickSort(int[] array, int leftIndex, int rightIndex) { if (rightIndex > leftIndex) { int pivotIndex = partition(array, leftIndex, array.length - 1); quickSort(array, leftIndex, pivotIndex - 1); quickSort(array, pivotIndex + 1, rightIndex); } }
- 严蔚敏版快速排序实现思想
- partition方法要实现的目的和上面算法导论版的是一样的
- 具体来说:为每个子序列设置leftIndex和rightIndex,leftIndex从左到右遍历数组,rightIndex从右到左遍历数组,遍历规则如下:
- 若leftIndex和rightIndex不相遇则就按下规则不断交替移动leftIndex和rightIdnex
- 必须先从rightIndex指针开始移动,否则需要另设置变量处理一些问题,稍加动手便可以明白这个问题
- 当rightIndex向左移动的过程中若找到一个小于所给子序列第一个元素的元素,交换此时leftIndex和rightIndex所代表的元素,停止移动rightIndex,开始移动leftIndex;否则一直移动rightIndex
- 当leftIndex向右移动的过程中若找到一个大于所给子序列第一个元素的元素,交换此时leftIndex和rightIndex所代表的元素,停止移动leftIndex,开始移动rightIndex;否则一直移动leftIndex
- 如此,直至rightIndex和leftIndex相遇
- 当rightIndex和leftIndex相遇时,其值就是pivot索引,且子序列的第一个元素应经被交换到该位置上了
private static int partitionYAN(int[] array, int leftIndex, int rightIndex) { int i = leftIndex; for (int j = rightIndex; i != j;) { while (j > i) { if (array[j] < array[i]) { swap(array, j, i); i ++; break; } else { j --; } } while (i < j) { if (array[i] > array[j]) { swap(array, i, j); j --; break; } else { i ++; } } } return i; }
public static void quickSortYAN(int[] array, int leftIndex, int rightIndex) { if (rightIndex > leftIndex) { int pivotIndex = partitionYAN(array, leftIndex, array.length - 1); quickSortYAN(array, leftIndex, pivotIndex - 1); quickSortYAN(array, pivotIndex + 1, rightIndex); } }
- 非递归实现的话,有思路就很简单:每次partition后将生成子序列的起始索引和结束索引成对存储进一个栈,只要栈不空,每次弹出一对索引,在其代表的序列上执行快速排序就OK了。
public class QuickSort { public static void quickSort(int[] array) { if (array.length <= 1) { return; } else { Stack<Integer> indexStack = new Stack<Integer>(); indexStack.push(0); indexStack.push(array.length - 1); while (!indexStack.isEmpty()) { int toIndex = indexStack.pop(); int fromIndex = indexStack.pop(); int ultimateIndex = fromIndex; for (int i = fromIndex + 1; i <= toIndex; i ++) { if (array[i] < array[fromIndex]) { ultimateIndex ++; if (ultimateIndex != i) { swap(array, ultimateIndex, i); } } } if (ultimateIndex != fromIndex) { swap(array, ultimateIndex, fromIndex); } if (ultimateIndex - 1 > fromIndex) { indexStack.push(fromIndex); indexStack.push(ultimateIndex - 1); } if (ultimateIndex + 1 < toIndex) { indexStack.push(ultimateIndex + 1); indexStack.push(toIndex); } } } } public static void quickSortYAN(int[] array) { if (array.length <= 1) { return; } else { Stack<Integer> indexStack = new Stack<Integer>(); indexStack.push(0); indexStack.push(array.length - 1); while (!indexStack.isEmpty()) { int toIndex = indexStack.pop(); int fromIndex = indexStack.pop(); int i = fromIndex; for (int j = toIndex; i != j;) { while (j > i) { if (array[j] < array[i]) { swap(array, j, i); i ++; break; } else { j --; } } while (i < j) { if (array[i] > array[j]) { swap(array, i, j); j --; break; } else { i ++; } } } if (i - 1 > fromIndex) { indexStack.push(fromIndex); indexStack.push(i - 1); } if (i + 1 < toIndex) { indexStack.push(i + 1); indexStack.push(toIndex); } } } } private static void swap(int[] array, int index1, int index2) { array[index1] ^= array[index2]; array[index2] ^= array[index1]; array[index1] ^= array[index2]; } }
- PS:
- Code还是去年工作半年闲暇时码的,目的是为了弥补自己本科期间没有动手写这些基础code的缺憾
- 总是工作时抽闲写一点,注释较少,望君手下留情