数据结构与算法 排序算法-快速排序

「快速排序 Quick Sort」是一种基于分治思想的排序算法,运行高效,应用广泛。

快速排序的核心操作是「哨兵划分」,其目标是:选择数组中的某个元素作为“基准数”,将所有小于基准数的元素移到其左侧,而大于基准数的元素移到其右侧。具体来说,哨兵划分的流程为:

  1. 选取数组最左端元素作为基准数,初始化两个指针 ij 分别指向数组的两端;
  2. 设置一个循环,在每轮中使用 ij)分别寻找第一个比基准数大(小)的元素,然后交换这两个元素;
  3. 循环执行步骤 2. ,直到 ij 相遇时停止,最后将基准数交换至两个子数组的分界线;
阅读更多

数据结构与算法 排序算法-插入排序

「插入排序 Insertion Sort」是一种简单的排序算法,它的工作原理与手动整理一副牌的过程非常相似。

具体来说,我们在未排序区间选择一个基准元素,将该元素与其左侧已排序区间的元素逐一比较大小,并将该元素插入到正确的位置。

回忆数组的元素插入操作,设基准元素为 base ,我们需要将从目标索引到 base 之间的所有元素向右移动一位,然后再将 base 赋值给目标索引。

单次插入操作

阅读更多

数据结构与算法 排序算法-选择排序

「选择排序 Selection Sort」的工作原理非常直接:开启一个循环,每轮从未排序区间选择最小的元素,将其放到已排序区间的末尾。

设数组的长度为 n ,选择排序的算法流程如下:

  1. 初始状态下,所有元素未排序,即未排序(索引)区间为 [0, n-1] 。
  2. 选取区间 [0, n-1] 中的最小元素,将其与索引 0 处元素交换。完成后,数组前 1 个元素已排序。
  3. 选取区间 [1, n-1] 中的最小元素,将其与索引 1 处元素交换。完成后,数组前 2 个元素已排序。
  4. 以此类推。经过 n - 1 轮选择与交换后,数组前 n - 1 个元素已排序。
  5. 仅剩的一个元素必定是最大元素,无需排序,因此数组排序完成。
阅读更多

算法与数据结构 排序算法

常见的排序算法

  • 选择排序是一种基于比较的排序算法,其基本思想是在每个回合中从未排序部分找出最小(或最大)元素,将其与已排序部分的末尾进行交换,以此类推,直至整个序列有序。该算法具有简单直观的特点,但时间复杂度较高,为O(n²),且不具备稳定性。

  • 冒泡排序通过交换相邻元素来实现排序。通过添加一个标志位来实现提前返回,我们可以将冒泡排序的最佳时间复杂度优化到 O(n) 。

  • 插入排序每轮将未排序区间内的元素插入到已排序区间的正确位置,从而完成排序。虽然插入排序的时间复杂度为 O(n²) ,但由于单元操作相对较少,它在小数据量的排序任务中非常受欢迎。

阅读更多

数据结构与算法 排序算法-冒泡排序

「冒泡排序 Bubble Sort」通过连续地比较与交换相邻元素实现排序。这个过程就像气泡从底部升到顶部一样,因此得名冒泡排序。

我们可以利用元素交换操作模拟上述过程:从数组最左端开始向右遍历,依次比较相邻元素大小,如果“左元素 > 右元素”就交换它俩。遍历完成后,最大的元素会被移动到数组的最右端。

1
利用元素交换操作模拟冒泡

2
bubble_operation_step2

阅读更多

数据结构与算法 非线性数据结构-红黑树 RBT

基于BST存在的问题,一种新的树——平衡二叉查找树(Balanced BST)产生了。平衡树在插入和删除的时候,会通过旋转操作将高度保持在logN。其中两款具有代表性的平衡树分别为AVL树和红黑树。AVL树由于实现比较复杂,而且插入和删除性能差,在实际环境下的应用不如红黑树。

红黑树(Red-Black Tree,以下简称RBTree)的实际应用非常广泛,比如Linux内核中的完全公平调度器、高精度计时器、ext3文件系统等等,各种语言的函数库如Java的TreeMap和TreeSet,C++ STL的map、multimap、multiset等。

RBTree也是函数式语言中最常用的持久数据结构之一,在计算几何中也有重要作用。值得一提的是,Java 8中HashMap的实现也因为用RBTree取代链表,性能有所提升。

阅读更多

数据结构与算法 非线性数据结构-二叉树

「二叉树 Binary Tree」是一种非线性数据结构,代表着祖先与后代之间的派生关系,体现着“一分为二”的分治逻辑。与链表类似,二叉树的基本单元是节点,每个节点包含一个「值」和两个「指针」。

节点的两个指针分别指向「左子节点」和「右子节点」,同时该节点被称为这两个子节点的「父节点」。当给定一个二叉树的节点时,我们将该节点的左子节点及其以下节点形成的树称为该节点的「左子树」,同理可得「右子树」。

在二叉树中,除叶节点外,其他所有节点都包含子节点和非空子树。例如,在以下示例中,若将“节点 2”视为父节点,则其左子节点和右子节点分别是“节点 4”和“节点 5”,左子树是“节点 4 及其以下节点形成的树”,右子树是“节点 5 及其以下节点形成的树”。

阅读更多