算法之排序算法总结

个人总结,仅供参考。详细内容请阅读《Introduce to Algorithm》算法导论

heap sort

  • 用数组存储最大堆,用二叉树表示最大堆特征结构
    图1(heap与array对应关系)
    这里写图片描述
Parent(i)
return i/2 取下等
Left(i)
return 2i
Right(i)
return 2i+1

max-heap的特征 : A[Parent(i)]>=A[i]

method:

  • maxHeapity:时间复杂程度为O(lgn), 是维护max-heap性质的关键.
  • buildMaxHeap:线性时间复杂程度, 输入一个乱序的数组,最终生成最大堆.
  • heapSort:时间复杂程度为O(nlgn), 对数组进行排序.
  • maxHeapInsert、heapExtractMax、heapIncreaseKey、heapMaximum : 时间复杂程度为O(lgn) , 利用堆实现优先级队列.

图2(求maxHeapity)
maxHeapity

//maxHeapity : 假设节点i的左右子树都已经是最大堆
maxHeapity(A, i ) {
  l = Left(i)
  r = Right(i)
  largest = i
  if l <= A.hipeSize && A[l] > A[i]
    largest = l
  if r < A.heapSize && A[r] > A[largest]
    largest = r
  if largest != i
    exchange A[i] with A[largest] //**不稳定**
    maxHeapity(a, largest)
}

图3(buidMaxHeap)
buidMaxHeap

buildMaxHeap(A) {
  A.heapSize = A.length
      for i = A.length/2 to 1 //取下等
         maxHeapity(A, i)
}

heapSort(A) {
  buildMaxHeap(A)
  for i = A.length dowmto 2
    exchange A[1] with A[i]
    A.heapSize = A.heapSize - 1
    maxHeapity(A, 1)
}
  • priority queue:根据排序数值的大小,确定优先级
heapMaximum(A){
 return A[1]
}

heapExtractMax(A) {
  if A.heapSize < 1
    error "heap underflow"
  max = A[1]
  A[1] = A[A.heapSize]
  A.heapSize = A.heapSize -1
  maxHeapity(A, 1)
  return max
}

heapIncreaseKey(A, i, key) {
  if key < A[i]
    error "new key is smaller than current key"
  A[i] = key
  while i > 1 and A[PARENT[i] < A[i]]
   exchange A[i] with A[PARENT[i]]
   i = PARENT[i]
}

maxHeapInsert(A, key) {
  A.heapSize = A.heapSize + 1
  A[A.heapSize] = -@
  heapIncreaseKey(A, A.heapSize ,key)
}

扩展:思考如何使用FIFO队列,FILO栈实现优先级队列。

quick sort

  • 思路:拆分–根据pivot把数组分为两半
    图4(partition示意图)
    partition
quickSort(A, p, r) {
  if p < r
    q = partition(A, p, r)
    quickSort(A, p, q - 1)
    quickSort(A, q + 1, r)
}

partition(A, p, r) {
  x = A[r]
  i = p - 1
  for j = p to 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
}

扩展:注意我们选择的partition选取的pivot总是最后一个数,思考如何实现随机选取pivot。文章底部给出实现思路。

insert,bubble,select sort O(n2)

  • bubble : 找到最大数,移到最后
  • Insert :从后插入到排好序的数值
  • shell : 缩小增量排序,又叫分组插入排序法,根据增量分成相应的组,再缩小增量,到1。
  • select : 从待排序的数组中选出最大或最小元素,与起始位置交换 //不稳定
insertSort(A) {
  for j = 2 to A.length
    key = A[j]
    //Insert A[j] into the sorted sequence A[1..j - 1]
    i = j - 1
    while i > 0 && A[i] > key
      A[i + 1] = A[i]
      i = i - 1
    A[i + 1] = key  
}

merge sort

  • 思路:先拆分,再合并排好序的两个数组
mergeSort(A, p, r) {
  if p < r
    q = _(p + r)/2_
    mergeSort(A, p , q)
    mergeSort(A, p + 1, r)
    merge(A, p, q, r)
}

merge(A, p, q, r) {
  n1 = q - p + 1
  n2 = r - q
  let L[1..n1 + 1] and R[1..n2 + 1] be new array
  for i = 1 to n1
    L[i] = A[p + i -1]
  for j = 1 to n2
    R[j] = A[q + j]
  L[n1 + 1] = @
  R[n2 + 1] = @
  i = 1
  j = 1
  for k = p to r
    if L[i] <= R[j]
      A[k] = L[i]
      i = i + 1
    else A[k] = R[j]
      j = j + 1
}

bucket sort

适合场景:输入的n个数在很小的一个区间内, 平均时间复杂程度为O(n).
图5(桶排序示意图)
bucketSort

bucketSort(A) {
  let B[0..n - 1] be a new array
  n = A.length
  for i = 0 to n - 1
    make B[i] an empty list
  for i = 1 to n
    insert A[i] into list B[_nA[i]_]
  for i = 0 to n - 1
    sort list B[i] with insertion sort
  concatenate the list B[0]...B[n - 1] together in order
}

radix sort

假设数组A中的元素都是d位数的整数,1是最小的位数,d是最高的位数。如图6是由d = 3 组成的数组
图6(radixSort示意图)
radixSort

radixSort(A, d) {
  for i = 1 to d
    use a stable sort to sort array A on digit i
}

图7(排序算法总结)
排序算法总结

//随机快排
quickSortRandom(A, p, r) {
  if p < r
    q = partitionRandom(A, p, r)
    quickSortRandom(A, p, q - 1)
    quickSortRandom(A, q + 1, r)
}

partitionRandom(A, p, r) {
  x = random(p, r);
  exchange A[x] with A[r]
  return partition(A, p, r)
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值