python入门项目一:排序和查找算法

一 插入排序

1.1 核心思想

插入排序(Insert ion Sort),其核心思想:将数组中的所有元素(从第二个元素开始,第一个默认已排好序)依次跟前面已经排好的所有元素相比较,如果选择的元素比已排序的元素小,则交换位置,直到全部元素都比较过。
因此,直接插入排序可以用两个循环完成:

第一层循环:遍历待比较的所有数组元素(从第二个元素开始)
第二层循环:将上层循环选择的元素(selected)与已经排好序的所有元素(ordered)相比较,从选择元素的前面一个开始直到数组的起始位置。如果selected < ordered,那么将二者交换位置,继续遍历;反之,留在原地,选择下一个元素。

1.2 过程示意图

排序过程示意图(图片来自于网络):
在这里插入图片描述

1.3 python 实现过程

#插入排序
def insert_sort(ls):
#假设左边已排序,右边未排序,每次从右边取一个数,遍历已排序的子序列,直到找到合适的位置
    print("before: ",ls)
    for j in range(1, len(ls)):
#将该元素与已排序好的前序数组依次比较,如果该元素小,则交换
#range(x, 0, -1):从x倒序循环到0,依次比较
#每次比较如果小于会交换位置,正好按递减的顺序
        for i in range(j, 0, -1):
            #符合条件则交换
            #ls[i] < ls[i - 1]:
               # [i], ls[i-1] = ls[i-1], ls[i]
            if ls[i] < ls [i - 1]:
                temp = ls[i]
                ls[i] = ls[i - 1]
                ls[i - 1] = temp
        print(ls)
    print("after: ", ls)

⚠️注意⚠️ 这个地方提供了两种交换方式
(1) 直接交换,中间用 , 连接
(2)借用中间数temp

1.4 实现结果

在这里插入图片描述

1.5 时间复杂度

最优时间复杂度:O(n)(升序序列,序列已经处于升序状态)
最坏时间复杂度:O(n2)
稳定性:稳定

二 冒泡排序

2.1 核心思想

  1. 将序列当中的左右元素,依次比较,保证右边的元素始终大于左边的元素;
    ( 第一轮结束后,序列最后一个元素一定是当前序列的最大值;)

  2. 对序列当中剩下的n-1个元素再次执行步骤1。

  3. 对于长度为n的序列,一共需要执行n-1轮比较 (利用while循环可以减少执行次数)

2.2 排序示意图

交换过程示意图(第一次)(来自网络):
在这里插入图片描述

2.3 python 代码实现

#冒泡排序
def bubble_sort(ls):
    print("before: ", ls)
    for j in range(len(ls) -1 , 0, -1):
        #j = [len(ls) - 1, len(ls) - 2, ..., 1] 每次需要比较的次数
        #i = [0, 1, 2, 3, ..., j - 1]  需要比较的下标
            #对于每一轮交换,都将序列当中的左右元素进行比较
            #每轮交换当中,序列最后的元素一定是最大的
            #因此每轮循环到序列未排序的位置即可
        for i in range(j):
            if ls[i] > ls[i + 1]:
                ls [i], ls[i+1] = ls [i + 1], ls[i] 
        print(ls)
    print("after: ",ls)
if __name__ == "__main__":
    ls = [54, 26, 93, 17, 77, 31, 44, 55, 20]
    bubble_sort(ls)

2.4 实现结果

在这里插入图片描述

2.5 时间复杂度

最优时间复杂度:O(n)(表示遍历一次发现没有任何可以交换的元素排序结束,在内循环可以做一个标识判断,如果首次循环没有任何交换,则跳出)
最坏复杂度:O(n2)
稳定性:稳定

三、选择排序

3.1 核心思想

选择排序( Selection Sort )是一种简单直观的排序算法,基本原理:首先在未排序中找到最小(大)的元素,存放在排序序列的起始位置,然后在从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序的末尾,依次类推,直到所有元素均排序完毕。

选择排序的主要优点与数据移动有关。如果某个元素位于正确的最终位置上,则它不会被移动。选择排序每次交换一对元素,它们当中至少有一个被移到其最终位置上,因此对 n 个元素的表进行排序共进行至多 n - 1次交换。在所有完成依靠交换去移动元素的排序方法中,选择排序属于非常好的一种。

