Python——排序(冒泡、选择、插入、快速、堆..) 时间复杂度 (个人向)

本文介绍了排序算法的时间复杂度和大O表示法,详细讲解了冒泡排序、选择排序、直接插入排序和快速排序的思路,并提到了堆排序的概念和操作。这些排序算法在Python中的应用广泛,理解其工作原理对于优化代码性能至关重要。

一、时间复杂度

将程序执行的计算步骤的总和叫做时间复杂度
时间复杂度实际上用来描述算法时间效率

例:如T(n)=n2+5n+6与T(n)=4n2+2n+1它们的频度不同,但时间复杂度相同,都为O(n2)。随着问题规模n的不断增大,上述时间复杂度不断增大,算法的执行效率越低。
总结:大O表示法就是将一个T(n)时间复杂度的系数去掉只留下最特征的部分就是大O表示法。
引用:
在这里插入图片描述

二、排序

常用排序:
冒泡排序 - (交换排序) 快速排序 - (交换排序)
选择排序 - (选择排序)、堆排序 - (选择排序)
直接插入排序 - (插入排序)、希尔排序 - (插入排序)、
(归并排序、、桶/基数排序)
——————————————
冒泡排序
思路:
1.重复遍历要排序的数列n个元素,一次比较相邻两个元素 一次比较,保证
右边的元素始终大于左边
的元素;
(第一轮结束后,数列中最后一个元素一定是当前数列中最大值)
2.对数列当中剩下的n-1个元素,再次执行步骤1
3.对于长度为n的数列,一共需要执行n-1次轮的比较

"""冒泡排序"""
def bubble_sort(lst):
    for i in range(len(lst) - 1):
        for j in range(len(lst) - 1 - i):
            if lst[j] > lst[j + 1]:
                lst[j], lst[j + 1] = lst[j + 1], lst[j]
    return lst


l1 = [33, 11, 44, 22, 55, 66, 12, 42, 23, 45, 97, 54]
print(bubble_sort(l1))
#[11, 12, 22, 23, 33, 42, 44, 45, 54, 55, 66, 97]

————————————————
选择排序
思路:
1.遍历待排序数列,并定义当前位置的元素为此次循环最小值
(首先找到最小的元素)
2.若最小元素不是待排序数列的第一个元素,将其和第一个元素互换
3.将该元素与剩下的元素依次比较寻找最小元素,重复1,2直至结束

"""选择排序"""
def select_sort(lst):
    for i in range(len(lst)):
        min = i
        for j in range(i + 1, len(lst)):
            if lst[j] < lst[min]:
                min = j
        lst[i], lst[min] = lst[min], lst[i]
    return lst
    
import random
lst = [random.randint(1, 22) for i in range(5)]
print(lst)
print(select_sort(lst))
# [4, 8, 13, 6, 3]
# [3, 4, 6, 8, 13]

————————————————
直接插入排序
思路:
将待排序数列中的所有元素依次跟前面已经排好的元素相比较,如果选择的元素比已排序的元素小,则交换位置,直到遍历过全部元素
注意:遍历待排序数列中所有元素,默认索引为0的元素已排序,所以从1开始

"""插入排序"""
def inset_sort(lst):
    for i in range(1,len(lst)):
        for j in range(i,0,-1):
            #从第i元素开始向前比较,如果小于前面一个元素 则交换位置
            if lst[j] < lst[j-1]:
                lst[j],lst[j-1] = lst[j-1],lst[j]
    return lst

import random
lst = [random.randint(10,66) for i in range(10)]
print(lst)
print(inset_sort(lst))
# [62, 32, 20, 56, 39, 39, 63, 16, 15, 48]
# [15, 16, 20, 32, 39, 39, 48, 56, 62, 63]

————————————————
快速排序
思路:通过多次比较和交换来实现
1.从待排序数列中挑选一个元素,称为"基准"(一般为索引为0的元素)
2.重新排序数列,所有元素中比基准值小的放在基准前面比基准值大的放在基准后面,排序后该基准处于数列中间位置,该操作可称为分区操作
3.递归调用,把左右两侧排序完毕

def quick_sort(lst, start, end):
    if start < end:
        s = start
        e = end
        num= lst[s]
        while s < e:
            while s < e and lst[e] > num:
                e = e - 1
            lst[s] = lst[e]
            while s < e and lst[s] < num:
                s = s + 1
            lst[e] = lst[s]
        #剩下一个s的坑,用来放num
        lst[s] = num
        # 这个地方用递归,对左右两边的排列再次调用快排
        quick_sort(lst, start, s - 1)
        quick_sort(lst, e + 1, end)
    return lst

lst =[random.randint(11,66) for i in range(5)]
print(lst)  # [28, 41, 14, 42, 12]
res = quick_sort(lst, 0, len(lst) - 1)
print(res)  # [12, 14, 28, 41, 42]

—————————————————————————————
堆排序

堆是一个近似完全二叉树的结构
并同时满足堆积的性质:
子结点的键值或索引总是小于(或者大于)它的父节点

堆的操作:
在堆的数据结构中,堆中的最大值总是位于根节点
(在优先队列中使用堆的话堆中的最小值位于根节点)
堆中定义以下几种操作:
最大堆调整:将堆的末端子节点作调整,使得子节点永远小于父节点
创建最大堆:将堆中的所有数据重新排序
堆排序:移除位在第一个数据的根节点,并做最大堆调整的递归运算

def d_sort(arr):
    l = len(arr)
    for i in range(int(l / 2 - 1), -1, -1):
        adjustHead(arr, i, l)
    # 交换堆顶和最后一个元素,并调整堆结构
    for j in range(l - 1, 0, -1):
        arr[0], arr[j] = arr[j], arr[0]  # 将堆顶元素和末尾元素进行交换
        adjustHead(arr, 0, j)  # 重新对对进行调整
    for k in range(0, l):
        print(arr[k])

# 构造大顶堆
def adjustHead(a, i, l):
    temp = a[i]  # 取出当前元素
    k = 2 * i + 1  # 从左子节点开始,即2*i+1
    while k < l:
    	# 若果左子节点小于右子节点,k指向右子节点
        if k + 1 < l & a[k] < a[k + 1]:  
            k = k + 1
        # 如果子节点大于父节点,将子节点赋值给父节点,并将子节点下标记录下来,
        	#后面将父节点值赋值给该子节点
        if a[k] > temp:  
            a[i] = a[k]
            i = k
        else:
            break
        k = 2 * k + 1  # 把该节点当作父节点,继续操作
    a[i] = temp  # 将父节点值赋值给该子节点

if __name__ == "__main__":
    a = [10, 2, 4, 5, 3,]
    d_sort(a)
#2 3 4 5 10
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值