话不多说,直接上代码:
package com.example.demo.study;
import org.junit.Test;
public class QuickSort
{
@Test
public void testSort()
{
int[] a = {5, 8, 7, 28, 96, 4 , 7, 0, 3};
quickSort(a, 0, a.length-1);
CommonService.printArray(a);
}
public void quickSort(int[] a, int start, int end)
{
int t = a[start];
int i = start;
int j = end;
while (j > i)
{
// 从j 向前遍历数组,找到比t小的的数,找到了就把当前值赋值到下标为i的位置
while (j > i && a[j] > t)
{
j --;
}
if (j > i)
{
a[i] = a[j];
i ++;
}
// 从i向后遍历数组,找到比t大的数,找到了就把当前值赋值到j的位置
while (j > i && a[i] < t)
{
i ++;
}
if (j > i)
{
a[j] = a[i];
j --;
}
a[i] = t;
// 给左侧数组排序
if (start < i - 1)
{
quickSort(a, start, i - 1);
}
// 给右侧数组排序
if (i + 1 < j)
{
quickSort(a, i + 1, end);
}
}
}
}
算法思想:
快速排序(Quick Sort)是交换排序的另一种(还有一种是冒泡排序)的排序方法,又称为分区交换排序法,是对冒泡排序的方法的改进。
个人解析(升序为例):整个过程包含有递归算法,不断的将一个数组一份为二,对小数组排序。其中单个排序过程大致如下:
1、默认选取第一个元素(a[start])为标准元素(t),再取最左侧元素下标为start,最右侧元素下标为end;
2、从右向左查找比 t 小的元素,找到了就把当前位置的元素赋值给 i 下标位置的元素,初始 i 位置的元素赋值给了 t 元素;
3、从左向右查找比 t 大的元素,找到了就把当前位置的元素赋值给j下标位置的元素(j下标的元素赋值到了 i 位置);
4、依次类推,i 和 j 最终会相遇(i 在增大,j在减小),最后把 t 位置值赋值给 i ,一次排序过程完毕;
5、重复上面1 ~ 5 步骤,对左边的元素和右边的元素进行排序,直到start >= end,此时所有元素完成排序;
时间复杂度:
快速排序算法的时间复杂度,有时候是O(nlgn), 有时候就是O(n2),这个和数据分布有关系(第一个初始元素)。
网上的算法分析我也看了一些,奈何数学功底不够,没太看懂。。。
但是我直观的感受是如果初始元素取的是中位或者接近中位数,那么这次的排序应该是最快的,相反,如果取到的初始元素偏离中位数越远,排序效率应该是越差。