Python 排序算法

名称时间复杂度是否原地排序稳定性
冒泡排序O(n^2)
插入排序O(n^2)
选择排序O(n^2)
归并排序O(nlogn)
快速排序O(nlogn)
计数排序O(n+k) k是数据范围
基数排序O(dn) d是维度
冒泡排序

重复地走访过要排序的元素列,依次比较两个相邻的元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。

def bubbleSort(array):

    a = len(array)
    # 如果该数组只有小于或等于一个元素,则直接返回原数组
    if a <= 1:
        return

    for i in range(a - 1):
        flag = False  # 设置一个标志,作用是防止重复排序
        for j in range(a - i - 1):
            if array[j] > array[j + 1]:  # 比较前一个元素与后一个元素的大小
                array[j], array[j + 1] = array[j + 1], array[j]  # 交换这两个元素
                flag = True
        if not flag:
            break

    return array
插入排序

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

将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。

从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)

    def insertionsort(self, list):
        if len(list) <= 1:
            return list
        for i in range(1, len(list)):
            a = list[i]
            j = i - 1
            for j in range(i-1, -2, -1):
                if list[j] > a:
                    list[j+1] = list[j]
                else:
                    break
            list[j+1] = a
        return list
选择排序

首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。

再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。

重复第二步,直到所有元素均排序完毕。

    def selectionsort(self, list):
        if len(list) <= 1:
            return list
        for i in range(len(list)-1):
            min = i
            for j in range(i+1, len(list)):
                if list[j] < list[min]:
                    min = j
            if i != min:
                list[i], list[min] = list[min], list[i]
        return list
归并排序

申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;

设定两个指针,最初位置分别为两个已经排序序列的起始位置;

比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;

重复步骤 3 直到某一指针达到序列尾;

将另一序列剩下的所有元素直接复制到合并序列尾。

    def mergesort(self, list):
        if len(list) <= 1:
            return list
        mid = len(list) // 2
        left, right = list[0:mid], list[mid:]
        return self.merge(self.mergesort(left), self.mergesort(right))

    def merge(self, left, right):
        result = []
        while left and right:
            if left[0] <= right[0]:
                result.append(left.pop(0))
            else:
                result.append(right.pop(0))
        while left:
            result.append(left.pop(0))
        while right:
            result.append(right.pop(0))
        return result
快速排序

从数列中挑出一个元素,称为 “基准”(pivot);

重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;

递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

    def partion(self, a, left, right):
        p = a[right]
        i = left
        for j in range(left, right):
            if a[j] < p:
                a[i], a[j] = a[j], a[i]
                i += 1
        a[right], a[i] = a[i], a[right]
        return i

    def quickSort(self, a, left, right):
        if left >= right:
            return
        q = self.partion(a, left, right)
        self.quickSort(a, left, q-1)
        self.quickSort(a, q+1, right)
        return a
计数排序

找出待排序的数组中最大和最小的元素

统计数组中每个值为i的元素出现的次数,存入数组C的第i项

对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加)

反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1

    def countingSort(self, n, m):
        a = [0 for i in range(m)]
        for i in n:
            a[i] += 1

        b = [0 for i in range(m)]
        for i in range(len(a)):
            b[i] = sum(a[:i+1])

        c = [0 for i in range(len(n))]
        for i in n:
            c[b[i] - 1] = i
            b[i] -= 1
        return c
基数排序

将整数按位数切割成不同的数字,然后按每个位数分别比较。

将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。

    def radixSort(self, list, d):
        for k in range(d):
            s = [[] for i in range(10)]
            for i in list:
                s[int(i / (10 ** k) % 10)].append(i)
            list = [j for i in s for j in i]
        return list
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值