python实例二(排序算法)


注意:本文所有排序实现均默认升序,若需要降序排序,定义函数的时候增加一个参数order,order>0升序,order<0降序即可

一、冒泡排序

原理:
冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。

步骤:
1.比较相邻的元素。如果第一个比第二个大,则交换;
2.对第0个到第n-1个数据做同样的工作。这时,最大的数就“浮”到了数列最后的位置上;
3.针对所有的元素重复以上的步骤,除了最后一个;
4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

代码:

def bubble_sort(arr):
    n = len(arr)                   # 获得数列的长度
    for i in range(n):           # 遍历所有数列元素
       sign = True                # 标记
        for j in range(0, n-i-1):     # 每轮找到最大数值
            if  arr[j] > arr[j+1] :       # 如果前者比后者大
                arr[j],arr[j+1] = arr[j+1], arr[j]      # 则交换两者
               sign = False
        # 某一次遍历如果没有数据交换,则说明已经排好序了,break 即可
        if sign:
            break                  # return arr[]
    return arr

实例:

if __name__ == '__main__':
    test_list = []
    while len(test_list) < 10:       # 范围内随机取10个数值
        test_list.append(randrange(0, 101, 3))
    shuffle(test_list)                   # 打乱数列
    print('排序前的数列:', test_list)
    sorted_list = bubble_sort(test_list)
    print('排序后的数列:', sorted_list)

在这里插入图片描述

二、选择排序

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

步骤:
1.在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
2.再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
3.以此类推,直到所有元素均排序完毕。

代码:

def select_sort(arr):
    n = len(arr)
    for i in range(n):
        min = i                             # 标记最小元素
        for j in range(i+1,n):
            if arr[j] < arr[min] :
                min = j                     # 找到最小值的下标
                arr[min],arr[i] = arr[i],arr[min]    # 交换两者
    return arr

三、插入排序

原理
插入排序(Insertion Sort)是一种简单直观的排序算法。通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

步骤:
1.从第一个元素开始,该元素可以认为已经被排序
2.取出下一个元素,在已经排序的元素序列中从后向前扫描
3.如果被扫描的元素(已排序)大于新元素,将该元素后移一位
4.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
5.将新元素插入到该位置后
6.重复步骤2~5

代码:

def insert_sort(arr):
	n = len(arr)
	for i in range(1, n):
		sign = arr[i]    # 注: 将arr[i]赋值为sign,不能直接用arr[i]
		j = i - 1
		while j >= 0 and arr[j] > sign:
			arr[j+1] = arr[j]
			j -= 1
		arr[j+1] = sign
	return arr

四、快速排序

原理:
快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为较小和较大的2个子序列,然后递归地排序两个子序列。

步骤:
1.从数列中挑出一个元素作为基准数。
2.分区过程,将比基准数大的放到右边,小于或等于它的数都放到左边。
3.再对左右区间递归执行第二步,递归到最底部的判断条件是数列的大小是零或一,此时该数列显然已经有序。

代码:

def quick_sort(arr):
    return qsort(arr, 0, len(arr) - 1)

def qsort(arr, start, end):
    if start < end:
        left = start
        right = end
        base = arr[start]
    else:
        return arr
    while left < right:
        while left < right and arr[right] >= base:
            right -= 1
        if left < right:  # 说明打破while循环的原因是arr[right] <= base
            arr[left] = arr[right]
            left += 1
        while left < right and arr[left] < base:
            left += 1
        if left < right:  # 说明打破while循环的原因是arr[left] >= base
            arr[right] = arr[left]
            right -= 1
    arr[left] = base  # 此时,left=right,用base来填坑

    qsort(arr, start, left - 1)
    qsort(arr, left + 1, end)
    return arr

递归优化
分析2:
1.先从待排序的数组中找出一个数作为基准数(取第一个数即可),
2.然后将原来的数组划分成两部分:小于基准数的左子数组和大于等于基准数的右子数组。
3.然后对这两个子数再递归重复上述过程,直到两个子数组的所有数都分别有序。
4.最后返回“左子数组” + “基准数” + “右子数组”,即是最终排序好的数组。

代码2:

def quick_sort(arr):
    if len(arr) <= 1:
        return arr

    # 左子数组
    left = []
    # 右子数组
    right = []
    # 基准数
    base = arr.pop()

    # 对原数组进行划分
    for x in arr:
        if x < base:
            left.append(x)
        else:
            right.append(x)

    # 递归调用
    return quick_sort(left) + [base] + quicksort(right)

五、希尔排序

原理:
先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录"基本有序"时,再对全体记录进行依次直接插入排序。

步骤:
1.先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)
2.分别进行直接插入排序,
3.然后依次缩减增量再进行排序,
4.待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。
5,因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的

代码:

def shell_sort(arr):
    n = len(arr)
    gap = round(n / 2)   # 初始间隔,用round()得到四舍五入值
    while gap >= 1:
        for i in range(gap, n):   
            temp = arr[i]
            j = i
            while j - gap >= 0 and arr[j - gap] > temp:  # 到这里与插入排序一样了
                arr[j] = arr[j - gap]
                j -= gap
            arr[j] = temp
        gap = round(gap / 2)
    return arr

六、堆排序

原理:
堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。

步骤:
1.构造最大堆(Build_Max_Heap):若数组下标范围为0~n,考虑到单独一个元素是大根堆,
则从下标n/2开始的元素均为大根堆。于是只要从n/2-1开始,向前依次构造大根堆,
这样就能保证,构造到某个节点时,它的左右子树都已经是大根堆。

2.由于堆是用数组模拟的。得到一个大根堆后,数组内部并不是有序的。因此需要将堆化数组有序化。思想是移除根节点,并做最大堆调整的递归运算。
(1).第一次将heap[0]与heap[n-1]交换,再对heap[0…n-2]做最大堆调整。
(2).第二次将heap[0]与heap[n-2]交换,再对heap[0…n-3]做最大堆调整。
(3).重复1~2操作直至heap[0]和heap[1]交换。
(4).由于每次都是将最大的数并入到后面的有序区间,故操作完后整个数组就是有序的了。

3.最大堆调整(Max_Heapify):该方法是提供给上述两个过程调用的。
目的是将堆的末端子节点作调整,使得子节点永远小于父节点 。

代码:

def heap_sort(arr):
	n = len(arr)
	first = int(n/2-1)    # 最后一个非叶子节点
	for start in range(first,-1,-1):    # 构建最大堆
		max_heapify(arr,start,n-1)
	for end in range(n-1,0,-1):    # 堆排,将最大根堆转换成有序数组
		arr[end],arr[0] = arr[0], arr[end]    # 将根节点元素与最后叶子节点进行互换,取出最大根节点元素,对剩余节点重新构建最大堆
		max_heapify(arr,0,end-1)    # 因为end上面取的是n-1,故而这里直接放end-1,相当于忽略了最后最大根节点元素arr[n-1]
	return arr

# 最大堆调整:将堆的末端子节点作调整,使得子节点永远小于父节点
# start为当前需要调整最大堆的位置,end为调整边界
def max_heapify(arr,start,end):
	root = start
	while True:
		child = root * 2 + 1    # 调整节点的子节点
		if child > end:
			break
		if child + 1 <= end and arr[child] < arr[child+1]:
			child = child + 1   # 取较大的子节点
		if arr[root] < arr[child]:    # 较大的子节点成为父节点
			arr[root], arr[child] = arr[child], arr[root]    # 交换
			root = child
		else:
			break
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值