The principle and implementation of common sorting algorithms

Original link: http://www.nosuchfield.com/2022/05/27/Principles-and-implementation-of-common-sorting-algorithms/

Bubble Sort

The principle of bubble sort is very simple, that is to move the largest (or smallest) element in the current unordered sequence to the beginning (or end) of the sequence every time, and then do the same operation to the remaining sequences except the element. . When all elements have been bubbled, the entire sequence becomes ordered. The process of bubble sort, as its name suggests, moves the largest element in the sequence to the end each time (assuming we choose this rule), which is like a bubble in water constantly floating from water to surface. .

The implementation of bubble sort is as follows, and a simple observation shows that its time complexity is O(n 2 )

 1
2
3
4
5
6
 def bubble_sort (arr) :
length = len(arr)
for i in range(length - 1 ):
for j in range(length - 1 - i):
if arr[j] > arr[j + 1 ]:
arr[j], arr[j + 1 ] = arr[j + 1 ], arr[j]

selection sort

Similar in principle to bubble sort, the difference is that bubble sort compares the size of adjacent elements, while selection sort compares the size with a fixed value, eliminating some unnecessary comparison processes. The same is to get the minimum value of an unordered sequence and put it at the beginning. Bubble sort compares and exchanges values ​​one by one, while selection sort uses the first element as the reference value for comparison. After getting the minimum value, you only need to put the minimum value. Swap with the beginning element.

The selection sort is implemented as follows, and the complexity is O(n 2 )

 1
2
3
4
5
6
7
8
 def select_sort (arr) :
length = len(arr)
for i in range(length):
min_num_index = i
for j in range(i, length):
if arr[j] < arr[min_num_index]:
min_num_index = j
arr[min_num_index], arr[i] = arr[i], arr[min_num_index]

Insertion sort

Insertion sort divides the sequence into two parts, one is ordered and the other is unordered. Each time an element is selected from the unordered sequence and inserted into the correct position in the sorted sequence, it is guaranteed that the sorted sequence is still in order, just as the cards are constantly drawn and inserted into the correct position when playing cards. Here we treat the first half of the sequence as an ordered sequence, and the second half as an unordered sequence.

Insertion sort is implemented as follows, and the complexity is O(n 2 )

 1
2
3
4
5
6
7
8
9
 def insert_sort (arr) :
length = len(arr)
for i in range( 1 , length):
value = arr[i]
j = i - 1
while j >= 0 and value < arr[j]: # Move the element forward
arr[j + 1 ] = arr[j] # Shift all one bit backward
j -= 1
arr[j + 1 ] = value

merge sort

Merge sort is to merge two ordered sequences into one sequence, and the ordered sequence before merging can be obtained by merging the two ordered sequences, and so on, the sorting is finally realized.

Merge sort is implemented as follows, the complexity is O(NlogN)

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
twenty one
twenty two
twenty three
twenty four
25
26
27
28
29
30
31
32
33
34
35
 def merge_sort (arr) :
def _merge_sort (_arr, left, right) :
if left >= right:
return
# Calculate the middle position
mid = (left + right) // 2
# Get the ordered sequence of the left half
_merge_sort(_arr, left, mid)
# Get the ordered sequence of the right half
_merge_sort(_arr, mid + 1 , right)

tmp = []
i = left
j = mid + 1
while i <= mid or j <= right: # traverse
if i > mid: # i has reached the end, only j
tmp.append(_arr[j])
j += 1
continue
if j > right: # j has reached the end, only i is saved
tmp.append(_arr[i])
i += 1
continue

# take the smaller value
if _arr[i] < _arr[j]:
tmp.append(_arr[i])
i += 1
else :
tmp.append(_arr[j])
j += 1

_arr[left: right + 1 ] = tmp # make this sequence ordered

_merge_sort(arr, 0 , len(arr) - 1 )

quick sort

Similar to quicksort and mergesort, they both use divide and conquer. The difference is that merge sort first creates two ordered subsequences, while quick sort randomly selects a pivot, and then places the value greater than the element on the right, and the value less than the element on the left. Repeating this, the final sequence becomes ordered.

Quicksort is implemented as follows, with a complexity of O(NlogN)

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 def quick_sort (arr) :
def _quick_sort (_arr, left, right) :
if left >= right:
return

