Python笔记(八)

1. 排序算法稳定性

如果在待排序的列表中,存在多个相同的数据,经过排序后,这些元素的相对次序保持不变,即可称这种排序算法是稳定的,反之则不稳定
在这里插入图片描述

2. 冒泡排序

2.1 基本思想

从小到大排序:两两比较,不符合条件时,就互换位置,直至序列中所有元素顺序正确。

2.2 实现分析

new_list = [5, 4, 3, 2, 1]
第一次:5和4比较,5和4位置互换 new_list = [4, 5, 3, 2, 1]
第二次:5和3比较,5和3位置互换 new_list = [4, 3, 5, 2, 1]
第三次,5和2比较,5和2位置互换 new_list = [4, 3, 2, 5, 1]
第四次,5和1比较,5和1位置互换,此时列表最后一个元素为最大值。 new_list = [4, 3, 2, 1, 5]
此时第一轮比较完成,开始进行第二轮
第一次,4和3比较,4和3位置互换 new_list = [3, 4, 2, 1, 5]
第二次,4和2比较,4和2位置互换 new_list = [3, 2, 4, 1, 5]
第三次,4和1比较,4和1位置互换 new_list = [3, 2, 1, 4, 5]
此时,4已经不用和5比较了,因为上一轮的结果就证明5是最大的。至此第二轮结束。

通过以上梳理发现,当元素个数为n时,一共需要比较n-1轮,来确定每个位置上符合条件的元素。
每一轮需要比较n-i次,其中i为当前轮数。

2.3 代码实现

def my_bubble_sort(my_list, is_desc=False):
    """
    冒泡排序
    :param my_list:需要进行排序的列表
    :param is_desc:是否从大到小,默认是否
    :return: new_list
    """
    length = len(my_list)
    out_num = 0  # 定义比较的轮数
    comp_times = 0  # 每轮比较的次数
    for i in range(length - 1):  # 定义外层循环,一共需要比较n-1轮
        out_num += 1
        for j in range(length - out_num):
            # 从小到大排序
            if my_list[j] > my_list[j + 1]:
                comp_times += 1  # 比较次数加一
                my_list[j], my_list[j + 1] = my_list[j + 1], my_list[j]
            # 如果这一轮比较的次数为0,说明是有序列表
            if comp_times == 0:
                break
    if is_desc:
        my_list.reverse()
    return my_list


new_list = [5, 4, 3, 2, 1]
print(my_bubble_sort(new_list))
print(my_bubble_sort(new_list, True))

2.4 总结

冒泡排序是稳定算法
最优时间复杂度为O(n)
最差时间复杂度为O(n^2)

3. 选择排序

3.1 基本思想

从小到大:
从待排序列中指定一个最小值,然后让其与剩余元素挨个比较,若碰见小的就替换,碰见大的就继续下一个比较。
确定之后,再从剩余元素中指定一个最小值,依次类推。直至排序完成

3.2 实现分析

new_list = [5, 4, 3, 2, 1]
第一轮:
先指定一个最小值5
4和5比较,4小于5,假定最小值为4
3和4比较,3小于4,假定最小值为3
2和3比较,2小于3,假定最小值为2
1和2比较,1小于2,假定最小值为1
此时第一轮完成,最小值发生了变化,所以交换1和5的位置。即new_list = [1, 4, 3, 2, 5]
第二轮:
指定最小值为4
3和4比较,3小于4,假定最小值为3
2和3比较,2小于3,假定最小值为2
5和2比较。5大于2,此时最小值仍为2,第二轮完成,最小值发生了变化,所以交换2和4的位置。
即new_list = [1, 2, 3, 4, 5]
第三轮
指定最小值为3
4和3比较,4大于3,最小值为3
5和3比较,5大于3,最小值为3
第三轮结束,此时最小值没有发生变化。即new_list = [1, 2, 3, 4, 5]
第四轮
指定最小值为4
5和4比较,5大于4,最小值为4.排序完成,即new_list = [1, 2, 3, 4, 5]

3.3 代码实现

def my_select_sort(my_list, is_desc=None):
    """
    选择排序
    :param my_list: 需要进行排序的列表
    :param is_desc: 是否从大到小,默认是否
    :return:
    """
    length = len(my_list)

    for j in range(0, length - 1):  # 控制轮数
        temp_min_index = j  # 假定的最小值的下标
        for i in range(j + 1, length):
            # 如果当前元素的值比下标小,就把当前元素的下标赋值给假定的最小值的下标
            if my_list[i] < my_list[temp_min_index]:
                temp_min_index = i
        # 如果当前轮中,下标值发生了变化,则进行交换
        if temp_min_index != j:
            my_list[j], my_list[temp_min_index] = my_list[temp_min_index], my_list[j]

    if is_desc:
        my_list.reverse()
    return my_list


