Python实现插入排序、选择排序、冒泡排序、归并排序、堆排序等

leetcode 排序:
912. 排序数组

各种排序复杂度、稳定度对比:
在这里插入图片描述
排序算法总结:

  • 不基于比较的排序【计数排序、基数排序】,对样本数据有严格的要求,不易改写;
  • 基于比较的排序,只要规定好两个样本怎么比大小就可以直接复用;
  • 基于比较的排序,时间复杂度的极限是 O ( N ∗ l o g ( N ) O(N*log(N) O(Nlog(N)
  • 时间复杂度 O ( N ∗ l o g ( N ) O(N*log(N) O(Nlog(N)、空间复杂度低于 O ( N ) O(N) O(N)、且稳定的基于比较的排序是不存在的;
  • 为了绝对的速度选快排,为了省空间选堆排,为了稳定性选归并!
class DiversitySort(object):
    # def __init__(self, arr):
    #     pass
    # self.arr = arr
    def generateRandomArr(self, maxLen, maxValue):
        """
        返回一个数组arr,arr长度[0,maxLen-1],arr中的每个值[0,maxValue-1]
        :return:
        """
        len = int(random.random() * maxLen)
        arr = [0] * len
        for i in range(len):
            arr[i] = int(random.random() * maxValue)
        return arr

    def heapify(self, arr, n, i):
        largest = i
        l = 2 * i + 1
        r = 2 * i + 2
        if l < n and arr[i] < arr[l]:
            largest = l

        if r < n and arr[largest] < arr[r]:
            largest = r

        if largest != i:
            arr[i], arr[largest] = arr[largest], arr[i]
            self.heapify(arr, n, largest)

    def heapSort(self, arr):
        """
        堆排序
        时间复杂度:
        空间复杂度:
        :param arr:
        :return:
        """
        n = len(arr)

        # Build a MaxHeap
        for i in range(n, -1, -1):
            self.heapify(arr, n, i)
        print(arr)
        # 一个个交换元素
        for i in range(n - 1, 0, -1):
            # Swap item
            arr[i], arr[0] = arr[0], arr[i]
            self.heapify(arr, i, 0)

    def selectSort(self, arr):
        """
        选择最小的 往前排
        :param arr:
        :return:
        """
        if not arr or len(arr) < 2:
            return arr

        for i in range(len(arr) - 1):
            minIndex = i
            for j in range(i, len(arr)):
                if arr[j] < arr[minIndex]:
                    minIndex = j

            arr[minIndex], arr[i] = arr[i], arr[minIndex]

        return arr

    def bubbleSort(self, arr):
        """
        两两比较,往后放
        :param arr:
        :return:
        """
        if not arr or len(arr) < 2:
            return arr
        for i in range(len(arr) - 1, -1, -1):
            for j in range(0, i):
                if arr[j] > arr[j + 1]:
                    arr[j], arr[j + 1] = arr[j + 1], arr[j]
        return arr

    def insertSort(self, arr):
        """
        类似于玩扑克,抓到一张新牌,然后插入到序列中
        """
        if not arr or len(arr) < 2:
            return arr
        for i in range(1, len(arr)):
            newNumIndex = i
            while newNumIndex - 1 >= 0 and arr[newNumIndex - 1] > arr[newNumIndex]:
                arr[newNumIndex], arr[newNumIndex - 1] = arr[newNumIndex - 1], arr[newNumIndex]
                newNumIndex -= 1

        return arr

    def merge(self, arr, L, M, R):
            """
            对两个有序数组归并
            :param arr:
            :param L:
            :param M:
            :param R:
            :return:
            """
            # 辅助数组
            help = [None] * (R-L+1)
            i = 0
            # 左右两个数组的起始指针位置
            p1, p2 = L, M+1
            while p1 <= M and p2 <= R:
                if arr[p1] <= arr[p2]:
                    help[i] = arr[p1]
                    p1 += 1
                else:
                    help[i] = arr[p2]
                    p2 += 1
                i += 1

            # p2 越界了
            while p1 <= M:
                help[i] = arr[p1]
                i += 1
                p1 += 1

            # p1 越界了
            while p2 <= R:
                help[i] = arr[p2]
                i += 1
                p2 += 1

            # 将help数组拷贝回主数组中
            for i in range(len(help)):
                arr[L+i] = help[i]

    def mergeSort(self, arr):
        """
        归并排序,递归方法实现
        :param arr:
        :return:
        """

        def process(arr, L, R):
            if L == R:
                return
            mid = L + int((R - L) >> 1)
            process(arr, L, mid)
            process(arr, mid+1, R)
            self.merge(arr, L, mid, R)

        if not arr or len(arr) < 2:
            return

        process(arr, 0, len(arr) - 1)

    def mergeSort2(self, arr):
        """
        归并排序,非递归方法实现
        :param arr:
        :return:
        """
        if not arr or len(arr) < 2:
            return
        step = 1
        N = len(arr)
        while step < N:
            L = 0
            while L < N:
                # M = 0
                if N - L >= step:
                    M = L + step - 1
                else:
                    M = N - 1

                if M == N - 1:
                    break
                # R = 0
                if N - 1 - M >= step:
                    R = M + step
                else:
                    R = N - 1
                self.merge(arr, L, M, R)
                if R == N - 1:
                    break
                else:
                    L = R + 1

            if step > N/2:
                break

            step *= 2
            
    def netherlandsFlag(self, arr, L, R):
        """
        arr[L...R]范围上,拿arr[R]做划分值,<arr[R] =arr[R] >arr[R]
        :param arr:
        :param L:
        :param R:
        :return: 返回等于arr[R]区域的左侧和右侧位置
        """
        if L > R:
            return [-1, -1]
        if L == R:
            return [L, R]

        lessR = L - 1
        moreL = R
        index = L
        while index < moreL:
            if arr[index] < arr[R]:
                arr[index], arr[lessR+1] = arr[lessR+1], arr[index]
                index += 1
                lessR += 1
            elif arr[index] > arr[R]:
                arr[index], arr[moreL - 1] = arr[moreL - 1], arr[index]
                moreL -= 1
            else:
                index += 1

        # 此时再讲最后一个元素arr[R]和大于arr[R]区域的左侧第一个元素 交换
        arr[R], arr[moreL] = arr[moreL], arr[R]
        return [lessR+1, moreL]

    def process(self, arr, L, R):
        if L >= R:
            return
        equal_L, equal_R = self.netherlandsFlag(arr, L, R)
        self.process(arr, L, equal_L-1)
        self.process(arr, equal_R+1, R)

    def quickSort1(self, arr):
        """
        快速排序,思路类似于荷兰国旗问题
        :param arr:
        :return:
        """
        if not arr or len(arr) < 2:
            return
        self.process(arr, 0, len(arr)-1)

    def quickSort2(self, arr):
        """
        快速排序
        改进二,每步判断是否还有大于小于区域
        :param arr:
        :return:
        """
        if not arr or len(arr) < 2:
            return

        stack = list()
        stack.append([0, len(arr)-1])
        while stack:
            cur = stack.pop(0)
            equal_L, equal_R = self.netherlandsFlag(arr, cur[0], cur[1])
            # 有小于区域
            if equal_L > cur[0]:
                stack.append([cur[0], equal_L - 1])
            # 有大于区域
            if equal_R < cur[1]:
                stack.append([equal_R + 1, cur[1]])

    def process3(self, arr, L, R):
        if L >= R:
            return

        # 引入随机数
        randVal = int(random.random() * (R - L + 1))
        arr[randVal], arr[R] = arr[R], arr[randVal]
        equal_L, equal_R = self.netherlandsFlag(arr, L, R)
        self.process(arr, L, equal_L-1)
        self.process(arr, equal_R+1, R)

    def quickSort3(self, arr):
        """
        快速排序
        改进三,引入随机数
        :param arr:
        :return:
        """

        if not arr or len(arr) < 2:
            return
        self.process3(arr, 0, len(arr)-1)

    def CountSort(self, arr):
        """
        计数排序
        only for 0~200 value
        创建最大值+1个桶
        :param arr:
        :return:
        """
        if not arr or len(arr) < 2:
            return
        maxValue = float("-inf")
        for item in arr:
            if item > maxValue:
                maxValue = item

        bucket = [0] * (maxValue + 1)
        for item in arr:
            bucket[item] += 1

        i = 0
        for j in range(len(bucket)):
            while bucket[j] > 0:
                bucket[j] -= 1
                arr[i] = j
                i += 1

    def RadixSort(self, arr):
        """
        基数排序
        :param arr:
        :return:
        """
        if not arr or len(arr) < 2:
            return
        self.rsort(arr, 0, len(arr)-1, self.maxBits(arr))

    def rsort(self, arr, L, R, digit):
        radix = 10
        help = [None] * (R - L + 1)
        for d in range(1, digit+1):
            count = [0] * radix
            for i in range(L, R+1):
                j = self.getDigit(arr[i], d)
                count[j] += 1
            # 累加和
            for i in range(1, radix):
                count[i] = count[i] + count[i-1]

            for i in range(R, L-1, -1):
                j = self.getDigit(arr[i], d)
                help[count[j] - 1] = arr[i]
                count[j] -= 1

            j = 0
            for i in range(L, R+1):
                arr[i] = help[j]
                j += 1

    def maxBits(self, arr):
        """
        返回最大值的位数
        :param arr:
        :return:
        """
        maxValue = float("-inf")
        for item in arr:
            if item > maxValue:
                maxValue = item
        res = 0
        while maxValue != 0:
            maxValue = maxValue // 10
            res += 1
        return res

    def getDigit(self, x, d):
        """
        返回x这个数的第d位的数据
        :param x:
        :param d:
        :return:
        """
        return int((x // math.pow(10, d-1)) % 10)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NLP_wendi

谢谢您的支持。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值