一、快速排序
1.基本思想:
1.先从数列中取出一个数作为基准数。
2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
3.再对左右区间重复第二步,直到各区间只有一个数。
2.演示
以一个数组作为示例,取区间第一个数为基准数。
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|
72 | 6 | 57 | 88 | 60 | 42 | 83 | 73 | 48 | 85 |
初始时,i = 0; j = 9; X = a[i] = 72
由于已经将 a[0] 中的数保存到 X 中,可以理解成在数组 a[0] 上挖了个坑,可以将其它数据填充到这来。
从j开始向前找一个比X小或等于X的数。当j=8,符合条件,将a[8]挖出再填到上一个坑a[0]中。a[0]=a[8]; i++; 这样一个坑a[0]就被搞定了,但又形成了一个新坑a[8],这怎么办了?简单,再找数字来填a[8]这个坑。这次从i开始向后找一个大于X的数,当i=3,符合条件,将a[3]挖出再填到上一个坑中a[8]=a[3]; j–;
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|
48 | 6 | 57 | 88 | 60 | 42 | 83 | 73 | 88 | 85 |
然后一直重复这个步骤即可
3.代码
public static void quickSort(int[] arr, int begin, int end) {
if (begin > end) {
return ;
}
int i = begin;
int j = end;
int x = arr[i];
while (i < j) {
while (i < j && x < arr[j]) {
j--;
}
if (i < j) {
arr[i] = arr[j];
}
while (i < j && x > arr[i]) {
i++;
}
if (i < j) {
arr[j] = arr[i];
}
}
arr[i] = x;
quickSort(arr, begin, i - 1);
quickSort(arr, i + 1, end);
}
4.复杂度分析
s
二、4种优化方式
1.以中枢为基准数据
public static void quickSort(int[] arr, int begin, int end) {
if (begin > end) {
return;
}
int i = begin;
int j = end;
int x = arr[(i + j) / 2];
int temp = 0;
while (i < j) {
while (i < j && x < arr[j]) {
j--;
}
while (i < j && x > arr[i]) {
i++;
}
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
quickSort(arr, begin, i - 1);
quickSort(arr, i + 1, end);
}
2.随机选取基准法
public static void quickSort(int[] arr, int begin, int end) {
if (begin > end) {
return ;
}
int random = new Random().nextInt(end - begin + 1) + begin; //随机选取基准数
int i = begin;
int j = end;
int x = arr[random];
int temp = 0;
while (i < j) {
while (i < j && x < arr[j]) {
j--;
}
while (i < j && x > arr[i]) {
i++;
}
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
quickSort(arr, begin, i - 1);
quickSort(arr, i + 1, end);
}
3.三数取中
1.将头部,中部,尾部数据比较大小
2.最大的数据放到最后,最小的数据放到中间,较大的数据放到头部
3.以头部数据为基准值
public static void newSort(int arr[], int begin, int end) {
int mid = arr.length /2;
if (arr[mid] > arr[end]) {
swap(arr, mid, end);
}
if (arr[mid] > arr[begin]) {
swap(arr, mid, begin);
}
if (arr[begin] > arr[end]) {
swap(arr, begin, end);
}
}
public static void swap(int arr[], int i, int j) {
int temp = 0;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void quickSort(int arr[], int begin, int end) {
if (begin >= end) {
return;
}
int i = begin;
int j = end;
if (j - i == arr.length - 1) {
newSort(arr, i, j);
}
int x = arr[begin];
while (i < j) {
while (i < j && x < arr[j]) {
j--;
}
if (i < j) {
arr[i] = arr[j];
}
while (i < j && x > arr[i]) {
i++;
}
if (i < j) {
arr[j] = arr[i];
}
}
arr[i] = x;
quickSort(arr, begin, i - 1);
quickSort(arr, i + 1, end);
}
4.序列长度达到一定程度后,使用直插排序
public static void insertSort(int arr[], int i, int j) {
for (int k = i + 1; k < j + 1; k++) {
int insertIndex = k;
int insertValue = arr[k];
while (insertIndex > 0 && insertValue < arr[insertIndex - 1]) {
arr[insertIndex] = arr[insertIndex - 1];
insertIndex--;
}
arr[insertIndex] = insertValue;
}
}
public static int quickSort(int arr[], int begin, int end) {
int i = begin;
int j = end;
int x = arr[begin];
while (i < j) {
while (i < j && x < arr[j]) {
j -= 1;
}
if (i < j) {
arr[i] = arr[j];
}
while (i < j && arr[i] < x) {
i += 1;
}
if (i < j) {
arr[j] = arr[i];
}
}
arr[i] = x;
return i;
}
public static void quick_insert(int arr[], int begin, int end) {
if (end - begin <= 2) {
insertSort(arr, begin, end);
return;
}
if (begin >= end) {
return;
}
int i = quickSort(arr, begin, end);
quick_insert(arr, begin, i - 1);
quick_insert(arr, i + 1, end);
}