《计算之魂》Task3:关于排序的讨论

发布于:2022-12-31 ⋅ 阅读:(252) ⋅ 点赞:(0)

在这里插入图片描述

1. 排序

所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减排列起来的操作。排序是计算机内经常进行的一种操作,其目的是将一组无序的记录序列调整为有序的记录序列。


1.1 评价指标

  • 时间复杂度
  • 空间复杂度
  • 使用场景:针对实际对节省时间和空间的不同需求,选择适用于不同场景的排序算法
  • 稳定性:稳定的算法在排序过程中不会改变元素彼此之间次序

1.2 不同排序算法O(n)分类

排序算法 平均时间复杂度度 最坏时间复杂度 额外空间复杂度 稳定性
选择排序 O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1) 稳定
插入排序 O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1) 稳定
归并排序 O ( n ∗ log ⁡ n ) O(n*\log n) O(nlogn) O ( n ∗ log ⁡ n ) O(n*\log n) O(nlogn) O ( n ) O(n) O(n) 稳定
堆排序 O ( n ∗ log ⁡ n ) O(n*\log n) O(nlogn) O ( n ∗ log ⁡ n ) O(n*\log n) O(nlogn) O ( 1 ) O(1) O(1) 不稳定
快速排序 O ( n ∗ log ⁡ n ) O(n*\log n) O(nlogn) O ( n 2 ) O(n^2) O(n2) O ( log ⁡ n ) O(\log n) O(logn) 不稳定

2. 算法介绍

2.1 选择排序

在这里插入图片描述
python 实现


def selection_sort(num_list):
    length = len(num_list)
    if length <= 1:
        return num_list

    for j in range(length):
        # 假设第一个元素为最小元素
        min_num_index = j
        
        # 遍历未排序区域元素,以此和未排序区域的第一个元素做对比
        for i in range(j+1, length):
            if num_list[i] < num_list[min_num_index]:
                min_num_index = i
         
        # 交换位置
        num_list[min_num_index], num_list[j] = num_list[j], num_list[min_num_index]

    return num_list

2.2 插入排序

在这里插入图片描述
python 实现

def insertion_sort(ls):
    for i in range(0,len(ls)):
        current_index = i
        while ls[current_index - 1] > ls[current_index] and current_index - 1 >= 0:
            ls[current_index] , ls[current_index - 1] = ls[current_index - 1] , ls[current_index]
            current_index -= 1
    return ls

2.3 归并排序

在这里插入图片描述
python 实现

# 1.将整个数组对半分开,直到只剩一个元素
 # 2.从一个元素开始往回进行对比合并,将合并的内容暂且放在一个空列表中
 # 定义合并merge函数
def merge(L,R):
    # 将两个排过序的两个列表进行合并并排序
    # 分别用于限定L、R的数据减少情况
    i, j = 0,0
    # 用于存放L与R的合并内容
    res = []
    while i < len(L) and j < len(R):
        # 如果左边的数大于右边的数,就将左边的数先添加到res中,再继续比较(合并的R、L已经排过序)
        # 如果如果右边的数大于左边的数,就将右边的数先添加到res中,再继续比较(合并的R、L已经排过序)
        if L[i] <= R[j]:
            res.append(L[i])
            i += 1
        else:
            res.append(R[j])
            j += 1
    # 因为当 i == len(L) 或者 j == len(R)时,跳出while循环,且每次循环只处理一个列表里的内容,所以其中有一个列表内容会先全部加入res中,另一个列表还剩内容未加进res中。
    # 对未处理完的列表,直接加入res中
    res += R[j:] if i == len(L) else L[i:]
    return res

 # 定义排序merge_sort函数
def merge_sort(List):
    length = len(List)
    if length <= 1:
        return List
    else:
        mid = length//2
        left = merge_sort(List[:mid])
        right = merge_sort(List[mid:])
        return merge(left,right)

参考资料:归并排序(Python代码)


2.4 堆排序

演示动画
原理及代码可参考python实现堆排序


2.5 快速排序

在这里插入图片描述

演示动画

python 代码

def quicksort(array):
	if len(array) < 2:
		return array
	else:
		pivot = array[0]
		less = [i for i in array[1:] if i <= pivot]
		greater = [i for i in array[1:] if i >= pivot]
		return quicksort(less) + [pivot] + quicksort(greater)

3. 思考题

思考题1.4.1 赛跑问题(GS)

假定有25名短跑选手比赛争夺前三名,赛场上有五条赛道,一次可以有五名选手同时比赛。比赛并不计时,只看相应的名次。假设选手的发挥是稳定的,也就是说如果约翰比张三跑得快,张三比凯利跑得快,约翰一定比凯利跑得快。最少需要几次比赛才能决出前三名?(在第6章给出了这一问题的解答。(难度系数3颗星))

答:参考了计算之魂第6章给出了的解答。

  1. 先进行五组比赛,决出各组名次。并令各组第一分别为A1B1C1D1E1
A组 B组 C组 D组 E组
A1 B1 C1 D1 E1
A2 B2 C2 D2 E2
A3 B3 C3 D3 E3
A4 B4 C4 D4 E4
A5 B5 C5 D5 E5
  1. 第六组比赛:各组第一 A1B1C1D1E1 分别进行一次比赛。假设名次为 A1B1C1D1E1 。则整体第一名为A1
  2. 第七组比赛:如下表,整体第二名必出现在 A2B1之间;整体第三名必出现在 A2B1A3B2C1 之间。
    A2B1A3B2C1 之间进行第七组比赛,第一名为整体第二名,第二名为整体第三名。
A组 B组 C组 D组 E组
B1 C1 D1 E1
A2 B2 C2 D2 E2
A3 B3 C3 D3 E3
A4 B4 C4 D4 E4
A5 B5 C5 D5 E5

思考题1.4.2 区间排序

如果有N个区间[l1,r1],[l2,r2],…,[lN,rN],只要满足下面的条件我们就说这些区间是有序的:存在xi∈[li,ri],其中i=1,2,…,N。
比如,[1, 4]、[2, 3]和[1.5, 2.5]是有序的,因为我们可以从这三个区间中选择1.1、2.1和2.2三个数。同时[2, 3]、[1, 4]和[1.5, 2.5]也是有序的,因为我们可以选择2.1、2.2和2.4。但是[1, 2]、[2.7, 3.5]和[1.5, 2.5]不是有序的。
对于任意一组区间,如何将它们进行排序?(难度系数3颗星)

答:该题解答参考了博客《计算之魂》思考题1.4 - Q2,内容如下:

  1. 按照右端点排序;
  2. 将右端点最大的区间作为头区间,讨论剩余 n -1 个区间的情况;
  3. 对剩余的 n - 1 个区间按照步骤二重复,直至仅剩 4 个区间为止(也就是右端点最小的四个区间);
  4. 如果第 4 个区间不能和第 3 个区间交换,则按照上图可以得到前三个区间的情况,并递归地讨论第 4 个区间与第 5 个区间是否能交换,直至递归到最后一个区间,算法终止;
  5. 如果能交换,则将第 3 个区间作为最大的区间,并可以得到 N1、N2、N4(按照右端点的相对大小排序)这三个区间的情况,并归位;
  6. 讨论第 4 个区间能否与第 2 个区间交换,不能的话则返回步骤 4;
  7. 能的话则返回步骤 5,直至讨论到第 4 个区间与第 1 个区间是否能交换,并返回步骤4。
本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到