pivot = random.randint(left, right) # random a pivot
_arr[pivot], _arr[right] = _arr[right], _arr[pivot] # put this value on the far right
j = left
for i in range(left, right):
if _arr[i] < _arr[right]: # If the current value is less than the value corresponding to pivot
_arr[i], _arr[j] = _arr[j], _arr[i] # put this value to the left
j += 1
_arr[j], _arr[right] = _arr[right], _arr[j] # Finally put this value in the middle of the small value and the large value

# Divide and conquer the values ​​on the left and right sides
_quick_sort(_arr, left, j - 1 )
_quick_sort(_arr, j + 1 , right)

_quick_sort(arr, 0 , len(arr) - 1 )

The complete code with all sorting algorithms and tests is as follows

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
twenty one
twenty two
twenty three
twenty four
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
 import copy
import random
import time


def time_keep (func) :
def wrapper (*args, **kw) :
start = time.time()
result = func(*args, **kw)
end = time.time()
print( '{:>12}: {}' .format(func.__name__, (end - start) * 1000 ))
return result

return wrapper


def get_array (start= 0 , end= 5000 , length= 1000 ) :
if start >= end or length <= 0 :
return []
random_list = []
for i in range(length):
random_list.append(random.randint(start, end))
return random_list


@time_keep
def bubble_sort (arr) :
length = len(arr)
for i in range(length - 1 ):
for j in range(length - 1 - i):
if arr[j] > arr[j + 1 ]:
arr[j], arr[j + 1 ] = arr[j + 1 ], arr[j]


@time_keep
def select_sort (arr) :
length = len(arr)
for i in range(length):
min_num_index = i
for j in range(i, length):
if arr[j] < arr[min_num_index]:
min_num_index = j
arr[min_num_index], arr[i] = arr[i], arr[min_num_index]


@time_keep
def insert_sort (arr) :
length = len(arr)
for i in range( 1 , length):
value = arr[i]
j = i - 1
while j >= 0 and value < arr[j]: # Move the element forward
arr[j + 1 ] = arr[j] # Shift all one bit backward
j -= 1
arr[j + 1 ] = value


@time_keep
def merge_sort (arr) :
def _merge_sort (_arr, left, right) :
if left >= right:
return
# Calculate the middle position
mid = (left + right) // 2
# Get the ordered sequence of the left half
_merge_sort(_arr, left, mid)
# Get the ordered sequence of the right half
_merge_sort(_arr, mid + 1 , right)

tmp = []
i = left
j = mid + 1
while i <= mid or j <= right: # traverse
if i > mid: # i has reached the end, only j
tmp.append(_arr[j])
j += 1
continue
if j > right: # j has reached the end, only i is saved
tmp.append(_arr[i])
i += 1
continue

# take the smaller value
if _arr[i] < _arr[j]:
tmp.append(_arr[i])
i += 1
else :
tmp.append(_arr[j])
j += 1

_arr[left: right + 1 ] = tmp # make this sequence ordered

_merge_sort(arr, 0 , len(arr) - 1 )


@time_keep
def quick_sort (arr) :
def _quick_sort (_arr, left, right) :
if left >= right:
return

pivot = random.randint(left, right) # random a pivot
_arr[pivot], _arr[right] = _arr[right], _arr[pivot] # put this value on the far right
j = left
for i in range(left, right):
if _arr[i] < _arr[right]: # If the current value is less than the value corresponding to pivot
_arr[i], _arr[j] = _arr[j], _arr[i] # put this value to the left
j += 1
_arr[j], _arr[right] = _arr[right], _arr[j] # Finally put this value in the middle of the small value and the large value

# Divide and conquer the values ​​on the left and right sides
_quick_sort(_arr, left, j - 1 )
_quick_sort(_arr, j + 1 , right)

_quick_sort(arr, 0 , len(arr) - 1 )


if __name__ == '__main__' :
random_array = get_array()

array1 = copy.deepcopy(random_array)
bubble_sort(array1)
print(array1)

array2 = copy.deepcopy(random_array)
select_sort(array2)
print(array2)

array3 = copy.deepcopy(random_array)
insert_sort(array3)
print(array3)

array4 = copy.deepcopy(random_array)
merge_sort(array4)
print(array4)

array5 = copy.deepcopy(random_array)
quick_sort(array5)
print(array5)

refer to

Top 10 Common Sorting Algorithms
Common basic sorting algorithms

This article is reprinted from: http://www.nosuchfield.com/2022/05/27/Principles-and-implementation-of-common-sorting-algorithms/
This site is for inclusion only, and the copyright belongs to the original author.

Leave a Comment