数据结构与算法之《排序算法》

排序算法

一种能将一串数据依照特定顺序进行排列的算法。排序算法在排序后能位置相等键值得原有秩序则称算法稳定。

1.冒泡排序——稳定

冒泡排序(Bubble Sort)算法重复遍历待排序序列,每次比较两个元素,如果它们的顺序错误就将它们进行交换。重复进行此过程,直到没有需要交换再的元素。之所以叫冒泡排序是因为随着排序算法的进行,较大元素会像一个个水中的气泡一样浮向序列末端。
算法具体流程(以开始左端,按升序排列为例):

  • 从左端第一个元素开始,比较相邻元素大小,若第一个元素大于第二个元素就交换他们
  • 对序列中的每一对元素重复上一步的工作,从第一对直到到最后一对,做完这一步最大元素会是序列最右端的元素,此时完成一次交换过程
  • 按上述步骤,每一次交换过程会完成一个数的排序,重复n-1次交换过程即可完成整个排序
    排序算法图解分析(一次交换过程):
    在这里插入图片描述
def bubble_sort(alist):   # 最坏时间复杂度:O(n^2)   最优时间复杂度:O(n)
	"""冒泡排序"""				
	for j in range(0,len(alist)-1):
		# 一次交换过程
		exchange = False
		for i in range(0,len(alist)-1-j):  
			if alist[i] > alist[i+1]:  # 如果前一个元素大于后一个元素就交换他们,否则什么也不做
				alist[i],alist[i+1] = alist[i+1],alist[i]
				exchange = True
		if exchange is False:	# 优化:如果遍历过程没有发生交换则序列已经有序,退出排序算法
			break
2.选择排序——不稳定

选择排序(Selection Sort),首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。然后,再从剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾。以此类推,直到所有元素排序完毕。
排序过程图解(以升序,选择最大值为例):
在这里插入图片描述

def select_sort(alist):
	"""选择排序"""
	n = len(alist)
	for j in range(n-1,0,-1):
		max_index = j
		for i in range(0,j): 	# i [0,1,...,n-2]
			if alist[max_index] < alist[i]:
				max_index = i
		alist[max_index],alist[j] = alist[j],alist[max_index]
3.插入排序——稳定

插入排序(Insert Sort),通过构建有序序列,对于未排序数据,在已排序数据中从后向前扫描,找到相应的插入位置并插入。
在这里插入图片描述

#---------------------插入排序实现-----------------------#
def insert_sort(alist):   # 最坏时间复杂度:O(n^2)   最优时间复杂度:O(n)
    """插入排序"""
    n = len(alist)
    for i in range(1,n):
        while i>0:
            if alist[i] < alist[i-1]:
                alist[i],alist[i-1] = alist[i-1],alist[i]
                i -= 1
            else:
                break
4.希尔排序

希尔排序(Shell Sort)是插入排序的一种,其排序的基本思想是将数组列在一个表中,并对列分别进行插入排序,重复这个过程,但每次用更长的列来进行。最后整个表就只有一列。将数组转换至表是为了更好的理解这一算法,算法本身还是使用数组进行排序。
希尔排序示意图:
在这里插入图片描述

#---------------------希尔排序实现-------------------------#
def shell_sort(alist):    # 最坏时间复杂度:O(n^2)  最优时间复杂度:由
    """希尔排序"""
    n = len(alist)
    gap = n // 2   # 此处gap采用折半方式
    while gap > 0:
        for i in range(gap,n):
            while i >= gap:
                if alist[i] < alist[i-gap]:
                    alist[i],alist[i-gap] = alist[i-gap],alist[i]
                    i -= gap
                else:
                    break
        gap //= 2
5.快速排序——不稳定

快速排序(Qucik Sort)又称划分交换排序,通过一趟排序将序列数据分割为独立的两部分,其中一部分的所有数据都比另一部分的数据要小,然后再按此方法对这两部分数据分别进行快速排序,整个过程可以递归进行,以此达到整个数据变成有序序列。
步骤:(以升序排列,基准值为左边第一个元素为例)

  • 选取序列第一个元素为基准值(mid_value)
  • 定义两个游标分别为序列第一个元素索引(low)和最后一个元素索引(high),从high游标开始比较与基准值得关系,若high游标的元素大于等于基准值则游标向前移动一步,直到不符合前述条件就将high游标的元素赋值给low游标,然后将low游标的元素与基准值比较,若low游标的元素小于基准值,则将游标向后移动一步,直到不符合前述条件就将low游标的元素赋值给high游标,然后再比较high游标,如此往复直到两个游标重合,重合之处便是基准值在序列中的最后位置,此时基准值左侧的元素比基准值小,右侧元素比基准值大或相等。
  • 递归的将小于基准值的子序列和大于基准值的子序列进行排序。当递归的子序列长度为1时便可结束递归。
    具体实现代码如下:
#----------------------快速排序实现----------------------#
def quick_sort(alist,start,end):  # 最坏时间复杂度:O(n^2)  最优时间复杂度:O(nlogn)
    """快速排序"""
    
    if start >= end:
        return
    low = start
    high = end
    mid_value = alist[start]
    
    while low < high:
        while low < high and alist[high] >= mid_value:
            high -= 1
        alist[low] = alist[high]
        
        while low < high and alist[low] < mid_value:
            low += 1
        alist[high] = alist[low]
        
    alist[low] = mid_value

    quick_sort(alist,start,low-1)
    quick_sort(alist,low+1,end)
6.归并排序——稳定

归并排序的思想是先递归分解序列,再合并序列。将序列分解到最小也就是只有一个元素时,合并两个有序序列。合并的基本思路是比较两个数组的最前面的数,谁小就先取谁,取了后相应的位置往后移动一步,然后再比较,直到一个序列为空,最后把另一个序列的全部剩余元素直接追加到后面。
具体实现代码如下:(图片为递归过程函数调用示意图)
在这里插入图片描述

#----------------------归并排序实现--------------------------#
def merge_sort(alist):	# 最坏时间复杂度=最优时间复杂度:O(nlogn)
    """归并排序"""
    if len(alist) == 1:
        return alist
    
    n = len(alist)
    num = n // 2
    left = merge_sort(alist[:num])
    right = merge_sort(alist[num:])
    
    return merge(left,right)

def merge(left,right):
    """合并序列"""
    result = []
    l_index,r_index = 0,0
    
    while l_index < len(left) and r_index < len(right):
        if left[l_index] <= right[r_index]:
            result.append(left[l_index])
            l_index += 1
        else:
            result.append(right[r_index])
            r_index += 1
    result.extend(left[l_index:])
    result.extend(right[r_index:])
    
    return result
排序算法效率比较

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值