选择排序、归并排序(分治法)、快速排序(分治法)、冒泡排序、sort以及比较、堆排序

1. 选择排序

  • 选择排序顾名思义就是每次都从剩下的元素中选择一个最小的放在待排序元素的第一位。算法中第一个for循环是为了遍历一遍元素,第二个for循环是为了找出第一个for循环的index之后最小的元素并将其和index+1的元素交换。

在这里插入图片描述
代码如下

def select_sort(origin_items):
    A = origin_items[:]  #使用切片赋值后改变A的元素origin_items中的元素不会改变。此时是
    					 #两个不同的列表
    for i in range(len(A) - 1):
        min_index = i
        for j in range(i + 1, len(A)):
            if A[min_index] > A[j]:
                min_index = j
        A[i], A[min_index] = A[min_index], A[i]
    return A

if __name__ == '__main__':
    A = [5, 3, 6, 5, 2, 7, 1, 99, 5]
    B = select_sort(A)
    print(B)

运行结果:
在这里插入图片描述

2. 归并排序(分治法)

  • 归并排序是先将待排序元素用merge_sort函数用’//2’的方法分割成最小的单元,然后使用merge函数 对其中的元素进行顺序归并。

在这里插入图片描述
代码如下

def merge_sort(item, left, right):
	if left < right:
		mid = (left+right) // 2
		merge_sort(item, left, mid)
		merge_sort(item, mid+1, right)
		position(item, left, mid, right)
	return item

def position(item, left, mid, right):
	tmp = []
	i = left
	j = mid + 1
	while i<= mid and j <= right:
		if item[i] < item[j]:
			tmp.append(item[i])
			i+= 1
		else:
			tmp.append(item[j])
			j += 1
	while i<= mid:
		tmp.append(item[i])
		i += 1
	while j <= right:
		tmp.append(item[j])
		j += 1
	item[left: right+1] = tmp

if __name__ == '__main__':
    A = [5, 2, 3, 6, 8, 1, 0, 99, 2]
    A = merge_sort(A, 0, len(A)-1)
    print(A)

运行结果:
在这里插入图片描述

3. 快速排序

  • 快速排序就是取一个中轴(这里选的元素是切片中的第一个元素),使用position函数将待排序元素左边的元素都小于等于中轴,右边的元素都大于中轴,使用_quick_sort调用partition并递归切片(所以也是分治法的思想)。总体就是将待排序元素先按1/2、1/4、1/8。。。切片,再排序使左边都小于右边,最终使整体元素有序。

在这里插入图片描述
代码如下

def quick_sort(A):
    items = A[:]
    _quick_sort(items, 0, len(items)-1)
    return items


def _quick_sort(item, left, right):
    if left < right:
        k = position(item, left, right)
        quick_sort(item, left, k-1)
        quick_sort(item, k+1, right)
    return item

## 这个快排是将最后一个元素当作基准,并且不移动基准直到最后
# def position(item, left, right):
#     i  = left - 1
#     for j in range(left, right):
#         if item[j] < item[right]:
#             i += 1
#             item[i], item[j] = item[j], item[i]
#     i += 1
#     item[i], item[right] = item[right], item[i]
#     return i

## 这个快排是以每一次排序的第一个元素作为基准,将基准拿出来,用填坑的方式交换元素
def position(item, left, right):
    tmp = item[left]
    while left < right:
        while left < right and item[right] >= tmp:
        # 这个是降序
        # while left < right and item[right] <= tmp:
            right -= 1
        item[left] = item[right]
        while left < right and item[left] <= tmp:
        # 这个是降序
        # while left < right and item[left] >= tmp:
            left += 1
        item[right] = item[left]
    item[left] = tmp
    return left

if __name__ == '__main__':
    A = [5, 2, 3, 6, 8, 1, 0, 99, 2]
    A = quick_sort(A)
    print(A)

运行结果:
在这里插入图片描述

4. 堆排序

堆排序就是使用列表的形式来表示一个完全二叉树,通过sift函数调整这个数,使得最大的数或者最小的数放在子树的根节点,然后将这个节点放到树的待排序的最后,循环就得到了有序

