排序算法原理与实现[冒泡、选择、插入、快速、哈希、计数](python版)

1. 冒泡排序:

  • 原理

冒泡排序算法的基本原理就是比较相邻两个数字的大小。将两个数中比较大的那个数交换到靠后的位置,不断交换下去就可以将最大的那两个数放到队列的尾部。然后重头再次交换)(交换list.lenght-1次),直到将数列排成有序数列。

  • 代码实现
# -*- coding:utf-8 -*-
""" 
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""

import timeit

List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]

def bubbleSort(List):
    """
    冒泡排序
    :param List:
    :return:
    """
    if len(List) <= 1:
        return List
    for i in range(len(List)-1):  # 经过n-1轮排序
        for j in range(len(List)-1): # 比较前一个数和后一个数的大小关系
            if List[j] >= List[j+1]:
                List[j], List[j+1] = List[j+1], List[j] # 如果前一个数比后一个数大,则调换位置
    return List

if __name__ == '__main__':
    print(List)
    print(bubbleSort(List))
    runtime = timeit.timeit("bubbleSort(List)","from __main__ import bubbleSort, List",number=1000)
    print(runtime)

2. 选择排序:

  • 原理

简单来说,选择排序只做了一件事件,那就是从数列中选择最大(最小)的那个数,将这个数放到合适的位置。然后抛开这个数的子序列中找最大(最小)的那个数放到合适的位置。然后一直到子序列为空。

  • 代码实现
# -*- coding:utf-8 -*-

""" 
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""
from timeit import timeit

List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]

"""
# 这个虽简洁易懂,但有重复数字会有有Bug,原因为相同数下标无法确定
def selectSort(List):
    if len(List) <= 1:  # 如果长度小于等于1,直接返回
        return List
    for i in range(0, len(List)-1):  # 遍历数组
        if List[i] >= min(List[i+1:]): # 如果对应下标数的值大于剩余部分的最小值,交换位置
            minIndex = List.index(min(List[i+1:])) # 求剩余部分的最小值小标
            List[i], List[minIndex] = List[minIndex], List[i] #满足条件, 交换位置
    return List
"""

def selectSort(List):
    if len(List) <= 1:   # 如果长度小于等于1,直接返回
        return List
    for i in range(len(List)-1):
        min_index = i
        for j in range(i+1,len(List)):
            if List[j] < List[min_index]:
                min_index = j
        List[i], List[min_index] = List[min_index], List[i]
    return List

if __name__ == '__main__':
    print(List)
    print(selectSort(List))
    print(timeit('selectSort(List)','from __main__ import selectSort, List',number=1000))

3. 插入排序:

  • 原理

插入排序首先将数列分为两部分,数列的第一数为left,其余数位right部分。然后将right部分中的数逐一取出,插入到left部分的适当位置。当right部分为空时,left部分就成了一个有序的序列。

  • 代码实现
# -*- coding:utf-8 -*-
""" 
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""
from timeit import timeit

List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]

def insertSort(List):
    if len(List) <= 1:
        return List
    for right in range(1,len(List)):  # 遍历右边没有排序的数组
        target = List[right]     # 需要排序的值
        for left in range(0, right):
            if target <= List[left]:
                List[left+1:right+1] = List[left:right]  # 将左边已经排序好的数组整体右移一位
                List[left] = target # 将需排序的值到左边已排序好数组的适当位置
                break  # 提高性能,如果比边已排序好的最小数都小,一次则跳出循环
    return List
 
# 第二种思路,从左边排序的列表最后边向最左边比较 
def insertSort2(List):
    if len(List) <= 1:
        return List
    for i in range(1,len(List)):
        j = i
        while j > 0:
            if List[j] < List[j-1]:
                List[j], List[j-1] = List[j-1], List[j]
                j -= 1
            else:
                break
    return List

if __name__ == '__main__':
    print(List)
    print(insertSort(List))
    print(timeit('insertSort(List)','from __main__ import insertSort, List',number=1000))

4. 快速排序:

  • 原理

以列表中任意一个数为基准(一般选用列表的第一个数,因为递归调用的最后每个列表只有一个数),将列表分为左右两个子列表:左边子列表的数要比基准数小,右边子序列表的数要比基准数打。然后继续把左边子列表和右边子列表按照同样的方法继续分解、比较,一直到无法分解为止。然后按照左边子列表(比基准数小) + 基准数 + 右边子列表(比基准数大)的方式连接起来。最后合成了一个有序数列。

  • 代码实现
# -*- coding:utf-8 -*-
""" 
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""

