一、冒泡排序
冒泡排序的的简单版本
简单选择排序,时间复杂度O(n^2)
ls = [1,2,445,77,43] length = len(ls) for i in range(length-1): for j in range(i,length-1): if ls[j] > ls[j+1]: ls[j],ls[j+1] = ls[j+1],ls[j] print(ls)
升级版,设置flag,当flag不再变化的时候说明后面的序列已经是有序的了,无需再判断。
ls = [1,2,445,77,43] length = len(ls) i = 0 flag = True while i<length-1 and flag: flag = False for j in range(i,length-1): if ls[j] > ls[j+1]: ls[j],ls[j+1] = ls[j+1],ls[j] flag=True print(ls)
二、选择排序
class Sqlist(): def __init__(self, ls): self.r = ls def select_sort(self): ls = self.r length = len(self.r) for i in range(length - 1): min = i for j in range(i + 1, length): if ls[i] > ls[j]: min = j if min != i: ls[i], ls[min] = ls[min], ls[i]
三、直接插入排序
class SQlist(): def __init__(self,ls): self.r = ls def insert_sort(self): ls=self.r length = len(ls) for i in range(1,length): if ls[i] < ls[i-1]: temp = ls[i] j = i - 1 while j>=0 and ls[j]>temp: ls[j+1] = ls[j] j-=1 ls[j+1] = temp ls = SQlist([3,1,4,5,2,9,8]) ls.insert_sort() print(ls.r)
四、归并排序
def merge(a,b): c = [] h = j = 0 while j < len(a) and h < len(b): if a[j] < b[h]: c.append(a[j]) j += 1 else: c.append(b[h]) h += 1 if j == len(a): for i in b[h:]: c.append(i) else: for i in a[j:]: c.append(i) return c def merge_sort(lists): if len(lists) <= 1: return lists middle = len(lists)//2 left = merge_sort(lists[:middle]) right = merge_sort(lists[middle:]) return merge(left, right) print(merge_sort([2,12,42,11,6,7,23]))
五、快速排序
思想:选择第一个数作为基准,使用双指针,i,j 分别指向列表开头和结尾,然后j指针先走(一定要尾指针先走!!),找到比基准小的数,然后停下。接着i指针先前走,找到第一个比基准大的数,这时候交换这两个数,交换完j指针继续向前走(再次注意!)。一直重复上述步骤,知道i=j停下,然后交换基准和当前的数。上面操作达到的效果是,基准归位!比基准小的在左边,比基准大的在右边。 递归上述步骤,即可完成排序。
def quicksort(lst, l, r): if r - l <= 1: return lst i, j = l, r while i < j: if lst[j] >= lst[l]: #j要放在前面 j -= 1 elif lst[i] <= lst[l]: i += 1 else: lst[i], lst[j] = lst[j], lst[i] j -= 1 lst[l], lst[i] = lst[i], lst[l] quicksort(lst, l, i) quicksort(lst, i + 1, r) return lst
上面步骤可能不直观,可以看看下面这解法,这种解法对快排的本质有很好的阐述。
def quicksort(L): if len(L) <= 1: return L return quicksort([lt for lt in L[1:] if lt <= L[0]]) + L[0:1] + quicksort([lt for lt in L[1:] if lt > L[0]])
注意:上面不是在原来列表的基础上排序,而是生成一个新的列表。如果要在原列表基础上排序。可以用切片赋值回去。不是原地排序空间复杂度高。
交换的核心思想是:保持左边是一个比基准小的序列。右边看成未知的。
import random from typing import List def quick_sort(a: List[int]): _quick_sort_inner(a, 0, len(a) - 1) def _quick_sort_inner(a: List[int], low: int, high: int): if high <= low: return m = _partition(a, low, high) _quick_sort_inner(a, low, m - 1) _quick_sort_inner(a, m + 1, high) def _partition(a: List[int], low: int, high: int): k = random.randint(low, high) a[k], a[low] = a[low], a[k] pivot, j = a[low], low for i in range(low + 1, high + 1): if a[i] < pivot: j += 1 a[j], a[i] = a[i], a[j] a[low], a[j] = a[j], a[low] return j
附:所有排序算法的动态演示:
http://tools.jb51.net/aideddesign/paixu_ys