# g10guang/g10guang.github.io

Switch branches/tags
Nothing to show
Fetching contributors…
Cannot retrieve contributors at this time
215 lines (176 sloc) 6.96 KB
layout title date categories
post

2018-09-04 09:00:05 +0800

# In short

```def qsort(arr: list, low: int, high: int):
if low >= high:
return
pos = partition(arr, low, high)
qsort(arr, low, pos - 1)
qsort(arr, pos + 1, high)```

partition 函数的功能：将所有小于等于 pivot 的数移动到数组左边，将所有大于 pivot 的数移动到右边，并且返回最终 pivot 元素的位置 pos，满足： `arr[low : pos] <= pivot and arr[pos + 1 : high] > pivot`

## 第一种

1. 选择当前数组的最后一个元素作为分界值
2. 选择 index 满足 `arr[low:index] <= pivot`
```def partition(arr: list, low: int, high: int):
# choose the last elem as pivot.
pivot = arr[high]
# make sure arr[low:index] <= pivot
index = low
for i in range(low, high):
if arr[i] <= pivot:
arr[index], arr[i] = arr[i], arr[index]
index += 1
# if pivot == max(arr[low:high+1]):
#       index == high
# else:
#       index < high and arr[index] > pivot
arr[index], arr[high] = pivot, arr[index]
return index```

## 第二种

1. 选择当前数组的第 0 号元素作为分界值
2. `arr[:head] <= pivot and arr[tail:high] > pivot`
3. `scanner == head + 1`
```def partition(arr: list, low: int, high: int):
# choose the first elem as pivot
pivot = arr[low]
# arr[low:head] <= pivot
# arr[tail+1:high+1] > pivot
# head point to the empty position
tail = high
# always scanner == head + 1
scanner = head + 1
while scanner <= tail:
if arr[scanner] > pivot:
arr[tail], arr[scanner] = arr[scanner], arr[tail]
tail -= 1
else:
scanner += 1
# head point to the empty position. and satisfy:
# arr[low:head] <= pivot and arr[tail+1:high+1] > pivot and head == tail
# so arr[head+1:high+1] > pivot, arr[head] is the position for pivot.

# 第三种

1. 选择当前数组第 0 号元素作为分界值
2. 同时发起从左到右、从右到左扫描，将大于 pivot 的放在右边，小于等于 pivot 的放在左边
3. `arr[low:l] <= pivot and arr[h+1:high+1] > pivot`
```def partition(arr: list, low: int, high: int):
# choose the first elem as pivot
pivot = arr[low]
# arr[low:l] <= pivot
# arr[h+1:high+1] >= pivot
l = low + 1
h = high
while l <= h:
while l <= h and arr[l] <= pivot:
l += 1
while l <= h and arr[h] > pivot:
h -= 1
if l < h:
#  arr[l] > pivot and arr[h] <= pivot, switch them.
arr[l], arr[h] = arr[h], arr[l]
# satisfy l == h + 1 and arr[low:l] <= pivot and arr[l:high+1] > pivot
# so arr[h] <= pivot
arr[low], arr[h] = arr[h], pivot
return h```

## 第四种

1. 选择当前数组第 0 个元素作为分界值
2. `arr[low:l] < pivot and arr[l:scanner] == pivot and arr[h+1:high+1] > pivot and arr[scanner:h+1] to scan`
```def qsort3(arr: list, low: int, high: int):
if low >= high:
return
pivot = arr[low]
# arr[low:l] < pivot
# arr[l] == pivot
# arr[h+1:high+1] > pivot
l = low
h = high
scanner = low + 1
while scanner <= h:
if arr[scanner] < pivot:
arr[l], arr[scanner] = arr[scanner], arr[l]
l += 1
scanner += 1
elif arr[scanner] > pivot:
arr[h], arr[scanner] = arr[scanner], arr[h]
h -= 1
else:
scanner += 1
# scanner == h + 1
# arr[l] == pivot
# arr[h] == pivot
# arr[low:l] < pivot and arr[h+1:high+1]
# so split the arr to three part: arr[low:l] + arr[l:h+1] + arr[h+1:high+1]
qsort3(arr, low, l - 1)
qsort3(arr, h + 1, high)```

## 第五种

```type Node struct {
v    interface{}
k    int
next *Node
}

// Quick sort for list [start, end)
func qsortList(start, end *Node) {
if start == end {
return
}
p, q := start, start.next
for q != end {
if q.k < p.k {
// swap the value, not change list structure
swap(p, q)
p = p.next
swap(p, q)
}
q = q.next
}
// sort [start, p)
qsortList(start, p)
// sort (p, end)
qsortList(p.next, end)
}

func swap(p, q *Node) {
p.v, q.v = q.v, p.v
p.k, q.k = q.k, p.k
}```

# Conclusion

1. 掌握算法的核心思想
2. 设定几个边界条件
3. 变量在变化过程中严格遵守边界条件