稳定排序与不稳定排序
如果排序后原本相等的两个数的相对位置发生了变化,则说明算法 不是 稳定排序算法。
冒泡排序
如果相邻的两个元素逆序,则交换。
冒泡排序是稳定排序算法。
1
2
3
4
5
6
7
8
9
10
|
def bubble_sort(nums: List[int]):
n = len(nums)
swapped = True
while swapped:
swapped = False
for i in range(1, n):
if nums[i] < nums[i - 1]:
swapped = True
nums[i], nums[i - 1] = nums[i - 1], nums[i]
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
void bubble_sort(vector<int> &nums) {
int n = nums.size();
bool swapped = true;
while (swapped) {
swapped = false;
for (int i = 1; i < n; ++i) {
if (nums[i] < nums[i - 1]) {
swapped = true;
swap(nums[i], nums[i - 1]);
}
}
}
}
|
选择排序
选择 $a[i]$ 之后比 $a[i]$ 小的最小值与 $a[i]$ 进行交换。
选择排序是 不 稳定排序算法,如序列 $[3_1,3_2,2]$ 排序后变为了 $[2,3_2,3_1]$。
1
2
3
4
5
6
7
8
9
10
11
12
|
def selection_sort(nums: List[int]):
n = len(nums)
for i in range(n - 1):
k = i
for j in range(i + 1, n):
if nums[j] < nums[k]:
k = j
if k != i:
nums[i], nums[k] = nums[k], nums[i]
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
void selection_sort(vector<int> &nums) {
int n = nums.size();
for (int i = 0; i < n - 1; ++i) {
int k = i;
for (int j = i + 1; j < n; ++j) {
if (nums[j] < nums[k]) {
k = j;
}
}
if (k != i) {
swap(nums[i], nums[k]);
}
}
}
|
插入排序
插入排序即将当前位置的数插入到之前已经有序的数之中。
插入排序是稳定排序算法。
1
2
3
4
5
6
7
8
9
10
11
12
|
def insertion_sort(nums: List[int]) -> None:
n = len(nums)
for i in range(1, n):
t = nums[i]
j = i - 1
while j >= 0 and nums[j] > t:
nums[j + 1] = nums[j]
j -= 1
nums[j + 1] = t
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
void insertion_sort(vector<int> &nums) {
int n = nums.size();
for (int i = 1; i < n; ++i) {
int t = nums[i], j = i - 1;
while (j >= 0 && nums[j] > t) {
nums[j + 1] = nums[j];
--j;
}
nums[j + 1] = t;
}
}
|
快速排序
将某个位置的数 $nums[i]$ 作为关键字,小于等于 $nums[i]$ 放在 $nums[i]$ 的左边,大于等于 $nums[i]$ 的数放在 $nums[i]$ 的右边。
快速排序是 不 稳定排序算法,如序列 $[3,2_1,2_2]$ 排序后后变为了 $[2_2,2_1,3]$。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
def partition(nums: List[int], lo: int, hi: int) -> int:
pivot = nums[lo]
while lo < hi:
while lo < hi and nums[hi] >= pivot:
hi -= 1
nums[lo] = nums[hi]
while lo < hi and nums[lo] <= pivot:
lo += 1
nums[hi] = nums[lo]
nums[lo] = pivot
return lo
def quick_sort(nums: List[int], lo: int, hi: int) -> None:
if lo < hi:
pos = partition(nums, lo, hi)
quick_sort(nums, lo, pos - 1)
quick_sort(nums, pos + 1, hi)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
int partition(vector<int> &nums, int lo, int hi) {
int pivot = nums[lo];
while (lo < hi) {
while (lo < hi && nums[hi] >= pivot) {
--hi;
}
nums[lo] = nums[hi];
while (lo < hi && nums[lo] <= pivot) {
++lo;
}
nums[hi] = nums[lo];
}
nums[lo] = pivot;
return lo;
}
void quick_sort(vector<int> &nums, int lo, int hi) {
if (lo < hi) {
int pos = partition(nums, lo, hi);
quick_sort(nums, lo, pos - 1);
quick_sort(nums, pos + 1, hi);
}
}
|
归并排序
归并排序是稳定排序算法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
def merge(nums: List[int], tmp: List[int], lo: int, mid: int, hi: int) -> None:
i, j, k = lo, mid + 1, 0
while i <= mid or j <= hi:
if i <= mid and (j > hi or nums[i] <= nums[j]):
tmp[k] = nums[i]
i += 1
else:
tmp[k] = nums[j]
j += 1
k += 1
nums[lo: hi + 1] = tmp[:k]
def merge_sort(nums: List[int], tmp: List[int], lo: int, hi: int) -> None:
if lo < hi:
mid = lo + ((hi - lo) >> 1)
merge_sort(nums, tmp, lo, mid)
merge_sort(nums, tmp, mid + 1, hi)
merge(nums, tmp, lo, mid, hi)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
void merge(vector<int> &nums, vector<int> &tmp, int lo, int mid, int hi) {
int i = lo, j = mid + 1, k = 0;
while (i <= mid || j <= hi) {
if (i <= mid && (j > hi || nums[i] <= nums[j])) {
tmp[k++] = nums[i++];
} else {
tmp[k++] = nums[j++];
}
}
copy(tmp.begin(), tmp.begin() + k, nums.begin() + lo);
}
void merge_sort(vector<int> &nums, vector<int> &tmp, int lo, int hi) {
if (lo < hi) {
int mid = lo + ((hi - lo) >> 1);
merge_sort(nums, tmp, lo, mid);
merge_sort(nums, tmp, mid + 1, hi);
merge(nums, tmp, lo, mid, hi);
}
}
|
基数排序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
def radix_sort(nums: List[int]) -> None:
n = len(nums)
output = [0] * n
max_val = max(nums)
exp = 1
while max_val // exp:
count = [0] * 10
for x in nums:
count[(x // exp) % 10] += 1
for i in range(1, 10):
count[i] += count[i - 1]
for x in reversed(nums):
count[(x // exp) % 10] -= 1
output[count[(x // exp) % 10]] = x
nums[:] = output
exp *= 10
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
void radix_sort(vector<int> &nums) {
int n = nums.size();
vector<int> output(n);
int max_val = *max_element(nums.begin(), nums.end());
int exp = 1;
while (max_val / exp) {
vector<int> count(10);
for (const int &x : nums) {
count[(x / exp) % 10] += 1;
}
for (int i = 1; i < 10; ++i) {
count[i] += count[i - 1];
}
for (int i = n - 1; i >= 0; --i) {
output[--count[(nums[i] / exp) % 10]] = nums[i];
}
copy(output.begin(), output.end(), nums.begin());
exp *= 10;
}
}
|
希尔排序
堆排序
总结