代码改变世界

排序算法小结

2018-03-20 16:48  zxbob  阅读(186)  评论(0编辑  收藏  举报

        排序算法一直以来是我的心病,这次为了搞定这块内容,进行了一次系统的学习,结合大神的讲解以及个人的总结,梳理了以下的解决方案,顺便给出相关的迁移问题以及解决方案。

概况:

排序一般分为选择排序和插入排序这两大类,其余排序都是在这两块上的优化和深入。

这里不得不提到时间复杂度,虽然为O(n*2),可是在特定的场合下,插入排序还是比较快的,尤其是在近乎有序的情况下,一般在数据量比较小而接近的

情况下使用比较好。

插入排序衍生出冒泡排序和希尔排序

高级排序(O(nlogn)):

归并排序、快速排序、双路/三路快速排序、堆排序

下面给出相关的代码实例(python格式):

选择排序:

def selectSort(arr):
    """
        选择排序
    """
    for i in range(0,len(arr)):
        # 在[i,n)中选择最小的索引
        min_index = i
        for j in range(i+1,len(arr)):
            if arr[j] < arr[min_index]:
                min_index = j
        # 交换i与min_index的位置
        # swap(arr[i], arr[min_index]) python中不需要使用这个,内存空间中局部变量无效
        arr[i], arr[min_index] = arr[min_index], arr[i]

插入排序:

def insertSort(arr):
    """
        插入排序
    """
    for i in range(1, len(arr)):
        # 选择arr[i]的位置
        a = arr[i]
        j = i
        for j in range(1, i+1)[::-1]:
            # if arr[j-1] > arr[j]:
            #     arr[j-1], arr[j] = arr[j], arr[j-1]
            if arr[j-1] > a:
                arr[j] = arr[j-1]
            else:
                break
        arr[j] = a

 快速排序:

def _parition(arr, s, e):
    """
        找拆分位置
        arr[s...index -1]<arr[index] arr[index+1....e]> arr[index]
    """
    #初始第一个
    base = arr[s]
    j = s
    #使得 arr[i+1....j-1]< base and arr[j+1....e]>base
    for i in range(s+1, e+1):
        if arr[i] < base:
            arr[j+1], arr[i] = arr[i], arr[j+1]
            j += 1
    arr[s], arr[j] = arr[j], arr[s]
    return j



def _quickSort(arr, l, r, n):
    """
        进行快排
    """
    if r < l:
        return
    index = _parition(arr, l, r)
    if index == n:
        return index

    _quickSort(arr, l, index-1, n)
    _quickSort(arr, index+1, r, n)


def quickSort(arr, n):
    """
        快速排序
    """
    return _quickSort(arr, 0, len(arr)-1, n)

  归并排序:

def __merge_sort(arr, s, mid, e):
    """
        归并arr[s...mid] arr[mid+1....e]
    """
    #初始化归并空间
    merge_arr = [0] * (e-s+1)
    #赋值
    for i in range(s, e+1):
        merge_arr[i-s] = arr[i]

    i = s
    j = mid+1
    #归并
    for k in range(s, e+1):
        if i > mid:
            arr[k] = merge_arr[j-s]
            j += 1
        elif j > e:
            arr[k] = merge_arr[i-s]
            i += 1
        elif merge_arr[i-s] <merge_arr[j-s]:
            arr[k] = merge_arr[i-s]
            i += 1
        else:
            arr[k] = merge_arr[j-s]
            j += 1



def _mergeSort(arr, s, e):

    if s >= e:
        return
    #改进数据量小的时候,用插入排序
    if e-s <20:
        insertSort(arr)
        return
    #中间位置
    mid = s + (e-s)//2
    _mergeSort(arr, s, mid)
    _mergeSort(arr, mid+1, e)
    if arr[mid] < arr[mid+1]:
        __merge_sort(arr, s, mid, e)


def mergeSort(arr):
    """
        归并排序
    """
    _mergeSort(arr, 0, len(arr)-1)  

堆排序:

def MAX_Heapify(heap, HeapSize, root):
    left = 2*root + 1
    right = left + 1
    larger = root
    if left < HeapSize and heap[larger] < heap[left]:
        larger = left
    if right < HeapSize and heap[larger] < heap[right]:
        larger = right
    if larger != root:#如果做了堆调整则larger的值等于左节点或者右节点的,这个时候做对调值操作
        heap[larger],heap[root] = heap[root],heap[larger]
        MAX_Heapify(heap, HeapSize, larger)


def Build_MAX_Heap(heap):
    HeapSize = len(heap)#将堆的长度当独拿出来方便
    for i in range((HeapSize -2)//2,-1,-1):#从后往前出数
        MAX_Heapify(heap,HeapSize,i)


def heapSort(arr):
    Build_MAX_Heap(arr)
    for i in range(len(arr)-1,-1,-1):
        arr[0],arr[i] = arr[i],arr[0]
        MAX_Heapify(arr, i, 0)
    return arr

以下是随机生成测试数据和计算排序时长的方式:

def generArr(l, r, n):

    arr = [0] * n
    for i in range(0, n):
        arr[i] = random.randint(l,n)
    return arr


def countTime(arr, func = None):
    """
        计算时长
    """
    start = time.time()
    func(arr)
    end = time.time()
    print(func.__name__, '时长{}s'.format(round((end-start), 5)))

  计算结果如下:

def main():
    """
        主函数
    """
    arr = generArr(0, 100, 10000)
    arrs = generArr(0, 100, 10000)
    countTime(arr, mergeSort)
    countTime(arrs, insertSort)
if __name__ == '__main__':
    main()


D:\anacond\python.exe E:/cources_python/data_structure/algorithm/sort_demo.py
mergeSort 时长15.77121s
insertSort 时长7.39828s

Process finished with exit code 0