十大经典排序算法python实现


性能比较

排序算法 时间复杂度(平均) 时间复杂度(最差) 时间复杂度(最好) 空间复杂度 稳定性
快速排序 O($nlog_{2}{n}$) O($n^{2}$) O($nlog_{2}{n}$) O($nlog_{2}{n}$) 不稳定
冒泡排序 O($n^{2}$) O($n^{2}$) O($n$) O(1) 稳定
选择排序 O($n^{2}$) O($n^{2}$) O($n^{2}$) O(1) 不稳定
归并排序 O($nlog_{2}{n}$) O($nlog_{2}{n}$) O($nlog_{2}{n}$) O($n$) 稳定
插入排序 O($n^{2}$) O($n^{2}$) O($n$) O(1) 稳定
希尔排序 O($n^{1.3}$) O($n^{2}$) O($n$) O(1) 不稳定
堆排序 O($nlog_{2}{n}$) O($nlog_{2}{n}$) O($nlog_{2}{n}$) O(1) 不稳定
桶排序 O($n + k$) O($n^{2}$) O($n$) O($n + k$) 稳定
计数排序 O($n + k$) O($n + k$) O($n + k$) O($n + k$) 稳定
基数排序 O($n * k$) O($n * k$) O($n * k$) O($n + k$) 稳定

快速排序

原理:对于任意一个需要排序的序列,首先选择序列中的人一个数为关键数据,然后将所有比它小的数都放左边,所有比它大的数都放右边,这就完成了一次快速排序,如此递归完成所有排序。

def quick_sort(data):
    """
    快速排序
    """
    if len(data) <= 1:
        return data
    else:
        base = data[0]
        left, right = [], []
        data.remove(base)
        for num in data:
            if num >= base:
                right.append(num)
            else:
                left.append(num)
        return quick_sort(left) + [base] + quick_sort(right)

冒泡排序

原理:遍历需要排序的序列元素,依次比较两个相邻的元素,如果他们的顺序错误就进行交换。重复遍历直到没有相邻元素需要交换,即该序列已经排序完成。

def bubble_sort(data):
    """
    冒泡排序
    """
    if len(data) <= 1:
        return data
    for i in range(len(data) - 1):
        for j in range(len(data) - i - 1):
            if data[j] > data[j + 1]:
                data[j], data[j + 1] = data[j + 1], data[j]
    return data

选择排序

原理:一共需要遍历n-1次,没遍历一次选择出最小的元素,完成排序。

def select_sort(data):
    """
    选择排序
    """
    if len(data) <= 1:
        return data
    for i in range(len(data) - 1):
        min_index = i
        for j in range(i + 1, len(data)):
            if data[j] < data[min_index]:
                min_index = j
        data[i], data[min_index] = data[min_index], data[i]
    return data

归并排序

原理:先使每个子序列有序,再使子序列段间有序。

def merge_sort(data):
    """
    归并排序
    """
    def merge(left, right):
        """
        归并过程
        """
        result = []  # 保存归并后的结果
        i = j = 0
        while i < len(left) and j < len(right):
            if left[i] <= right[j]:
                result.append(left[i])
                i += 1
            else:
                result.append(right[j])
                j += 1
        result = result + left[i:] + right[j:]
        return result

    # 递归过程
    if len(data) <= 1:
        return data
    mid = len(data) // 2
    left = merge_sort(data[:mid])
    right = merge_sort(data[mid:])
    return merge(left, right)

插入排序

原理:通过构建有序序列,对未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入

def insert_sort(data):
    """
    插入排序
    """
    if len(data) <= 1:
        return data
    for i in range(1, len(data)):
        for j in range(i, 0, -1):
            if data[j] < data[j - 1]: 
                data[j], data[j - 1] = data[j - 1], data[j]
            else:
                break
    return data

希尔排序

原理:整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,它与插入排序的不同之处在于,它会优先比较距离较远的元素。

def shell_sort(data):
    """
    希尔排序
    """
    if len(data) <= 1:
        return data
    gap = 1  
    while gap < len(data) // 3:
        gap = gap * 3 + 1
    while gap >= 1:
        for i in range(gap, len(data)):
            j = i
            while j >= gap and data[j] < data[j - gap]:
                data[j], data[j - gap] = data[j - gap], data[j]
                j -= gap
        gap //= 3
    return data

堆排序

原理:在堆的数据结构中,堆中的最大值总是位于根节点,把序列放入堆数据中一直维持最大堆积性质。

