Skip to content

Commit

Permalink
更新快速排序
Browse files Browse the repository at this point in the history
  • Loading branch information
0xcaffebabe committed Feb 8, 2020
1 parent 6d60b86 commit e932ef8
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 33 deletions.
Binary file added assets/202002081411.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/批注 2020-02-08 134532.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/批注 2020-02-08 134637.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/批注 2020-02-08 134920.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/批注 2020-02-08 142132.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
136 changes: 103 additions & 33 deletions 算法与数据结构/排序.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,46 +198,116 @@ for (int sz = 1; sz <= a.length; sz += sz) {

## 快速排序

![202002081411](/assets/202002081411.gif)

选定一个元素,将比该元素小的元素放其左边,比它大的放在其右边,并递归地对它左右两边的子序列进行排序

- 快速排序在最差的情况下,会退化为O(N^2)

```java
private void quickSort(Comparable<?>[] a, int l, int r) {
if (l >= r) {
return;
}
int p = partition(a, l, r);
quickSort(a, l, p - 1);
quickSort(a, p + 1, r);
}

/**
* 返回一个p,使得a[l...p-1] < a[p] 并且 a[p+1...r] > a[p]
*/
private int partition(Comparable<?>[] a, int l, int r) {
var v = a[l];
int j = l;
// 从左到右扫描(一)
for (int i = l + 1; i <= r; i++) {
//如果扫描的元素小于v,则将该元素跟大数组的第一个元素交换,同时,小数组的位置扩张1(二)
if (less(a[i], v)) {
swap(a, j + 1, i);
j++;
}
}
// 最后,将v与小数组的最后一个元素交换位置(三)
swap(a, l, j);
return j;
}
```

****

![批注 2020-02-08 134532](/assets/批注%202020-02-08%20134532.png)

****

![批注 2020-02-08 134637](/assets/批注%202020-02-08%20134637.png)

****

![批注 2020-02-08 134920](/assets/批注%202020-02-08%20134920.png)

### 优化

当数组里有大量相同的元素,快速排序的时间复杂度为退化到N^2,解决方法是在两侧使用双指针向中间扫描

![批注 2020-02-08 142132](/assets/批注%202020-02-08%20142132.png)

- 双路快速排序

```java
public static void quickSort(int a[], int low, int hi) {
if (hi<=low) {
return;
private int partition(Comparable<?>[] a, int l, int r) {
var v = a[l];
// i:a[l+1...i] <=v j:[j...r] >=v
int i = l + 1, j = r;
while (true) {
while (i <= r && less(a[i], v)) i++;
while (j >= l + 1 && greater(a[j], v)) j--;
if (i > j) {
break;
} else {
swap(a, i, j);
i++;j--;
}
int j =partition(a,low,hi);
quickSort(a, low, j - 1); // 左子序列排序
quickSort(a, j + 1, hi); // 右子序列排序
}
swap(a,l,j);
return j;
}
```

- 三路快速排序

```java
private void quickSort(Comparable[] a, int l, int r) {
if (l >= r) {
return;
}

private static int partition(int[] a, int low, int hi) {

int i=low, j=hi+1; // 左右扫描指针
int v = a[low]; // 基准数
while (true){
while (a[++i]<v){ // 从左往右扫描,直到扫描元素大于等于基准数
if (i==hi) {
break;
}
}
while (v<a[--j]){ // 从右往左扫描,直到扫描元素小于等于基准数
if (j==low){
break;
}
}
if (i>=j){ // 扫描结束的标志:左指针在右指针的右边或在一起
break;
}
// 交换左右指针的元素,也就是把把右边比基准数小的跟左边比基准数大的交换位置
int t=a[i];
a[i]=a[j];
a[j]=t;
// partition
var v = a[l];

int lt = l; // a[l+1...lt] < v
int gt = r + 1; // a[gt...r] > v
int i = l + 1; // a[lt+1...i) == v
while (i < gt) {
if (a[i].compareTo(v) < 0) {
swap(a, i, lt + 1);
lt++;
i++;
} else if (a[i].compareTo(v) > 0) {
swap(a, i, gt - 1);
gt--;
}else {
i++;
}
// 把基准数放入正确的位置
int t= a[low];
a[low]=a[j];
a[j]=t;
return j;
}
swap(a,i,lt);

quickSort(a, l, lt - 1);
quickSort(a, gt, r);
}
```

## 归并排序与快速排序的背后

- 两个算法都使用了分治算法

0 comments on commit e932ef8

Please sign in to comment.