第九章 排序

第九章 排序

标签(空格分隔): 数据结构


一、排序的问题和定义

对于同一集实际数据,完全可能存在很多种不同的但都有意义的序。

排序算法

内排序:在一个排序工作的执行过程中,待排序的记录全部保存在内存,这种工作就成为内排序;
外排序:针对外存(磁盘)数据的排序工作称为外排序。
排序工作要求数据集合存在一种可用的序。数据本身有自然的序,也可以给它造出一种序,最典型的方法就是设计一种hash函数,把数据集的元素映射到某个有序集,如整数集合的子集。
基于关键码比较,数据记录排序,比较之后调整数据记录的位置,可以确定两种最重要的基本操作:
①比较关键码的操作,通过这种操作确定数据的顺序关系。
②移动数据记录的操作,用于调整记录的位置和顺序。
n为数据长度,讨论在完成整个排序过程中执行上述两种操作的次数,以此作为评价算法效率的度量(时间复杂度)
理论研究的明确结论:基于关键码比较的排序问题,时间复杂度是O(n log(n))。也就是说,实现这一过程的任何算法都不可能优于O(n log(n))

  • 执行算法所需要的空间:对已有的序列排序,算法完成后被排序的序列依然存在。临时性辅助空间用过之后就释放了,但其大小需要考量。
  • 内存排序算法的空间需求,特别关注其空间复杂度是否常量。常量的空间开销意味着排序工作可以在原序列里完成,只需要用几个简单变量作为操作中的临时存储。原地排序算法。
    稳定性:稳定的算法能够维持序列中所有排序码相同记录的相对位置。
    适应性:如果一个排序算法对接近有序的序列工作更快,那么就有适应性。
    常见的分类方法:插入、选择、交换、分配、归并、外部排序

简单排序算法

共同特点是简答并且最坏情况的复杂度高

插入排序

# 插入排序
def insert_sort(lst):
    for i in range(1, len(lst)):
        x = lst[i]
        j = i
        while j > 0 and lst[j - 1].key > x.key:
            lst[j] = lst[j - 1]
            j -= 1
        lst[j] = x

简单的插入排序:最坏情况下O(n^2),算法稳定。
经常被用于高级排序算法,作为其中一部分。希尔排序,shell排序,采用一种变动间隔的排序技术,其中用简单插入排序作为基础算法,可以得到更高的操作效率。
采用切分待排序序列(例如快速和归并排序),切分得到的序列很短时,就转到简单的插入排序算法。python语言的内置排序算法就是如此—–切分待排序!

选择排序

def select_sort(lst):
    for i in range(len(lst) - 1):  # 确定范围,至倒数2
        k = i
        for j in range(i, len(lst)):
            if lst[j].key < lst[k].key:  # 取i位置后的min
                k = j
        if i != k:  # 最小值不是首元素时
            lst[i], lst[k] = lst[k], lst[i]

冒泡排序

def bubble_sort(lst):
    for i in range(len(lst)):
        found = False
        for j in range(1, len(lst) - i):
            if lst[j - 1].key > lst[j].key:
                lst[j - 1], lst[j] = lst[j], lst[j - 1]
                found = True
        if not found:
            break

归并排序

    def merge(from_lst, to_lst, low, m, high):
    i, j, k = low, m, low
    while i < m and j < high:  # 反复复制两段首记录中较小的
        if from_lst[i].key <= from_lst[j].key:
            to_lst[k] = from_lst[i]
            i += 1
        else:
            to_lst[k] = from_lst[j]
            j += 1
        k += 1
    while i < m:  # 复制第一段剩余记录
        to_lst[k] = from_lst[i]
        i += 1
        k += 1
    while j < high:  # 复制第二段剩余记录
        to_lst[k] = from_lst[j]
        j += 1
        k += 1
    def merge_pass(from_lst, to_lst, llen, slen):
        i = 0
        while i + 2 * slen < llen:  # 归并长len的两段
            merge(from_lst, to_lst, i, i + slen, i + 2 * slen)
            i += 2 * slen
        if i + slen < llen:  # 剩下两段,后段长度小于 slen
            merge(from_lst, to_lst, i, i + slen, llen)
        else:  # 只剩下一段,复制到数组to
            for j in range(i, llen):
                to_lst[j] = from_lst[j]
    def merge_sort(lst):
        slen, llen = 1, len(lst)
        templst = [None] * llen
        while slen < llen:
            merge_pass(lst, templst, llen, slen)
            slen *= 2
            merge_pass(templst, lst, llen, slen)  # 结果存回原位
            slen *= 2

本章小结

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值