def heap_sort(data):
    """
    堆排序
    """
    def sift_down(start, end):
        """
        最大堆调整
        """
        root = start
        while True:
            child = 2 * root + 1
            if child > end:
                break
            if child + 1 <= end and data[child] < data[child + 1]:
                child += 1
            if data[root] < data[child]:
                data[root], data[child] = data[child], data[root]
                root = child
            else:
                break

    # 创建最大堆
    for start in range((len(data) - 2) // 2, -1, -1):
        sift_down(start, len(data) - 1)

    # 堆排序
    for end in range(len(data) - 1, 0, -1):
        data[0], data[end] = data[end], data[0]
        sift_down(0, end - 1)
    return data

桶排序

原理:桶排序是计数排序的升级版,它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。

def bucket_sort(data, bucket_size = 5):
    """
    桶排序
    默认5个桶
    """
    max_num, min_num = max(data), min(data)
    bucket_count = (max_num - min_num) // bucket_size + 1
    buckets = []
    for i in range(bucket_count):
        buckets.append([])
    for num in data:
        buckets[(num - min_num) // bucket_size].append(num)
    data.clear()
    for bucket in buckets:
        insert_sort(bucket)
        data.extend(bucket)
    return data

计数排序

原理:先开辟一个覆盖序列范围的数组空间,将输入的数据值转化为键存储在额外开辟的数组空间中,再依次取出。

def count_sort(data):
    """
    计数排序
    需要是整数序列
    """
    if len(data) <= 1:
        return data
    bucket = [0] * (max(data) + 1)
    for num in data:
        bucket[num] += 1
    i = 0
    for j in range(len(bucket)):
        while bucket[j] > 0:
            data[i] = j
            bucket[j] -= 1
            i += 1
    return data

基数排序

原理:将序列所有数字统一为相同数字长度,数字较短的数前面补零。从最低位开始,依次进行一次排序,然后从低位到高位依次完成排序。

def radix_sort(data):
    """
    基数排序
    """
    if len(data) <= 1:
        return data
    radix = 10
    div = 1
    max_bit = len(str(max(data)))
    bucket = [[] for i in range(radix)]
    while max_bit:
        for num in data:
            bucket[num // div % radix].append(num)
        j = 0
        for b in bucket:
            while b:
                data[j] = b.pop(0)
                j += 1
        div *= 10
        max_bit -= 1
    return data

测试结果

data = [2,3,5,7,1,4,6,15,5,2,7,9,10,15,9,17,12]
print("input data &#123;&#125;".format(data))
quick_ret = quick_sort(data)  # 快速排序
print("quick_ret &#123;&#125;".format(quick_ret))
bubble_ret = bubble_sort(data)  # 冒泡排序
print("bubble_ret &#123;&#125;".format(bubble_ret))
select_ret = select_sort(data)  # 选择排序
print("select_ret &#123;&#125;".format(select_ret))
merge_ret = merge_sort(data)  # 归并排序
print("merge_ret &#123;&#125;".format(merge_ret))
insert_ret = insert_sort(data)  # 插入排序
print("insert_ret &#123;&#125;".format(insert_ret))
shell_ret = shell_sort(data)  # 希尔排序
print("shell_ret &#123;&#125;".format(shell_ret))
heap_ret = heap_sort(data)  # 堆排序
print("heap_ret &#123;&#125;".format(heap_ret))
bucket_ret = bucket_sort(data)  # 桶排序
print("bucket_ret &#123;&#125;".format(bucket_ret))
count_ret = count_sort(data)  # 计数排序
print("count_ret &#123;&#125;".format(count_ret))
radix_ret = radix_sort(data)  # 基数排序
print("radix_ret &#123;&#125;".format(radix_ret))

input data [2, 3, 5, 7, 1, 4, 6, 15, 5, 2, 7, 9, 10, 15, 9, 17, 12]
quick_ret [1, 2, 2, 3, 4, 5, 5, 6, 7, 7, 9, 9, 10, 12, 15, 15, 17]
bubble_ret [1, 2, 3, 4, 5, 5, 6, 7, 7, 9, 9, 10, 12, 15, 15, 17]
select_ret [1, 2, 3, 4, 5, 5, 6, 7, 7, 9, 9, 10, 12, 15, 15, 17]
merge_ret [1, 2, 3, 4, 5, 5, 6, 7, 7, 9, 9, 10, 12, 15, 15, 17]
insert_ret [1, 2, 3, 4, 5, 5, 6, 7, 7, 9, 9, 10, 12, 15, 15, 17]
shell_ret [1, 2, 3, 4, 5, 5, 6, 7, 7, 9, 9, 10, 12, 15, 15, 17]
heap_ret [1, 2, 3, 4, 5, 5, 6, 7, 7, 9, 9, 10, 12, 15, 15, 17]
bucket_ret [1, 2, 3, 4, 5, 5, 6, 7, 7, 9, 9, 10, 12, 15, 15, 17]
count_ret [1, 2, 3, 4, 5, 5, 6, 7, 7, 9, 9, 10, 12, 15, 15, 17]
radix_ret [1, 2, 3, 4, 5, 5, 6, 7, 7, 9, 9, 10, 12, 15, 15, 17]

完~


文章作者: Boole
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Boole !
评论
 上一篇
python面试题50道 python面试题50道
python面试题,总结了50道,当然面试题远远不止这些,刷题解决不了根本问题,还是多些实战好。
下一篇 
图片风格迁移 图片风格迁移
两张图像经过预训练好的分类网络,若提取出的高维特征之间的(欧氏)距离越小,则这两张图像内容越相似;若提取出的低维特征在数值上基本相等,则这两张图像越相似。
2020-10-31
  目录