排序算法(2)

文章目录

概要

接上回

在上篇说过经典的排序算法,有冒泡,插入,选择;归并,快排。其中讲了冒泡,插入,选择;这一回写归并和快排。

原理及实现

原理是很好玩的,如果不喜欢,先记住,总有一天会用得上的。

原理挺有意思的,喜欢就去研究,不喜欢就记住一些常用的,以备不时之需。先聊聊归并吧。

归并排序

本来想找个定义,看了下维基百科,也不是很满意的概念,如下:

定义

归并排序(英语:Merge sort,或mergesort),是建立在归并操作上的一种有效的排序算法,效率为𝑂(𝑛log𝑛)(大O符号)。1945年由约翰·冯·诺伊曼首次提出。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同时进行。

定义是这样的,怎么理解呢?采用分治递归,意思就是先平均分成2份,然后比较排序;递归这种操作,就是将2份中任何一份继续采用分治法(分治法这里不细聊,以后会写文章的),分成2份,直到不能再分为止;

性能

  1. 归并排序是稳定的排序算法;数组长度就那么长,一直在分割,然后继续分割直到不能再分,然后采用合并数组;
  2. 时间复杂度:O(nlogn)
  3. 空间复杂度:O(nlogn)

代码Python

python 复制代码
dfrom typing import List


def merge_sort(a: List[int]):
    merge_sort_between(a, 0, len(a) - 1)


def merge_sort_between(a: List[int], low: int, high: int):
    # The indices are inclusive for both low and high.
    if low < high:
        mid = low + (high - low) // 2
        merge_sort_between(a, low, mid)
        merge_sort_between(a, mid + 1, high)
        merge(a, low, mid, high)


def merge(a: List[int], low: int, mid: int, high: int):
    # a[low:mid], a[mid+1, high] are sorted.
    i, j = low, mid + 1
    tmp = []
    while i <= mid and j <= high:
        if a[i] <= a[j]:
            tmp.append(a[i])
            i += 1
        else:
            tmp.append(a[j])
            j += 1
    start = i if i <= mid else j
    end = mid if i <= mid else high
    tmp.extend(a[start:end + 1])
    a[low:high + 1] = tmp

快速排序

归并说完了,来看看快排。定义如下:

定义

快速排序(英语:Quicksort),又称分区交换排序(partition-exchange sort),是一种排序算法,最早由东尼·霍尔提出。在平均状况下,排序𝑛个项目要𝑂(𝑛log𝑛)(大O符号)次比较。在最坏状况下则需要𝑂( n 2 n^2 n2)次比较,但这种状况并不常见。事实上,快速排序Θ(𝑛log𝑛)通常明显比其他算法更快,因为它的内部循环可以在大部分的架构上很有效率地达成。

按照定义,对一定长度的数据,选一个基准值,然后所有数据一个一个跟基准值比较,然后交互i,j的位置。还是分治和递归的思想,一直这么分,partion。

接下来看看代码,如下:

代码

python 复制代码
from typing import List
import random


def quick_sort(a: List[int]):
    quick_sort_between(a, 0, len(a) - 1)


def quick_sort_between(a: List[int], low: int, high: int):
    if low < high:
        # get a random position as the pivot
        k = random.randint(low, high)
        a[low], a[k] = a[k], a[low]

        m = partition(a, low, high)  # a[m] is in final position
        quick_sort_between(a, low, m - 1)
        quick_sort_between(a, m + 1, high)


def partition(a: List[int], low: int, high: int):
    pivot, j = a[low], low
    for i in range(low + 1, high + 1):
        if a[i] <= pivot:
            j += 1
            a[j], a[i] = a[i], a[j]  # swap
    a[low], a[j] = a[j], a[low]
    return j

小结

学习总结

归并,排序都采用了分治的思想。时间复杂度归并O(nlogn),空间复杂度归并的比较大,达到O(n);快排时间复杂度O(nlogn),快排极端情况达到O( n 2 n^2 n2),但是概率很小,而且可以通过合理的选用基准值来避免,适用范围较广。

相关推荐
小刘|3 分钟前
《Java 实现希尔排序:原理剖析与代码详解》
java·算法·排序算法
jjyangyou8 分钟前
物联网核心安全系列——物联网安全需求
物联网·算法·安全·嵌入式·产品经理·硬件·产品设计
van叶~25 分钟前
算法妙妙屋-------1.递归的深邃回响:二叉树的奇妙剪枝
c++·算法
简简单单做算法26 分钟前
基于Retinex算法的图像去雾matlab仿真
算法·matlab·图像去雾·retinex
云卓SKYDROID40 分钟前
除草机器人算法以及技术详解!
算法·机器人·科普·高科技·云卓科技·算法技术
半盏茶香1 小时前
【C语言】分支和循环详解(下)猜数字游戏
c语言·开发语言·c++·算法·游戏
徐子童1 小时前
双指针算法习题解答
算法
想要打 Acm 的小周同学呀1 小时前
LRU缓存算法
java·算法·缓存
劲夫学编程2 小时前
leetcode:杨辉三角
算法·leetcode·职场和发展
毕竟秋山澪2 小时前
孤岛的总面积(Dfs C#
算法·深度优先