常见算法排序

常见算法排序_第1张图片
常见排序归类

直接插入排序

时间复杂度:O(n²)
空间复杂度:O(1)
稳定性:稳定
算法思想:假设待排序的数据是数组A[1….n]。初始时,A[1]自成1个有序区,无序区为A[2….n]。在排序的过程中,依次将A[i] (i=2,3,….,n)从后往前插入到前面已排好序的子数组A[1,…,i-1]中的适当位置,当所有的A[i] 插入完毕,数组A中就包含了已排好序的输出序列。

def insert_sort(array):  # 定义直接插入排序的函数,将需要排序的数组作为形参
    for i in range(len(array)):  # 从头依次循环,并取循环坐标作为下一循环的节点
        for j in range(i):  # 从头开始,循环到第一循环循环到的数为止
            if array[i] > array[j]:  # 判断第一循环坐标的值是否大于第二循环坐标的值
                array.insert(j, array.pop(i))  # 判断结果为真则将值小的数置前
    return array  # 返回排好序之后的数组

希尔排序
时间复杂度:O(n)
空间复杂度:O(n√n)
稳定性:不稳定
算法思想:希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。

def shell_sort(array):
    gap = len(array)  # 设置增量
    while gap > 1:
        gap = gap // 2  # 选择增量,当所有的数被分为一组的时候即退出循环
        for i in range(gap, len(array)):  # 分组
            for j in range(i % gap, i, gap):  # 设置增量为步进,实现比较每组数大小的效果
                if array[i] < array[j]:  # 判断后将数值小的数组元素置前
                    array[i], array[j] = array[j], array[i]
    return array

简单选择排序
时间复杂度:O(n²)
空间复杂度:O(1)
稳定性:不稳定
算法思想:每一趟从待排序的数据元素中选择最小(或最大)的一个元素作为首元素,直到所有元素排完为止,简单选择排序是不稳定排序。

def select_sort(array):
    for i in range(len(array)):  # 每取一个值,可以看做是一趟
        x = i  # min index
        for j in range(i, len(array)):  # 遍历数组,与取出的元素进行比较
            if array[j] < array[x]:  # 取当前趟次最小元素,置于已经遍历过的数据之前
                x = j
        array[i], array[x] = array[x], array[i]
    return array

堆排序
时间复杂度:O(nlog₂n)
空间复杂度:O(1)
稳定性:不稳定
算法思想:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。

def heap_sort(array):
    def heap_adjust(parent):  # 构造初始堆并比较近似完全二叉树中节点的值
        child = 2 * parent + 1  # 左孩子节点
        while child < len(heap):
            if child + 1 < len(heap):
                if heap[child + 1] > heap[child]:
                    child += 1  # 右孩子节点
            if heap[parent] >= heap[child]:  # 父节点大于右孩子节点便结束循环
                break
            heap[parent], heap[child] = heap[child], heap[parent]  # 交换左孩子节点与父节点的值,使大数后沉

            parent, child = child, 2 * child + 1

    heap, array = array.copy(), []
    for i in range(len(heap) // 2, -1, -1):
        heap_adjust(i)
    while len(heap) != 0:  # 使所有的数都经过比较
        heap[0], heap[-1] = heap[-1], heap[0]
        array.insert(0, heap.pop())
        heap_adjust(0)
    return array

https://blog.csdn.net/MoreWindows/article/details/6709644
http://www.cnblogs.com/dolphin0520/archive/2011/10/06/2199741.html
https://www.cnblogs.com/chengxiao/p/6129630.html


http://images.cnblogs.com/cnblogs_com/kkun/201111/201111301912294099.gif
冒泡排序
时间复杂度:O(n²)
空间复杂度:O(1)
稳定性:稳定
算法思想:对相邻的元素进行两两比较,顺序相反则进行交换,这样,每一趟会将最小或最大的元素“浮”到顶端,最终达到完全有序。

def bubble_sort(array):
    for i in range(len(array)):
        for j in range(i, len(array)):
            if array[i] > array[j]:  # 若前面的数大于后面的数,则交换位置
                array[i], array[j] = array[j], array[i]
    return array

快速排序
时间复杂度:O(nlog₂n)
空间复杂度:O(nlog₂n)
稳定性:不稳定
算法思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

def quick_sort(array):
    def recursive(begin, end):
        if begin > end:
            return
        l, r = begin, end
        pivot = array[l]  # 定义标准,也就是本次执行结束之后找到自己位置的那个数
        while l < r:  # 利用while循环从开始到结尾依次与标准比较
            while l < r and array[r] > pivot:  # 比标准大的数,放到右边
                r -= 1
            while l < r and array[l] <= pivot:  # 比标准小的数,放到左边
                l += 1
            array[l], array[r] = array[r], array[l]  # 若不满足上述条件,左右调换
        array[l], array[begin] = pivot, array[l]  # 标准找到自己位置
        recursive(begin, l - 1)  # 左边调用,即:对比已经找到位置的数小的数进行排序
        recursive(r + 1, end)  # 右边调用,即:对比已经找到位置的数大的数进行排序

    recursive(0, len(array) - 1)  # 调用一次方法,一个数找到正确位置,下次参与排序的数-1
    return array

http://www.cnblogs.com/foreverking/articles/2234225.html


归并排序
时间复杂度:O(nlog₂n)
空间复杂度:O(1)
稳定性:稳定
算法思想:是创建在归并操作上的一种有效的排序算法,效率为O(n log n)。1945年由约翰·冯·诺伊曼首次提出。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同时进行。(先分后治再合并)

def merge_sort(array):
    def merge_arr(arr_l, arr_r):  # 先治后合
        array = []
        while len(arr_l) and len(arr_r):  # 治
            if arr_l[0] <= arr_r[0]:  # 右边的组数大,就添加左边的数到下一组
                array.append(arr_l.pop(0))  # 判断一个,取出一个,直到全部取完
            elif arr_l[0] > arr_r[0]:  # 左边的组数大,就添加右边的数到下一组
                array.append(arr_r.pop(0))
        if len(arr_l) != 0:  # 合
            array += arr_l  # 合左边
        elif len(arr_r) != 0:
            array += arr_r  # 合右边
        return array

    def recursive(array):  # 分
        if len(array) == 1:  # 分到最小单位
            return array
        mid = len(array) // 2  # 对二取整,切片划分数组
        arr_l = recursive(array[:mid])
        arr_r = recursive(array[mid:])
        return merge_arr(arr_l, arr_r)  # 一分为二

    return recursive(array)

https://www.cnblogs.com/chengxiao/p/6194356.html


基数排序
时间复杂度:O(d(r+n))
空间复杂度:O(rd+n)
稳定性:稳定
算法思想:将整数按位数切割成不同的数字,然后按每个位数分别比较。

def radix_sort(array):
    bucket, digit = [[]], 0  # 初始化桶数组和数位控制
    while len(bucket[0]) != len(array):  # 判断是否将所有位数取出
        bucket = [[], [], [], [], [], [], [], [], [], []]  # 设置桶数组
        for i in range(len(array)):
            num = (array[i] // 10 ** digit) % 10  # 取当前位数
            bucket[num].append(array[i])  # 放入相应的桶中
        array.clear()  # 清楚当前数据
        for i in range(len(bucket)):
            array += bucket[i]  # 将排好序的桶数组添加进数组
        digit += 1  # 数位控制
    return array

https://www.cnblogs.com/skywang12345/p/3603669.html


常见算法排序_第2张图片
算法执行时间
常见算法排序_第3张图片
算法速度比较

你可能感兴趣的:(常见算法排序)