基础排序算法——LowLow三人组

本文详细介绍了三种基本排序算法:冒泡排序、选择排序和插入排序。冒泡排序包括传统冒泡排序和一种称为“排头法”的变体,其实质是选择排序。文章探讨了这些排序算法的工作原理、时间复杂度,并展示了优化方法。对于选择排序,作者指出其无法像冒泡排序那样通过提前终止来优化。插入排序则是通过分隔已排序和未排序部分逐步构建有序序列。所有排序算法的时间复杂度均为O(n^2)。
摘要由CSDN通过智能技术生成

LowB三人组——冒泡排序、插入排序、选择排序

牛 逼三人组——快速排序、归并排序、堆排序、希尔排序(另外的)

1、冒泡排序法:

按寻常理解,是要相邻的元素进行比较,将极值逐个放到末尾,寻常代码如下

# 咕噜咕噜往后排
# 传统冒泡排序法
def bubble_sort(lst):
    for i in range(len(lst)):
        for j in range(i+1,len(lst)):
            if lst[j-1]>lst[j]:
                lst[j],lst[j-1] = lst[j-1],lst[j]
        print(lst)

lst = [1,3,5,2,6]
bubble_sort(lst)

在这里插入图片描述
但有一种排序,也是逐个逐个对比,只是把极值放在头部,代码如下

# 类似冒泡排序的排头法
def like_bubble_sort(lst):
    for i in range(len(lst)):
        for j in range(i+1, len(lst)):
            if lst[i]>lst[j]:
                lst[i],lst[j] = lst[j],lst[i]
        print(lst)

    return lst
lst = [1,3,5,2,6]
like_bubble_sort(lst)

在这里插入图片描述
第二种与传统冒泡排序法,极值位置和对比位置虽有不同,但排序的过程都是两两相互比较的,并且时间复杂度、空间复杂度,都是一样的。因此,第二种排序,可以说是传统冒泡排序的延伸,但实际应用中又略有不同,姑且称第二种类似冒泡的排序法,成为“排头法”吧(生动一些,我也不知道有没有其他专业人士给专门命名了)。

时间复杂度:每个元素都要跟剩余元素比较,所以比较次数是n*(n-1)=n^2-n。根据以下时间复杂度的大O表示法,冒泡排序时间复杂度为O(n ^ 2)
【大O和小O在数学中分别表示极限大和极限小,可搜索了解】
在这里插入图片描述

实际应用的优化——冒泡排序法

但上述的冒泡排序法实际应用是不够高效的,当某一轮排序过程中,不再产生相邻元素的交换,说明,每一个元素都比前一个元素大(或小),比后一个元素小(或大)。这时候,排序已提前完成,无需再进行下一轮的排序。
优化后的代码如下

# 优化后的冒泡排序法
def bubble_sort(lst):
    for i in range(len(lst)-1):
        # 每轮循环前设置控制变量stop为True
        stop = True
        for j in range(i,len(lst)-1):
            if lst[j+1]>lst[j]:
                lst[j],lst[j+1] = lst[j+1],lst[j]
                # 如果每轮相邻元素的对比中,有交换,则设置控制变量stop为False,表示不能停止排序
                stop = False
        print(lst)
        # 每轮循环比较后,判断stop是否依然是True,如果是True,表示比较过程没有交换,则立刻停止冒泡排序
        if stop:
            return lst
lst = [1,3,5,2,6]
bubble_sort(lst)

优化后的冒泡排序法,只需要进行3轮的比较
在这里插入图片描述

但之前所说的类似于冒泡排序法的“排头法”就不能这么优化了,因为排头法虽然也是两两进行比较,但却不是相邻元素的比较,只是头部元素与后续每一个元素的比较,如果一轮排序下来,无元素交换,也只能说明头部元素是极值,却不能说明相邻元素之间的顺序已确定。因此如果盲目使用优化的方法,会导致结果出错的。

# “优化后” 的排头法
def like_bubble_sort(lst):
    for i in range(len(lst)):
        break_key = True
        for j in range(i+1, len(lst)):
            if lst[i]>lst[j]:
                lst[i],lst[j] = lst[j],lst[i]
                break_key = False
        print(lst)
        if break_key:
            break
    return lst
lst = [1,3,5,2,6]
like_bubble_sort(lst)

如果是用之前优化传统冒泡排序法的方法,这个排头法对比一次就结束了,因为原列表的头部数字1,在与后续元素比较时,都是最小的,这样第一轮排序就没有元素交换,这时如果停止后续的排序,那么结果就会出错。
在这里插入图片描述

选择排序法

算法有多讨厌呢,大概就是曾经夜郎自大地与别人讨论,“排头法”其实就是冒泡排序的衍生物后,发现。。。原来 “排头法” ,学名 “选择排序法”,尴尬,尴了个大尬。
在记录冒泡排序法衍生出的“排头法”,其实原理就是“选择排序法”。可怕吗,哈哈哈哈哈哈,不可怕,就是有点儿尴尬。
选择排序法的原理就是,极值往前排。
实现的方法有好几种,但主要说明以下两种
第一种就是上边冒泡尴尬了的“排头法”,效率非常低,每次都要交换

# 选择排序法
def select_sort(lst):
    for i in range(len(lst)):
        for j in range(i+1, len(lst)):
            if lst[i]>lst[j]:
                lst[i],lst[j] = lst[j],lst[i]
        print(lst)
lst = [1,3,5,2,6]
select_sort(lst)

在这里插入图片描述
第二种,相对好一些,至少是遇到极值先记下坐标,当一轮比较下来后,将极值坐标与头部坐标交换即可。这样就节省了交换的次数

# 优化后的选择排序法
def select_sort(lst):
    for i in range(len(lst)):
        min_index = i
        for j in range(i+1, len(lst)):
            if lst[i]>lst[j]:
                min_index = j
        lst[i],lst[min_index] = lst[min_index],lst[i]
        print(lst)
lst = [1,3,5,2,6]
select_sort(lst)

在这里插入图片描述
但依然发现,无论优化与否,选择排序的比较次数都一样,并且案例中第3轮排序其实已经是最后的顺序,却还是要继续完成后两轮的排序。
因此,选择排序暂时没有更好的优化方式。
(吐槽,选择排序,取名一点儿都不生动)
选择排序的时间复杂度:O(n^2)

插入排序法

插入排序:分隔两列,前列已排序,后列未排序,后列逐个向前列排序
# 插入排序法
def insert_sort(lst):
	length = len(lst)
	for i in range(length):
		j = i+1
		# 前序
		while j>0:
			if lst[j]<lst[j-1]:
				lst[j],lst[j-1] = lst[j-1],lst[j]
				j -= 1
			else:
				break
		return lst

插入排序法的时间复杂度:O(n^2)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值