from timeit import timeit

List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]

def quickSort(List):
    """
    快速排序:优点:代码简洁,易于理解 缺点: 太过耗费空间
    :param List:
    :return:
    """
    if len(List) <= 1:
        return List
    left = []     # 左区,用来存放比基准数小的数
    right = []    # 右区,用来存放比基准数大的数
    for i in List[1:]:   # 遍历除基准数以外的所有数
        if i <= List[0]:
            left.append(i)
        else:
            right.append(i)
    return quickSort(left) + [List[0]] + quickSort(right)  # 递归调用,无限拆分后合并各个有序数组

if __name__ == '__main__':
    print(List)
    print(quickSort(List))
    print(timeit('quickSort(List)','from __main__ import quickSort, List',number=1000))

5. 哈希排序

  • 原理

改进了得插入排序,将待排序的数组根据差量分成若干的的子数组,分别进行插入排序,通过不断地修改组距,使得分组数逐渐减少,当组距为1是,则就是一个插入排序

  • 代码实现
# -*- coding:utf-8 -*-
""" 
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""
from timeit import timeit

List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]

def shellSort(List):
    """
    希尔排序
    :param List:
    :return:
    """
    n = len(List)
    gap = n // 2
    # gap变化到0之前,插入算法执行的次数
    while gap > 0:
        # 插入算法,与普通的插入算法的区别就是gap步长
        for i in range(gap, n): # 外层循环控制的是所有子序列的所有元素(不包括每一组第一个数)
            j = i
            while j > 0:
                if List[j] < List[j - gap]: # 内层循环就是一个插入排序,比较与前一个数的大小关系
                    List[j], List[j - gap] = List[j - gap], List[j]
                    j -= gap
                else:
                    break
        # 缩短gap步长
        gap //= 2
    return List

if __name__ == '__main__':
    print(List)
    print(shellSort(List))
    print(timeit('shellSort(List)','from __main__ import shellSort, List',number=1000))

6. 计数排序

  • 原理

计数排序算法采用了一个巧妙的办法,首先需要创建一个与原数列等长的新数列,选择一个数为计基数,然后统计整个数列中有多少个数比基数小。如果有n个数比基数小,那么将基础放到数列的n+1位置上(不过此方法的空间和时间复杂度都比较大)

  • 代码实现
# -*- coding:utf-8 -*-
""" 
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""

from timeit import timeit

List = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]

def countingSort(List):
    """
    计数排序
    :param List:
    :return:
    """
    if len(List) <= 1:
        return List
    # 创建一个跟原数组长度相同的空数组
    rLen = len(List)
    rList = [None]*rLen
    for i in range(rLen): # 遍历数组,选择基数
        small = 0   # 记录比基数小的个数
        same = 0   # 记录跟基数相等的个数
        for j in range(rLen): # 找出比基数小或相等的数
            if List[j] < List[i]:
                small += 1
            elif List[j] == List[i]:
                same += 1
        for k in range(small,small+same):
            rList[k] = List[i]
    return rList

if __name__ == '__main__':
    print(List)
    print(countingSort(List))
    print(timeit('countingSort(List)','from __main__ import countingSort, List',number=1000))

如果有问题,欢迎在评论区交流喔,博主看到会第一时间回复。

发布了54 篇原创文章 · 获赞 24 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_43388615/article/details/105206562