Python十大排序算法

版权声明:个人学习笔记 https://blog.csdn.net/qq_31821675/article/details/84842025

代码如下:
 

'''
几乎是我们学习排序入门算法了,两次遍历,时间复杂度较高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))

猜你喜欢

转载自blog.csdn.net/qq_31821675/article/details/84842025