import random
def heap_sort(item):
    n = len(item)
    # 从最后一个有孩子节点的根节点开始循环调用调整函数,使所有的父节点都大于孩子节点,调整完后根节点就是最大的数,然后依次出数
    # 这个过程就是构造大根堆(构造小根堆在调整函数里改两个符号即可)
    for i in range(n//2-1, -1, -1):
        sift(item, i, n-1)
    # 将根节点出数,将最后一个节点放到根节点并开始一次调整,得到剩余堆里最大的元素
    for i in range(n-1, -1, -1):
        # 将根节点也就是最大的节点和最后一个节点换位置,这样不用再开辟一个新列表存储有序元素,是升序
        item[0], item[i] = item[i], item[0]
        sift(item, 0, i-1)
    return item


def sift(item, low, high):
    i = low
    # j是i的左孩子(如果有的话)
    j = 2 * i +1
    tmp = item[i]
    while j <= high:
        # 如果i有右孩子并且右孩子比左孩子的值大,就让j指向右孩子
        if j < high and item[j] < item[j+1]:
        # 构建小根堆(只需要改两个符号即可)
        # if j < high and item[j] > item[j+1]:
            j += 1
        # 如果孩子的值比父节点大就把孩子节点上升到父节点,最初的父节点在tmp里放着
        if tmp < item[j]:
        # 构建小根堆
        # if tmp > item[j]:
            item[i] = item[j]
            # 把刚刚较大的孩子节点当成新的父节点并重新开始循环
            i = j
            # j就是新的父节点的左孩子
            j = 2 * i + 1
        else:
            break
    # 将最开始的根节点放到相应的父节点(或叶子节点)
    item[i] = tmp


if __name__ == '__main__':
    A = []
    for i in range(100):
        A.append(random.randint(0, 1000))
    print(heap_sort(A))

运行结果:
在这里插入图片描述

- 比较:

from time import time
import random
import copy
import sys


sys.setrecursionlimit(10000000)


def bubble(A):
    for i in range(len(A)-1):
        for j in range(len(A)-i-1):
            if A[j] > A[j+1]:
                A[j], A[j+1] = A[j+1], A[j]
    return A


def select_sort(A):
    for i in range(len(A)-1):
        for j in range(i, len(A)):
            if A[j] < A[i]:
                A[i], A[j] = A[j], A[i]
    return A


# 这里换了另一种写法
def merge_sort(A):
    if len(A) < 2:
        return A[:]
    mid = len(A) // 2
    left = merge_sort(A[:mid])
    right = merge_sort(A[mid:])
    return merge(left, right)


def merge(item1, item2):
    index1, index2 = 0, 0
    item = []
    while index1 < len(item1) and index2 < len(item2):
        if item1[index1] < item2[index2]:
            item.append(item1[index1])
            index1 += 1
        else:
            item.append(item2[index2])
            index2 += 1
    item += item1[index1:]
    item += item2[index2:]
    return item


def quick_sort(A):
    item = A[:]
    _quick_sort(item, 0, len(item)-1)
    return item


def _quick_sort(item, start, end):
    if start < end:
        k = position(item, start, end)
        _quick_sort(item, start, k-1)
        _quick_sort(item, k+1, end)


# 这里换了另一种写法
def position(item, start, end):
    i = start - 1
    for j in range(start, end):
        if item[j] <= item[end]:
            i += 1
            item[i], item[j] = item[j], item[i]
    i += 1
    item[i], item[end] = item[end], item[i]
    return i

if __name__ == '__main__':
    A = [i for i in range(10000)]
    random.shuffle(A)
    B = copy.deepcopy(A)
    C = copy.deepcopy(A)
    D = copy.deepcopy(A)
    E = copy.deepcopy(A)
    print('待排序元素个数: %d' % len(A))
    start1 = time()
    A = select_sort(A) #选择排序
    end1 = time()
    merge_sort(B) #归并排序
    end2 = time()
    quick_sort(C) #快速排序
    end3 = time()
    D.sort()
    end4 = time()
    G = sorted(F)
    end5 = time()
    E = bubble(E)
    end6 = time()
    print('选择排序的时间为:%.18f' % (end1 - start1))
    print('归并排序的时间为:%.18f' % (end2 - end1))
    print('快速排序的时间为:%.18f' % (end3 - end2))
    print('sort排序的时间为:%.18f' % (end4 - end3))
    print('sorted排序的时间为:%.18f' % (end5 - end4))
    print('冒泡排序的时间为:%.18f' % (end6 - end5))
    print('运行总时间为:%.18f' % (end6 - start1))

运行结果:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190722224917846.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dibDMyMA==,size_16,color_FFFFFF,t_70
由图可知快速排序速度最快(sort是改进的归并排序和插入排序的组合)
A.sort() A自身排序
B = sorted(A) 将A的有序返回给B,A不变

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值