• Python十大排序算法


    代码如下: 快排
     

    '''
    几乎是我们学习排序入门算法了,两次遍历,时间复杂度较高n*n,稳定排序
    '''
    def bubbleSort(tmpList):
        for i in range(len(tmpList)-1):
            for j in range(len(tmpList)-1,i,-1):
                if tmpList[j-1] > tmpList[j]:
                    tmpList[j-1],tmpList[j] = tmpList[j],tmpList[j-1]
        print(tmpList)
    bubbleSort([9,8,7,6,5,4,3,2,1])
    
    
    '''
    选择排序:思想就是 当当前数跟后面所以对比,然后找到最小的。这两个点进行交换。
    331 -> 133  不稳定排序 时间复杂度n*n
    '''
    def selectSort(tmpList):
        for i in range(len(tmpList) - 1):
            minIndex = i
            for j in range(i+1,len(tmpList)):
                if tmpList[j] < tmpList[i]:
                    minIndex = j
            if minIndex != i:
                tmpList[i],tmpList[minIndex] = tmpList[minIndex],tmpList[i]
        print(tmpList)
    
    selectSort([9,8,7,6,5,4,3,2,1])
    
    '''
    插入排序:通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
    时间复杂度 n*n  稳定。
    '''
    def InsertSort(tmpList):
        for i in range(1,len(tmpList)):
            key = tmpList[i]
            a = i
            while key < tmpList[a-1]:
                tmpList[a] = tmpList[a-1]
                a = a-1
                if a - 1 < 0:
                    break
            tmpList[a] = key
        print(tmpList)
    
    InsertSort([9,8,7,6,5,4,3,2,1])
    
    '''
    希尔排序: 每次将相同间隔的数组成一个小数组,然后用插入排序实现, 时间复杂度为 nlgn 不稳定
    '''
    def ShellSort(tmpList):
        step = len(tmpList)//2
        while step > 0:
            for i in range(step):
                j = i + step
                while j < len(tmpList):
                    a = j
                    key = tmpList[j]
                    while key < tmpList[a - step]:
                        tmpList[a] = tmpList[a - step]
                        a = a - step
                        if a - step < 0:
                            break
                    tmpList[a] = key
                    j += step
            step = step//2
        print(tmpList)
    
    ShellSort([9,8,7,6,5,4,3,2,1])
    
    '''
    堆排:思想来自于二叉树,还是完全二叉树,有大根堆(从小到大),小根堆(从大到小)。
    先建立完全二叉树,建立的思路就是 大根堆或者小根堆的定义。
    建好后,每次将当前最大数 挪到根节点,然后将根节点跟最后节点数据实现互换,如此循环执行即可。
    '''
    def adjustHeap(tmpList,i,size):
        left = 2*i+1
        right = 2*i+2
        max = i
        if i < size//2:
            if left < size and tmpList[left] > tmpList[max]:
                max = left
            if right < size and tmpList[right] > tmpList[max]:
                max = right
            if max != i:
                tmpList[max],tmpList[i] = tmpList[i],tmpList[max]
                adjustHeap(tmpList,max,size) # 数据互换后要考虑 i 下面根节点的影响。
    
    def buildHeap(tmpList,size): # 建立一个 大根堆
        for i in range((size)//2,0,-1):
            adjustHeap(tmpList,i,size)
    
    def heapSort(tmpList):
        size = len(tmpList)
        buildHeap(tmpList,size)
        for i in range(0,size)[::-1]:
            tmpList[i],tmpList[0] = tmpList[0],tmpList[i]
            adjustHeap(tmpList,0,i)
        print(tmpList)
    heapSort([9,8,7,6,5,4,3,2,1])
    
    '''
    归并排序: 分治的思想,将数据分成若干小的组合,然后组合与组合两两排序,排序后的组合再两两排序,
    深度遍历的思想  DFS, 这样的函数通常都包含递归调用的思想   不稳定
    '''
    def merge(left,right):
        ans = []
        i = 0
        j = 0
        while i < len(left) and j < len(right):
            if left[i] <= right[j]:
                ans.append(left[i])
                i += 1
            else:
                ans.append(right[j])
                j += 1
        ans += left[i:] + right[j:]
        return ans
    def mergeSort(tmpList):
        size = len(tmpList)
        if size < 2:
            return tmpList
        mid = size // 2
        left = mergeSort(tmpList[:mid])
        right = mergeSort(tmpList[mid:])
        return merge(left,right)
    print(mergeSort([9,8,7,6,5,4,3,2,1]))
    
    '''
    快排:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列,不稳定
    '''
    def subSort(tmpList,left,right):
        key = tmpList[left]
        while left < right:
            while left < right and tmpList[right] >= key:
                right -= 1
            tmpList[left] = tmpList[right] # 理解下 减少不必要的数据交换
            while left < right and tmpList[left] <= key:
                left += 1
            tmpList[right] = tmpList[left] # 理解下 减少不必要的数据交换
        tmpList[left] = key
        return left # 返回中间数的索引
    
    def quickSort(tmpList,left,right):
        if left < right:
            keyIndex = subSort(tmpList,left,right)
            quickSort(tmpList,left,keyIndex)
            quickSort(tmpList,keyIndex+1,right)
    
    tmpList = [5,1,9,3,7,4,8,6,2]
    quickSort(tmpList,0,len(tmpList)-1)
    print(tmpList)
    
    
    '''
    !!!  计数排序、基数排序、桶排序则属于非比较排序,算法时间复杂度O(n),优于比较排序。但是也有弊端,会多占用一些空间,有特定的数据要求,不能是负数,不能是小数,相当于是用空间换时间。
    '''
    
    '''
    桶排:通排序非常浪费空间, 比如需要排序的范围在0~2000之间, 需要排序的数是[3,9,4,2000], 同样需要2001个空间
    注意: 通排序不能排序小数
    '''
    def bucketSort(tmpList): # 待排序数组, 最大的筒子,数组的长度
        max_num = max(tmpList) # 选择一个最大数
        bucket = [0]*(max_num+1)  # 创建一个元素全为0的列表当桶
        for i in tmpList: # 把所有元素放入桶中,计算该数出现次数
            bucket[i] += 1
        ans = []
        for i in range(len(bucket)):
            if bucket[i] != 0: # 如果该数出现的次数大于0
                for j in range(bucket[i]): # 出现多少次都将数放入桶中
                    ans.append(i)
        return ans
    
    tmpList = [5,6,3,2,1,65,2,0,8,0]
    print(bucketSort(tmpList))
    
    '''
    计数排序:基本思想是:对每一个输入的元素a[i],确定小于 a[i] 的元素个数。所以可以直接把 a[i] 放到它输出数组中的位置上。假设有5个数小于 a[i],所以 a[i] 应该放在数组的第6个位置上。
    '''
    def countSort(tmpList,maxNum): #  呆排序数组,最大值
        ans = [0]*len(tmpList)
        c = [0]*(maxNum+1)
        for i in tmpList:
            c[i] += 1
        for i in range(1,maxNum+1):
            c[i] += c[i-1]  #统计每个数字所在的idx
        for j in tmpList:
            ans[c[j]-1] = j
            c[j] = c[j] - 1
        return ans
    
    tmpList = [5,6,3,2,1,65,2,0,8,0]
    print(countSort(tmpList,max(tmpList)))
    
    def radixSort(tmpList):
        n = 1 # 计算数最多多少位
        maxNum = max(tmpList)
        while maxNum//(10**n) > 0:
            n +=1
        for i in range(n): # n轮排序
            s = [[] for i in range(10)] # 因为没一位数字都是0~9 ,故建立10个桶
            # 对于数组中的元素,首先按照最低有效数字进行排序,然后由低位向高位进行
            for j in tmpList:
                '''对于3个元素的数组[977, 87, 960],第一轮排序首先按照个位数字相同的
                   放在一个桶s[7]=[977],s[7]=[977,87],s[0]=[960]
                   执行后list=[960,977,87].第二轮按照十位数,s[6]=[960],s[7]=[977]
                   s[8]=[87],执行后list=[960,977,87].第三轮按照百位,s[9]=[960]
                   s[9]=[960,977],s[0]=87,执行后list=[87,960,977],结束。'''
                s[j//(10**i)%10].append(j)
            tmpList = [j for i in s for j in i]
        return tmpList
    
    tmpList = [5,6,3,2,1,65,2,0,8,0]
    print(radixSort(tmpList))
    关注公众号 海量干货等你
  • 相关阅读:
    C# 使用FileSystemWatcher类来对一个日志文件的变化进行实时监测
    C# 高效提取txt文档最后一行数据
    C# 高效提取txt文档最后一行数据
    Bat 批处理之 for/f 详解
    Bat 批处理之 for/f 详解
    windows bat命令 如何获取文件最后一行
    windows bat命令 如何获取文件最后一行
    C#读取文件或者字符流的最后几行,类似linux的tail命令OK
    C#读取文件或者字符流的最后几行,类似linux的tail命令OK
    C#开源文件实时监控工具Tail&TailUI
  • 原文地址:https://www.cnblogs.com/sowhat1412/p/12734321.html
Copyright © 2020-2023  润新知