分治法快速排序
快速排序是最常用的排序算法之一
快速排序也是采用了分治的思想,有如下几个过程
- 设i=array[0] 也就是待排序的数组的第一个元素 通过双指针的循环使得比 i小的数都在i的左边,所以比i大的数都在i的右边(等于i的我们不关心)在左右出现都可以。这一步双指针操作,只需要线性O(n)的时间就可以完成,因为只遍历一次数组
- 把k左边的部分进行快速排序(递归过程)
- 把k右边的部分进行快速排序(递归过程)
例如:
根据指针的不断变化来把数交换位置,其中总会有 j 或 k 的值是等于 i 的
public class QuickSort {
//主函数
public static void main(String[] args) {
int array[] = {5, -5, 10, 50, 13, 27, 10, -16};
quickSort(array, 0, array.length - 1);
for (int i = 0; i < array.length; i++) {
System.out.print(array[i]+" ");
}
}
/**
*
* @param array 需要排序的数组
* @param head 排序的上界
* @param tail 排序的下界
*/
static void quickSort(int[] array, int head, int tail) {
//递归出口, 当需要排序的上下 界相等时候则说明只有一个元素,跳出递归
if (head >= tail) {
return;
}
// 首元素 i 也是用于分开大于 i 与小于 i 两个部分的对象元素
int i = array[head];
int j = head , k = tail ; // j 为左指针 k 为右指针
while (j != k) { // 当j == k 的时候说明 两个指针相遇 左右两边的元素都与 i 比较过了
while (j < k && array[k] >= i) { //此处循环表示 右边的元素与 i 比较,如果大于i 那么指针左移
k-- ;
}
swap(array,j,k); //跳出循环,证明该元素小于i 则交换 j 与 k 的位置
while (j < k && i >= array[j]) { //此处循环表示 左边的元素与 i 比较,如果小于i 那么指针右移
j++;
}
swap(array, j, k); //跳出循环,证明该元素大于i 则交换 j 与 k 的位置
}
quickSort(array, head, j-1 ); //递归调用 左半边再进行比较
quickSort(array, j+1, tail); //递归调用 右半边再进行比较
}
/**
* 交换
* @param array
* @param i
* @param j
*/
static void swap(int[] array, int i, int j) {
int c = array[i] ;
array[i] = array[j];
array[j] = c ;
}
}
性能分析:
- 最坏情况:当每一次划分的两个子问题你包含的是n-1个元素和0个元素的时候,则出现最坏情况,也就是每一次的i总是最大或者最小的时候出现最坏情况,该情况下复杂度为O(n²)
- 最佳情况:当每一次划分的两个子问题的规模都不大于2/n的时候则与归并排序一样复杂度为O(nlgn) 但是归并排序需要额外的存储空间来保存,相比之下快速排序会更加常用
还真写错了。当时两个while循环我觉得先左边再右边符合逻辑一点,我就直接换位置了,感觉没啥问题,可得到哦结果完全不同!!得小心。