Basic 7 Algorithms in Python
Bubble Sort(冒泡排序)
Main Idea: use two loops to iterate data array, find the maximum, and throw it to the end.
(两次循环,每次选大的放在后面,重复,直到没有数据)
Feature: Stable
O(n^2)
def bubble_sort(arr):
for i in range(len(arr)):
for j in range(0, len(arr) - i - 1):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
return arr
Alternative: add a flag into outter loop, reducing the # of comparison.
(通过在外循环设置标志位,可以减少比较的次数,但意义不大)
def bubble_sort(arr):
for i in range(len(arr)):
flag = 0
for j in range(0, len(arr) - i - 1):
if arr[j] >= arr[j + 1]:
flag += 1
arr[j], arr[j + 1] = arr[j + 1], arr[j]
if flag == 0:
break
return arr
Selection Sort(选择排序)
Main Idea: use two loops to iterate data array, find the minimum, and insert it at the beginning.
(两次循环,每次选小的放在前面,重复,直到没有数据)
Feature: Unstable
O(n^2)
def selection_sort(arr):
for i in range(len(arr)):
for j in range(i, len(arr)):
if arr[i] > arr[j]:
arr[i], arr[j] = arr[j], arr[i]
return arr
Alternative: store the current index, reducing the # of switching.
(通过在外循环存储的索引, 减少数据交换的次数)
def selection_sort(arr):
for i in range(len(arr)):
min_idx = i
for j in range(i, len(arr)):
if arr[min_idx] > arr[j]:
min_idx = j
if i != min_idx:
arr[i], arr[min_idx] = arr[min_idx], arr[i]
return arr
Insertion Sort(插入排序)
Main Idea: use two loops to iterate data array simultaneously, insert a new data item into sorted results at an appropriate location. and push the rest data behind this location as a whole.
(两次循环,将无序数据插入到已经有序的结果中,在插入位置,将后面的数据整体后移,重复,直到没有数据)
Feature: Stable
O(n^2)
def insertion_sort(arr):
for i in range(len(arr)):
prev_idx = i - 1
current = arr[i]
while prev_idx >= 0 and arr[prev_idx] > current:
arr[prev_idx + 1] = arr[prev_idx]
prev_idx -= 1
arr[prev_idx + 1] = current
return arr
Alternative1: use binary search to find the location where the new element should insert.
(用二分查找,找到需要插入的位置)
def insertion_sort(arr):
for i in range(len(arr)):
current = arr[i]
low, high = 0, i - 1
while low <= high:
mid = int((low + high) / 2)
if current < arr[mid]:
high = mid - 1
else:
low = mid + 1
for j in range(i, low, -1):
arr[j] = arr[j - 1]
arr[low] = current
return arr
Alternative2: use a descreasing number as a gap, to accelerate seaching process.
(用一个递减的数值,作为间隔,每轮中,比较每个间隔对应的值,结合直接插入排序。 还有另外一个名字-希尔排序)
def insertion_sort(arr):
gap = len(arr) // 2
while gap >= 1:
for i in range(gap, len(arr)):
end_val = arr[i]
front_idx = i - gap
while front_idx >= 0 and arr[front_idx] > end_val:
arr[front_idx + gap] = arr[front_idx]
front_idx -= gap
arr[front_idx + gap] = end_val
gap //= 2
return arr
Feature: Unstable
O(nlogn)
Merge Sort(归并排序)
Main Idea: a classic sorting solution using divide-and-conquer. split data into pieces, and sort those small data and combine all of them.
(递归地把当前序列平均分成两半, 分到只剩一个元素的时候, 停止切分开始进行两两排序,当解决完N个小问题之后,就可以把结果再拼装起来)
Feature: Stable
O(nlogn)
def merge(left, right):
res = []
while left and right:
min_val = left.pop(0) if left[0] < right[0] else right.pop(0)
res.append(min_val)
res += left if left else right
return res
def merge_sort(arr):
if len(arr) <= 1:
return arr
mid = len(arr) // 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
return merge(left, right)
Alternative: instead, use a recursion method to write this algorithm, we can also use an iteration way.
(除了使用递归方式去实现归并排序,也可以使用迭代的思路去实现)
def merge(arr, low, mid, high):
left = arr[low: mid]
right = arr[mid: high]
res = []
while left and right:
min_val = left.pop(0) if left[0] < right[0] else right.pop(0)
res.append(min_val)
res += left if left else right
arr[low: high] = res
def merge_sort(arr):
sub_length = 1
while sub_length < len(arr):
low = 0
while low < len(arr):
mid = low + sub_length
high = min(low + 2 * sub_length, len(arr))
if mid < high:
merge(arr, low, mid, high)
low += 2 * sub_length
sub_length *= 2
return arr
Test Code Link1 | Test Code Link2
Quick Sort(快速排序)
Main Idea: another classic solution using divide-and-conquer. choose an item as pivot, split data into two part, one part is less than pivot, the rest will greater than pivot. continue doing this until no data.
(通过设置枢轴的方式,将原始数据分成两个部分,将两个小部分排序并把结果最后合起来,重复切分,直到没有数据)
Feature: Unstable
O(nlogn)
def quick_sort(arr, left, right):
if left < right:
pivot = arr[right]
low, high = left, right
while left< right:
while left < right and arr[left] < pivot:
left += 1
arr[right] = arr[left]
while left < right and arr[right] > pivot:
right -= 1
arr[left] = arr[right]
arr[left] = pivot
quick_sort(arr, low, left - 1)
quick_sort(arr, left + 1, high)
return arr
Alternative1: the most easy way to do quick sorting.
(我认为是最容易理解的一种实现方式)
def quick_sort(arr):
if arr:
pivot = arr[0]
less = [x for x in arr if x < pivot]
great = [x for x in arr if x > pivot]
return quick_sort(less) + [pivot] + quick_sort(great)
else:
return []
Alternative2: 1. return the index of pivot. 2. split the data.
(设置一个函数返回枢轴的位置,以此位置切分原始数据,一直迭代下去)
def quick_sort(arr, left, right):
if left < right:
pivot_idx = split(arr, left, right)
quick_sort(arr, left, pivot_idx - 1)
quick_sort(arr, pivot_idx + 1, right)
return arr
def split(arr, left, right):
pivot = arr[right]
i = left - 1
for j in range(left, right):
if arr[j] <= pivot:
i += 1
arr[i], arr[j] = arr[j], arr[i]
arr[i + 1], arr[right] = pivot, arr[i + 1]
return i + 1
Test Code Link1 | Test Code Link2
Counting Sort(计数排序)
Main Idea: convert data item into key-value pair, the iterate the keys.
(将输入的数据值转化为键存储在额外开辟的桶空间中,然后遍历生成的桶,从小到大依次拿出来就是结果)
Feature: Stable
O(n + k)
def bucket_sort(arr):
buckets = [0] * ((max(arr) - min(arr)) + 1)
for i in range(len(arr)):
buckets[arr[i] - min(arr)] += 1
res = []
for i in range(len(buckets)):
if buckets[i] != 0:
res += [i + min(arr)] * buckets[i]
return res
Waning: to be honest, no one will use this to solve real-world problem. will waste lot of memory space.
(没什么人会用)
Radix Sort(基数排序)
Main Idea: distribute the data into buckets based on their unit digit. and collect all of them, and then redistribute them based on their tens digit, continue doing this way.
(依次用原始数据各项的个十百等数位进行映射,每次映射后,再将桶里的数据依次提出来,覆盖表原来的数据,重复下去直到所有数位都用完)
Feature: Stable
O(n*k)
def radix_sort(arr):
digit = 0
max_digit = 1
max_value = max(arr)
while 10 ** max_digit < max_value:
max_digit += 1
while digit < max_digit:
buckets = [[] for _ in range(10)]
for i in arr:
num = int((i / 10 ** digit) % 10)
buckets[num].append(i)
temp_result = []
for bucket in buckets:
temp_result.extend(bucket)
arr = temp_result
digit += 1
return arr
Warning: What should I say, same as the counting sort, even though it has some improvement.
(跟计数排序一样,没人用)
笔记完整代码Github: https://github.com/AaronYang2333/CSCI_570/wiki
持续更新!