插入排序 insertion-sort
插入排序原理:像排序扑克牌,开始时左手为空并且桌面上牌面向下。然后,每次从桌子上拿走一张并将它插入到正确的位置。为了找到每一张牌的正确位置,我们从右到左将它与手中的牌进行比较。
时间复杂度:O(n2)
def insertion-sort(A): #A为数组 for j in range(2, length(A)): key = A[j] i = j-1 #将A[i]插入序列A[1,2,3,...,j] while i > 0 && A[i] > key: A[i+1] = A[i] i = i - 1 A[i+1] = key
2. 归并排序算法 merge
归并排序算法原理:假设桌上有两堆牌面朝上的牌,每堆都已排序,最小的牌在顶上。基本步骤是从朝上的两堆牌中挑选比较小的一张,将该牌从堆中移开。为避免每次都检查堆是否为空,在每个堆底部放一张哨兵牌:inf。
时间复杂度:O(nlgn)
def merge(A, p, q, r): n1 = p-q+1 n2 = r - q L = 0 * [n1+1] R = 0 * [n2+1] for i in range(1, n1): L[i] = A[p+i-1] for j in range(1, n2): R[j] = A[q+j] L[n1+1] = sys.maxint #inf R[n2+1] = sys.maxint #inf i = 1 j = 1 for k in range(p,r): if L[i] <= R[j]: A[k] = L[i] i += 1 else: A[k] = R[j] j = j + 1 def merge-sort(A, p, r): if p < r: q = (p + r)/2 merge-sort(A, p, q) merge-sort(A, q+1, r) merge(A, p, q, r)
3. 堆排序
时间复杂度:O(nlgn) 具有空间原址性,需要常数个临时存储空间
二叉堆是一个数组
二叉堆分为最大堆和最小堆
最大堆:除了根节点外所有结点i都满足 A[parent(i)] >= A[i]------》在堆排序算法中使用
最小堆:除了根节点外所有结点i都满足 A[parent(i)] <= A[i]------》用于构建优先队列
def parent(i): return i/2 def lift(i): return 2i def right(i): return 2i + 1 ''' 维护最大堆的性质,输入为一个数组A, 和一个下标i. 在调用max-heapify时,假定根节点为left(i), right(i)的二叉树都是最大堆 但这是A[i] 有可能小于其他孩子,这就违背了最大堆的性质,此方法通过让A[i] 逐级下降,使下标i为根节点的子树重新遵循最大堆的性质 ''' def max-heapify(A, i): l = left(i) r = right(i) if l <= A.length() and A[l] > A[i]: largest = l else: largest = i if r <= A.length() and A[r] > A[largest]: largest = r if largest != i: temp = A[i] A[i] = A[largest] A[largest] = temp max- heapify(A, largest) ''' 建堆:对树中的其他结点都调用一次max-heapify ''' def build-max-heap(A): A.heap-size = A.length() for i in range(A.heap-size, 1): max-heapify(A, i) ''' 堆排序算法 ''' def heapsort(A): build-max-heap(A) for i in range(A.length(), 2): temp = A[1] A[1] = A[i] A[i] = temp A.heap-size = A.heap-size - 1 max-heapify(A, 1) 4. 快速排序 时间复杂度:O(nlgn) (期望) 原址性 def quicksort(A, p ,r): if p < r: q = partition(A, p ,r) quicksort(A, p ,q-1) quicksort(A, q+1, r) def partition(A, p, r): x = A[r] i = p - 1 for j in range(p, r-1): if A[j] <= x: i = i + 1 exchange A[i] with A[j] exchange A[i+1] with A[r] return i+1
1、2、3、4比较排序
5、6、7 线性时间排序
5. 计数排序
基本思想:对每一个输入元素x,确定小于x的元素个数。利用这一信息,就可以直接把x放到它在输出数组中的位置上。在计数排序算法中,输入A[1,,,,n] A.length() = n。还需要两个数组 B[1,,,,,n]存放排序的输入, C[0,k] 提供临时存储空间
def counting-sort(A, B, k): C = (k+1) * [0] #初始化一个数组C[0,,,,k] for j in range(1, A.length()): C[A[j]] = C[A[j]] + 1 #C[i]表示等于i元素的个数 for i in range(1, k): C[i] = C[i] + C[i-1] #计算有多少元素小于等于i for j in range(A.length(), 1): B[C[A[j]]] = A[j] C[A[j]] = C[A[j]] - 1
6. 基数排序
假设n个d位元素存放在数组A中,1是最低位,d是最高位
def radix-sort(A, d): for i in range(1, d): use a stable sort to sort array A on digit
7. 桶排序
def bucket-sort(A): n = A.length() B = n * [0] for i in range(1, n): insert A[i] into B[nA[i]] for i in range(0, n-1): sort list B[i] with inserton sort concatenate the list B[0],B[1],....B[n] together in order