Python实现排序算法

排序算法常用术语

稳定与不稳定

稳定: 如果a原本在b前面,而a=b,排序之后a仍然在b的前面;
不稳定: 如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面;

内排序与外排序

内排序: 所有排序操作都在内存中完成;
外排序: 由于数据太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行;

排序算法的性能三大影响因素

1 . 时间性能(时间复杂度): 一个算法执行所耗费的时间。
2. 辅助空间 (空间复杂度): 运行完一个程序所需内存的大小。
3. 算法的复杂性 : 算法本身的复杂度,而不是指算法的时间复杂度

常见排序算法性能比较

在这里插入图片描述

排序算法

在这里插入图片描述

交换排序:冒泡排序

冒泡排序 (Bubble Sort)一种交换排序,它的基本思想是:两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。这个算法的名字由来是因为越大的元素会经由交换慢慢“”到数列的顶端

冒泡排序算法的运作如下:

  1. 比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个。
    2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
    3. 针对所有的元素重复以上的步骤,除了最后一个。
    4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

在这里插入图片描述
冒泡排序复杂度分析

最好的情况, 也就是要排序的表本身就是有序的,那么我们比较次数,可以推断出就是n‐1 次的比较,没有数据交换,时间复杂度为O(n)。

最坏的情况,即待排序表是逆序的情况,此时需要比较1+2+3+4+…+(n-1)=n(n-1)/2次,即时间复杂度为O(n**2)。

稳定性: 稳定

def BubbleSort(nums):
    """实现冒泡排序"""
    length = len(nums)
    for i in range(length - 1):
        for index in range( length - i - 1):
            if nums[index] > nums[index + 1]:
                nums[index], nums[index + 1] = nums[index + 1], nums[index]
    return nums

if __name__ == '__main__':
    nums = [3,4,5,6,1,24,9]
    print(BubbleSort(nums))

交换排序:快速排序

快速排序(Quick Sort)的基本思想是:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的。

在这里插入图片描述
层数为O(logn)(即调用栈的高度为O(logn)),而每层需要的时间为O(n)。因此整个算法需要的时间为O(n) * O(logn) = O(nlogn)

"""
基本思想:通过一趟排序将待排序记录分隔成两部分,其中一部分记录的关键字大于另一部分记录的关键字,
则可对这两部分记录继续进行排序,以答到整个序列有序的目的
"""

def quickSort(array):
    if len(array) < 2:
        return array
    else:
        # key = array[0]
        # bigarray = []
        # smallarray = []
        # for i in array[1:]:
        #     if i > key:
        #         bigarray.append(i)
        #     if i < key:
        #         smallarray.append(i)
        # return quickSort(smallarray) + [key] + quickSort(bigarray)
        pivot = array[0]
        less = [i for i in array[1:] if i < pivot]
        greater = [i for i in array[1:] if i > pivot]
        return quickSort(less) + [pivot] + quickSort(greater)

if __name__ == '__main__':
    print(quickSort([10, 5, 2, 3, 11, 55, 1]))

插入排序: 直接插入排序

直接插入排序(Straight Insertion Sort)的基本操作是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增 1 的有序表。

在这里插入图片描述
原理: 每次将排序中的元素,插入到前面已经排好序的有序序列中去,直到排序完成。

def insert_num(nums):
    """直接插入排序"""
    # 待排序的序列长度
    count = len(nums)
    # 将第一个索引认为是有序的数值序列,依次遍历除了第一个元素之外的其他元素,插入到前面的有序序列
    for i in range(1, count):
        # 要插入的数值元素
        key = nums[i]
        # 插入元素的前一个元素的索引
        j = i - 1
        # 进行大小比较的时候是从有序序列的最后一个元素(j = i - 1)开始进行比较,依次往回进行比较
        # 如果插入的元素小于有序序列里的元素,则进行位置调换,直到比较到有序序列的第一个元素时结束
        while j >= 0:
            if nums[j] > key:
                nums[j + 1] = nums[j]
                nums[j] = key
            j -= 1

    return nums


if __name__ == '__main__':
    nums = [5, 3, 6, 9, 10, 8, 4]
    sort_nums = insert_num(nums)
    print(sort_nums)

最好的情况, 也就是要排序的表本身就是有序的, 因此没有移动的记录,时间复杂度为 O(n)。
最坏的情况, 即待排序表是逆序的情况,时间复杂度为 O(n**2)。

插入排序:希尔排序

基本思想:
算法先将要排序的一组数按某个增量d(n/2,n为要排序数的个数)分成若干组,每组中记录的然后
再用一个较小的增量(d/2)对它进行分组,在每组中再进行直接插入排序。当增量减到1时,进行
直接插入排序后,排序完成。

在这里插入图片描述

def insert_num(nums):
    for i in range(1, len(nums)):
        # j为有序列表的最后一个元素下标
        j = i - 1
        key = nums[i]
        while j >= 0:
            if nums[j] > key:
                nums[j + 1] = nums[j]
                nums[j] = key
            j -= 1

        return nums


def shellSort(arr):
    """希尔排序"""
    step = int(len(arr) / 2)
    while step > 0:
        # print('step:', step)
        arr_len = len(arr)
        for index in range(arr_len):
            if index + step < arr_len:
                if arr[index] > arr[index + step]:
                    arr[index], arr[index + step] = arr[index + step], arr[index]
        step = int(step / 2)

    return insert_num(arr)


if __name__ == '__main__':
    arr = [49, 38, 65, 97, 76, 13, 27, 49, 55, 4]
    arr = shellSort(arr)
    print(arr)

选择排序

选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

def findSmallest(arr):
    """寻找最小元素, 返回的时最小元素的索引,方便后续最小元素的寻找"""
    smallest = arr[0]
    smallest_index = 0
    for i in range(1, len(arr)):
        if arr[i] < smallest:
            smallest = arr[i]
            smallest_index = i
    return smallest_index

def Selection_Sort(arr):
    """选择排序"""
    """
    首先在未排序的序列中找出最小(大)元素,存放在排序序列的起始位置,然后,
    再从剩余未排序的元素中继续寻找最小(大)元素,然后放在已经排序的序列的末尾,
    依次类推,直到所有的元素均排序完毕
    """
    newArr = []
    for i in range(len(arr)):
        # 返回最小元素的索引
        smallest = findSmallest(arr)
        # 取出arr中的最小元素,添加到newArr中,并将其从arr中删除
        newArr.append(arr.pop(smallest))

    return newArr

if __name__ == '__main__':
    arr = [8, 4, 5, 12, 88, 10]
    print(Selection_Sort(arr))

时间复杂度:

最优时间复杂度:O(n2 )
最坏时间复杂度:O(n2 )
稳定性:不稳定(考虑升序每次选择最大的情况)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值