【算法二排序--python】

排序

将一组无序列表调整为有序列表。
python内置函数(内部使用的是顺序查找方法):sort()。

Li=[23,45,21,56]
a=sorted(Li) #返回排序后的新列表,不会修改原有列表
Li.sort() #无返回值,在原有序列上进行升序排序
print(Li)
Li.sort(reverse=True)  #在原有序列上进行降序排序
print(Li)
  • 排序的方法):

    • 冒泡排序:
      • 时间复杂度为O(n2),在原有列表上进行修改
      • 每一趟排序逐个对相邻的两个数进行对比,一趟排序固定一个有序数据
      • 如果有一趟排序没有发生交换,说明列表已经有序可以直接结束算法,提高效率
    • 选择排序:
      • 时间复杂度为O(n2),在原有列表上进行修改
      • 每次从列表的无序区选择最小元素和无序区第一个元素交换,并将其加入有序区
    • 插入排序:
      • 时间复杂度为O(n2),在原有列表上进行修改
      • 把无序区的元素逐个放入有序区的合适位置

    • 快速排序:
      • 时间复杂度为O(nlog2n)
      • 逐个取列表元素将其归位,左边元素比它小,右边元素都比它大,递归完成
      • 最坏情况:当列表是逆序时,每次只能排序一个元素,时间复杂度为O(n2)。解决方法可以在第一次取随机位置的元素与第一个元素交换,再进行排序。
    • 堆排序:
      • 时间复杂度为O(nlog2n)
    • 归并排序:
      • 时间复杂度为O(logn)
    • 希尔排序:
      • 时间复杂度为O(logn)
    • 计数排序:
      • 时间复杂度为O(logn)
    • 基数排序:
      • 时间复杂度为O(logn)
        如果查找需要执行很多次,可以考虑先将列表进行排序,使用二分查找执行。可以提高效率。

冒泡排序

如果有一趟排序没有发生交换,说明列表已经有序可以直接结束算法,提高效率。

def bubble_sort(Li):  #在Li列表上直接进行修改
    for i in range(len(Li)-1):
        exchange=False
        for j in range(len(Li)-i-1):
            if Li[j]>Li[j+1]:
                Li[j],Li[j+1]=Li[j+1],Li[j]
                exchange=True
        if not exchange:
            return

选择排序

#每次选择最小的元素放入新的列表中
#时间复杂度为O(n**2),并且空间复杂度为T(n)
def select_sort_simple(Li):
    Li_new=[]
    for i in range(len(Li)):
        min_val=min(Li)        #时间复杂度为O(n)
        Li_new.append(min_val)
        Li.remove(min_val)     #时间复杂度为O(n)
    return Li_new

#每次从列表的无序区选择最小元素和无序区第一个元素交换
#时间复杂度为O(n**2),在原有列表上进行修改
def select_sort(Li):
    for i in range(len(Li)-1):
        min_index=i
        for j in range(i+1,len(Li)):
            if Li[min_index]>Li[j]:
                min_index=j
        Li[i],Li[min_index]=Li[min_index],Li[i]

插入排序

#把无序区的元素逐个放入有序区的合适位置
#时间复杂度为O(n**2)
def inert_sort(Li):
    for i in range(1,len(Li)):
        j=i-1
        temp=Li[i]
        while j>=0 and Li[j]>temp:
            Li[j+1]=Li[j]
            j-=1
        Li[j+1]=temp

快速排序

#逐个取列表元素将其归位,左边元素比它小,右边元素都比它大,递归完成
def partition(Li,left,right):
    tmp=Li[left]
    while left<right:
        while left<right and Li[right]>tmp:
            right-=1
        Li[right],Li[left]=Li[left],Li[right]
        while left<right and Li[left]<tmp:
            left+=1
        Li[right],Li[left]=Li[left],Li[right]
    Li[left]=tmp
    return left
def quick_sort(Li,left,right):
    if left<right:
        mid=partition(Li,left,right)
        quick_sort(Li,left,mid-1)
        quick_sort(Li,mid+1,right)

堆排序

完全二叉树顺序存储时,父节点与孩子节点下标的关系为:
左孩子节点下标=2父节点下标+1
左孩子节点下标=2
父节点下标+2
大根堆:一个完全二叉树,满足任意节点都比其孩子节点大
小根堆:一个完全二叉树,满足任意节点都比其孩子节点小
堆的向下调整:假设节点的左右子树都是堆,但是自身不是堆。可以通过一次向下调整将其变换成一个堆。(逐步将左右子树中的最大的元素向上移动,遇到左右子树的节点都比该节点小,将该节点填补在此处)
堆排序的方法为:
1、建立一个堆。(从最后一个非叶子节点开始使用堆的向下调整构建堆)
2、得到堆顶元素为最大元素
3、去掉堆顶,将堆的最后一个元素放到堆顶,此时可以通过一次调整(堆的向下调整)重新使堆有序
4、循环重复

#向下调整函数
def sift(Li,low,high):
    :param Li:列表
    :param low:堆的根节点位置
    :param high:堆的最后一个元素位置
    
    i=low       #i最开始指向根节点
    j=2*i+1     #j开始是左孩子
    tmp=Li[low]   #把堆顶存起来
    while j <=high:    #只要j位置有数
        if j+1<=high and Li[j+1]>Li[j]:   #如果有右孩子并且比左孩子大
            j=j+1     #j指向右孩子
        if Li[j]>tmp:
            Li[i]=li[j]
            i=j       #往下看一层
            j=2*i+1
        else:         #tmp更大,把tmp放到i的位置上
            Li[i]=tmp
            break
    else:
        Li[i]=tmp     #把tmp放到叶子节点上

#构造堆
def heap_sort(data):
    n=len(data)
    for i in range(n//2-1,-1,-1):
        sift(data,i,n-1)
    for i in range(n-1,-1,-1):
        data[0],data[i]=data[i],data[0]
        sift(data,0,i-1)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值