3.2 排序示意图

排序过程,图示(图来源网络):
假设右边为已排序,然后从左边未排序中选择一个最大值,放到右边来。
在这里插入图片描述

3.3 python 实现过程

这里代码的思想为:假设左边为已排序,右边为排序。

#选择排序
def selection_sort(ls):
    print("before: ", ls)
    for i in range (len(ls)-1):
        #i = [0, 1, 2, 3, ..., len(ls) - 2]
        #j = [i + 1, i + 2, ..., len(ls) - 1]
        main_index = i
        for j in range(i + 1, len(ls)):
            if ls[j] < ls[main_index]:
                main_index = j
        if main_index !=i:
            ls[main_index], ls[i] = ls[i], ls[main_index]
        print(ls)
    print("after: ", ls)

if __name__ == "__main__":
     ls = [54, 26, 93, 17, 77, 31, 44, 55, 20]

     selection_sort(ls)   

3.4 实现结果

在这里插入图片描述

3.5 时间复杂度

最优时间复杂度:O(n2)
 最坏时间复杂度:O(n2)
 稳定性:不稳定(考虑升序每次选择最大的情况)

四、快速排序

4.1 核心思想

快速排序(Quick Sort),又称为划分交换排序(Partition-exchange Sort),通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要笑,然后在按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

快速排序过程:

① 从数列中选出一个元素,称为“基准”(pivot)。
② 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准大的摆在基准的后面(相同的数,可以放到任意一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
③ 递归(recursive)把小于基准值元素子数列和大于基准值元素的子数列排序。

递归的的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。

4.2 排序过程示意图

在这里插入图片描述

4.3 python 实现过程

#快速排序
def quick_sort(ls, start, end):
    '''
    快速排序-1
    low和high分别指向序列的头和尾
    low += 1, high -= 1
    在low自增的过程中,直到找到大于mid_val的下标
    在high自减的过程中,直到找到小于mid_val的下标
    然后将这两个值交换
    '''
    if start >= end:
        return
    
    low = start
    high = end
    mid_val = ls[low]

    while low < high:
        while low < high and ls[high] > mid_val:
            high -= 1
        ls[low] = ls[high]

        while low < high and ls[low] < mid_val:
            low +=1
        ls[high] = ls[low]
    ls [low] = mid_val
    print("mid: ", mid_val, ls)

    quick_sort(ls, start, low - 1)   #左边的子序列
    quick_sort(ls, low + 1, end)      #右边的子序列
    return ls

if __name__ == "__main__":
    ls = [54, 26, 93, 17, 77, 31, 44, 55, 20]
    
    print("before:", ls)
    res = quick_sort(ls, 0, len(ls) - 1)
    print("quick sort: ", res)

4.4 实现结果

在这里插入图片描述

4.5 时间复杂度

最优时间复杂度:O(nlogn)
最坏时间复杂度:O(n2)
稳定性:不稳定

五 二分查找

5.1 基本思想

二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好,其缺点是要求待查找表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。

基本思想:假设表中元素是按升序排序,将表中间位置记录关键字与查找关键字比较,如果两者相等,则查找成功,否则利用中间位置记录分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一个子表。重复以上过程,知道找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

5.2 python实现代码

#二分查找
def binary_search_recursion(ls,item):
    n = len(ls)
    if n < 1:
        return False

    mid  = n // 2

    #与中间值比较
    if item == ls[mid]:
        return True
    #去左边子序列查找
    elif item < ls[mid]:
        return binary_search_recursion(ls[:mid], item)
    #去右边子序列查找
    else:
        return binary_search_recursion(ls[mid + 1:],item)
    
if __name__ == "__main__":
    ls = [17, 20, 26, 31, 44, 54, 55, 77, 93]

    num = int(input("请输入一个整数"))
    res = binary_search_recursion(ls, num)
    print("查找结果:", res)

5.3 实现结果

在这里插入图片描述

5.4 时间复杂度

最优时间复杂度:O(1)
最坏时间复杂度:O(logn)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值