new_list = [5, 4, 3, 2, 1]
print(my_select_sort(new_list))

3.4 总结

选择排序的最优最差的时间复杂度都是O(n^2),是不稳定算法。

4. 插入排序

4.1 基本思想

将一个数据插入到已经排好的有序数列中,从而得到一个新的且个数加一的有序数列,该算法适用于少量数据的排序。

4.2 实现分析

new_list = [6, 3, 4, 7, 2]
第一轮
假设6为有序数列,
3与6比较,3小于6,3和6交换位置,有序数列为3,6
第二轮
4与6比较,4小于6,4和6交换位置,然后4与3比较,4大于3,有序数列为3,4,6
第三轮
7与6比较,7大于6,有序数列为3,4,6,7
第四轮
2与7比较,2小于7,2与7交换位置,
然后2与6比较,2小于6,2与6交换位置。
然后2与4比较,2小于4,2与4交换位置。
然后2与3比较,2小于3,2与3交换位置。
此时,排序完成。
通过上述发现,每个元素都是与其前一个元素比较,直至找到合适的位置,或者是直到数列开始位置。

4.3 代码实现

def my_insert_sort(my_list, is_desc=None):
    """
    插入排序
    :param my_list: 需要进行排序的列表
    :param is_desc: 是否从大到小,默认是否
    :return:
    """
    length = len(my_list)
    # 外部循环,控制有多少待排序的元素
    for i in range(1, length):
        # 挨个比较
        for j in range(i, 0, -1):
            if my_list[j] < my_list[j-1]:
                my_list[j], my_list[j-1] = my_list[j-1], my_list[j]
            else:
                break
    if is_desc:
        my_list.reverse()
    return my_list


new_list = [6, 3, 4, 7, 2]
print(my_insert_sort(new_list))

4.4 总结

插入排序的最差时间复杂度为O(n^2),最优时间复杂度为O(n),是稳定算法。

5. 快速排序

5.1 基本思想

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小。然后再按照此方法对这两部分数据分别进行快速排序,依次类推,以此达到整个数据变成有序序列。

5.2 实现分析

首先定义两个左右游标,分别指向数列的开始和结尾。
其次定义一个界限值middle,默认为数列的第一个元素
然后分别移动左右游标遍历序列,将小于middle的值,归类到左边。
将大于middle的值,归类到右边。最后将界限值放入中间。至此,第一轮完成
然后对左右两边的数列分别进行递归快速排序。

5.3 代码实现

def my_quick_sort(my_list, start, end):
    """
    快速排序
    :param my_list: 需要进行排序的列表
    :param start: 起始位置
    :param end: 结束位置
    :return:
    """
    # 递归结束条件
    if start >= end:
        return

    # 定义界限值
    mid = my_list[start]
    # 定义左右游标
    left = start
    right = end
    while left < right:
        # 从结尾开始找小于mid的值,归类到左边
        while my_list[right] >= mid and left < right:
            right -= 1
        my_list[left] = my_list[right]
        # 从开头开始找大于mid的值,归类到右边
        while my_list[left] < mid and left < right:
            left += 1
        my_list[right] = my_list[left]

    my_list[left] = mid

    # 递归
    my_quick_sort(my_list, start, left - 1)
    my_quick_sort(my_list, right + 1, end)

    return my_list


new_list = [5, 9, 2, 7, 10, 1, 6, 8, 4]
print(my_quick_sort(new_list, 0, len(new_list) - 1))

5.4 总结

快速排序的最差时间复杂度为O(n^2),最优时间复杂度为O(nlogn) 即2的多少次方为n。是不稳定算法。

6. 二分查找

二分查找又称折半查找,即将搜索范围不断缩小一半,以此找到需要查询的目标元素。
二分查找要求为有序数列,且为顺序存储结构。

实现代码

def my_binary_search(my_list, item):
    mid = len(my_list) // 2

    # 递归终止条件
    if mid == 0:
        return False

    if my_list[mid] == item:
        return True
    if item > my_list[mid]:
        return my_binary_search(my_list[mid:], item)
    elif item < my_list[mid]:
        return my_binary_search(my_list[:mid], item)
    else:
        return False
  • 20
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值