排序算法

1 快速排序

快速排序使用了分治思想,分治的三个过程如下:

A 分解

数组A[p..r]被划分为两个(可能为空)子数组A[p..q-1]和A[q+1..r],使得A[p..q-1]中的每一个元素都小于等于A[q],而A[q]也小于等于A[q+1..r]中的每一个元素。其中计算下标q也是算法的一部分。

B 解决

通过递归调用快速排序,对子数组A[p..q-1],A[q+1..r]进行排序

C 合并

因为子数组都是原址排序的,不需要合并

下面是快速排序算法的实现(算法导论(95页快速排序))

QUICKSORT(A,  p, r)

    if p < r

        q = PARTTION(A, p, r)

        QUICKSORT(A,  p, q-1)

        QUICKSORT(A,  q+1, p)

计算下标

PARTTION(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


写了一个例子,追踪地址:

https://github.com/hk2413435641/codes/blob/master/algorithm/quick_sort.c

快速排序的平均时间复杂度为O(nlgn),最坏的情况下是O(n2),快速排序可能是实际中最好的选择,因为它还支持原址排序

2 堆排序

堆排序算法使用的是最大堆作为容器的。堆可以看成是一颗二叉树,这颗二叉树除了最底层外,其它层都是满的。所以如果一个节点索引为[i],则父节点索引为[i/2],左孩子节点为[2i],右孩子节点为[2i+1]。堆分为最大堆和最小堆。最大堆指的是父节点都要比自己的孩子节点大,最小堆相反,所有的父节点都要比自己的孩子节点小。其中,堆排序使用最大堆作为数据容器。优先队列使用的是最小堆。

堆排序的步骤:

1 维持最大堆结构

2 建堆

3 堆排序

维持最大堆结构的伪代码:

MAX-HEAPIFY (A, i)

    l = LEFT(i)

   R = RIGHT(i)

   if  l <= A.heap_size && A[l] > A[i]

        largest = l;

    else largest = i;

   if  r <= A.heap_size && A[r] > A[largest]

       largest = r;

   if  largest != i

        exchange A[i] with A[largest]

        MAX-HEAPIFY(A, largest)

建堆的伪代码:

BUILD-MAX-HEAP(A)

    A.heap_size = A.length

   for i = [A.length/2] downto 1

        MAX-HEAPIFY(A, i)

堆排序的伪代码:

HEAPSORT(A)

    BUILD-MAX-HEAP(A)

    for i = A.length downto 2

        exchange A[1] with A[i]

       A.heap_size = A.heap_size - 1

       MAX-HEAPIFY(A, 1)


实现代码:https://github.com/hk2413435641/codes/blob/master/algorithm/heap_sort.c

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容