数据结构—排序算法(python实现)

数据结构

脑图

排序算法

稳定性,简单解释就是两个相同的值经过算法后是否依旧能保持前面的在前面,后面的在后面

1.冒泡排序

1.1步骤

复制代码
1.比较第一个与第二个,如果前者大则交换位置
2.推进,即比较第二个和第三个
3.重复上述步骤

这个数据就如同气泡一样,将大的往后移,小的往前推。用冒泡排序命名可以说是很形象了

1.2python代码实现冒泡:

python 复制代码
# 冒泡排序
def bubbles_sort(arr):
	# 循环列表长度
    for i in range(1, len(arr)):
    	# 对于每一个arr[j]与后一个arr[j+1]进行对比
        for j in range(0, len(arr)-i):
        	# 比较
            if arr[j] > arr[j+1]:
            	# 前者大则交换两者位置
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
    return arr

bubbles_sort([5,4,3,2,1])

1.3分析冒泡

时间复杂度:最坏情况:O(N**2)

      最好情况:O(N)

空间复杂度:O(1)

稳定

2.插入排序

2.1步骤

复制代码
1.将数组分为两个部分已经排序和未排序(初始认为第一个已经排序,后面的为未排序)
2.取未排序的第一个,与已排序的进行对比,并加入进已经排序的数组
3.重复第二步,直至未排序的为空

这个方式就如同打牌时摸牌一样,将牌堆中抽上来的牌与手牌进行对比,再决定插入哪个地方,最后继续抽牌。

2.2python代码实现插入排序:

python 复制代码
# 插入排序
def insertion_sort(arr):
    for i in range(1, len(arr)):
    	# 取值(抽牌)
        key = arr[i]
        j = i-1
        # 选择插入位置
        while j >= 0 and key < arr[j]:
            arr[j+1] = arr[j]
            j -= 1
        arr[j+1] = key
    return arr
insertion_sort([5,4,3,2,1])

2.3分析插入

时间复杂度:最坏情况下为O(N**2),此时待排序列为逆序,或者说接近逆序

      最好情况下为O(N),此时待排序列为升序,或者说接近升序。

空间复杂度:O(1)

稳定

3.选择排序

3.1步骤

复制代码
1.将数组分为两个部分已经排序和未排序(初始全部为未排序),
2.寻找未排序中的最小的值,并且与未排序中的第一个交换位置
3.重复2,直到未排序全部有序

可以发现,其中就是寻找最小值,放入有序的过程

3.2python代码实现:

python 复制代码
# 选择排序
def select_sort(arr):
	# 循环寻找最小值
    for i in range(len(arr)):
        min_index=0
        min=arr[i]
        for j in range (i+1,len(arr)):
            if arr[j]<min:
                min=arr[j]
                min_index=j
        # 如果位置不同则交换位置
        if min!=arr[i]:
            arr[i],arr[min_index]=arr[min_index],arr[i]
    return arr
    
arr = [23, 25, 12, 22, 11]
sorted_arr = select_sort(arr)

3.3分析选择

时间复杂度:最坏情况:O(N^2)

      最好情况:O(N^2)

空间复杂度:O(1)

不稳定

事实上我们也可以同时选出最大最小值放入两边

4.快速排序

这个有两种方法(其实都是一种思路,不同的实现方式)

4.1步骤

复制代码
方法1
1.令第一个数据为基准,并且利用两个指针l和r指向队首和队尾(如果只有一个数据则返回自己)
2.将r的数据与基准进行对比,如果大于基准则指向上一个数据,如果小于则与l进行交换
3.将l的数据与基准进行对比,如何小于基准则指向下一个数据,如果大于则与r进行交换
4.重复2和3,知道rhel指向同一个位置,这个位置就是基准的位置(此时左边的数全部小于基准,右边的数全部大于基准)
5.将左右两边的数列重复上述和此步骤,直到结束。

对于python,我们还有另一种方法

复制代码
方法2
1.令第一个数据为基准(如果只有一个数据则返回自己)
2.利用列表推导式,直接选出所有小于基准,等于基准,大于基准的数
3.将小于基准的,大于基准的重复上述和此步骤,直到全部返回

快速排序主要是选择基准,将左边全部为小的,右边全部为大的,从而进行对比,并且利用了递归的思想,将两边重复从而实现有序

4.2python代码实现:

方法1:

python 复制代码
def quick(arr):
	# 如果只有一个则无需排序
    if len(arr) <= 1:
        return arr
    # 选择基准
    base=arr[0]
    l=0
    r=len(arr)-1
    # 比较,交换数据
    while l<r:
        while l<r and arr[l]<base:
            l+=1
        while l<r and arr[r]>base:
            r-=1
        arr[l],arr[r]=arr[r],arr[l]
    # 将l和r重复时候的位置填入基准值
    arr[l],arr[0]=arr[0],arr[l]
    # 将左右递归
    return quick(arr[:l])+[arr[l]]+quick(arr[l+1:])
quick_sort([5,4,3,2,1])

方法2:

python 复制代码
def quick_sort(arr):
    if len(arr) <= 1:
        return arr
    pivot = arr[0]  
    # 选择小于基准的
    left = [x for x in arr if x < pivot]
    # 选择等于基准的
    middle = [x for x in arr if x == pivot]
    # 选择大于基准的
    right = [x for x in arr if x > pivot]
    # 递归
    return quick_sort(left) + middle + quick_sort(right)
quick_sort([5,4,3,2,1])

其实都是一个逻辑,将小的放左边,大的放右边

4.3分析快排

时间复杂度在最坏情况下是O(n^2)

平均情况O(n log n)

空间复杂度最坏情况下为O(n)

在平均情况下,是O(log n)。

5.希尔排序

5.1步骤

复制代码
1.按照步长分组,并且将这组通过插入变为有序
2. 减小步长,重复步骤1
3. 直到步长变为1,数组有序

5.2python代码实现:

python 复制代码
def shell_sort(arr):
    n = len(arr)
    gap = n // 2
    # 减小间隔进行排序
    while gap > 0:
        for i in range(gap, n):
            temp = arr[i]
            j = i
            # 插入排序
            while j >= gap and arr[j - gap] > temp:
                arr[j] = arr[j - gap]
                j -= gap
            arr[j] = temp
        gap //= 2

# 测试希尔排序
arr = [12, 34, 54, 2,6, 3,1]
shell_sort(arr)
print("排序后的数组:", arr)

5.3分析

时间复杂度平均:O(N^1.3)

空间复杂度:O(1)

不稳定

6.归并排序

6.1步骤

复制代码
1.分而治之,将一个数组按两个为一组进行分组,并让其有序
2.将两个有序数组之间两两组合,直到和为原来长度的大组

6.3python代码实现:

python 复制代码
def merge_sort(arr):
    if len(arr) > 1:
        mid = len(arr) // 2  # 找到中间位置
        L = arr[:mid]  # 分割数组为两部分
        R = arr[mid:]

        merge_sort(L)  # 对左半部分进行排序
        merge_sort(R)  # 对右半部分进行排序

        i = j = k = 0

        # 合并过程
        while i < len(L) and j < len(R):
            if L[i] < R[j]:
                arr[k] = L[i]
                i += 1
            else:
                arr[k] = R[j]
                j += 1
            k += 1

        # 检查是否有剩余元素
        while i < len(L):
            arr[k] = L[i]
            i += 1
            k += 1

        while j < len(R):
            arr[k] = R[j]
            j += 1
            k += 1
arr = [12, 11, 13, 5, 6, 7]
merge_sort(arr)
print( arr)

6.4分析

平均时间复杂度:O(nlogn)

最佳时间复杂度:O(n)

最差时间复杂度:O(nlogn)

空间复杂度:O(n)

排序方式:In-place

稳定性:稳定

相关推荐
懂点Tech15 小时前
ctfshow misc28:GIF 高度修改解题与脚本实现
开发语言·windows·python
comedate15 小时前
SMLib 的 Examples 导读:PyAPI / SM_API / SMLib 三组示例怎么读
python·cad·smlib·examples·sm_api
云和数据.ChenGuang15 小时前
Python 重写(Override)深度解析:从 MRO 到 super() 的完整机制
java·开发语言·人工智能·python·langchain·1024程序员节
川石课堂软件测试16 小时前
学习软件测试需掌握的一些知识
数据库·python·sql·功能测试·网络协议·mysql·http
万化冥合16 小时前
PyBox屏幕键盘如何辅助演示键盘操作?
python·计算机外设
车软学堂16 小时前
从测试转开发,到底要补什么
网络·人工智能·python·功能测试·单片机·车载系统·自动化
天空依然蔚蓝16 小时前
分享一个自动检测网站在线状态的python程序
python·运维开发·1024程序员节
路灯上の马陈17 小时前
二叉树的定义与性质
数据结构·二叉树·树结构·1024程序员节
岁月宁静17 小时前
一个 AI 项目从本地到上线,要经过哪些步骤?全流程讲清楚
python·docker·agent
codists18 小时前
《crafting interpreters》阅读笔记:p45-p45
python