mirror of
https://github.com/krahets/hello-algo.git
synced 2024-12-25 10:16:29 +08:00
Add build script for Swift.
This commit is contained in:
parent
05f0054005
commit
38751cc5f5
25 changed files with 128 additions and 1223 deletions
|
@ -12,8 +12,8 @@ func swap(nums: inout [Int], i: Int, j: Int) {
|
|||
}
|
||||
|
||||
/* 快速排序类 */
|
||||
// 快速排序类-哨兵划分
|
||||
func quickSortPartition(nums: inout [Int], left: Int, right: Int) -> Int {
|
||||
/* 哨兵划分 */
|
||||
func partition(nums: inout [Int], left: Int, right: Int) -> Int {
|
||||
// 以 nums[left] 作为基准数
|
||||
var i = left
|
||||
var j = right
|
||||
|
@ -30,22 +30,23 @@ func quickSortPartition(nums: inout [Int], left: Int, right: Int) -> Int {
|
|||
return i // 返回基准数的索引
|
||||
}
|
||||
|
||||
// 快速排序类-快速排序
|
||||
/* 快速排序 */
|
||||
func quickSort(nums: inout [Int], left: Int, right: Int) {
|
||||
// 子数组长度为 1 时终止递归
|
||||
if left >= right {
|
||||
return
|
||||
}
|
||||
// 哨兵划分
|
||||
let pivot = quickSortPartition(nums: &nums, left: left, right: right)
|
||||
let pivot = partition(nums: &nums, left: left, right: right)
|
||||
// 递归左子数组、右子数组
|
||||
quickSort(nums: &nums, left: left, right: pivot - 1)
|
||||
quickSort(nums: &nums, left: pivot + 1, right: right)
|
||||
}
|
||||
|
||||
|
||||
/* 快速排序类(中位基准数优化) */
|
||||
// 快速排序类(中位基准数优化)-选取三个元素的中位数
|
||||
func quickSortMedianThree(nums: [Int], left: Int, mid: Int, right: Int) -> Int {
|
||||
/* 选取三个元素的中位数 */
|
||||
func medianThree(nums: [Int], left: Int, mid: Int, right: Int) -> Int {
|
||||
if (nums[left] < nums[mid]) != (nums[left] < nums[right]) {
|
||||
return left
|
||||
} else if (nums[mid] < nums[left]) != (nums[mid] < nums[right]) {
|
||||
|
@ -55,42 +56,37 @@ func quickSortMedianThree(nums: [Int], left: Int, mid: Int, right: Int) -> Int {
|
|||
}
|
||||
}
|
||||
|
||||
// 快速排序类(中位基准数优化)-哨兵划分(三数取中值)
|
||||
func quickSortMedianPartition(nums: inout [Int], left: Int, right: Int) -> Int {
|
||||
/* 哨兵划分(三数取中值) */
|
||||
func partitionMedian(nums: inout [Int], left: Int, right: Int) -> Int {
|
||||
// 选取三个候选元素的中位数
|
||||
let med = quickSortMedianThree(nums: nums, left: left, mid: (left + right) / 2, right: right)
|
||||
let med = medianThree(nums: nums, left: left, mid: (left + right) / 2, right: right)
|
||||
// 将中位数交换至数组最左端
|
||||
swap(nums: &nums, i: left, j: med)
|
||||
return quickSortPartition(nums: &nums, left: left, right: right)
|
||||
return partition(nums: &nums, left: left, right: right)
|
||||
}
|
||||
|
||||
// 快速排序类(中位基准数优化)-快速排序
|
||||
/* 快速排序(中位基准数优化) */
|
||||
func quickSortMedian(nums: inout [Int], left: Int, right: Int) {
|
||||
// 子数组长度为 1 时终止递归
|
||||
if left >= right {
|
||||
return
|
||||
}
|
||||
// 哨兵划分
|
||||
let pivot = quickSortMedianPartition(nums: &nums, left: left, right: right)
|
||||
let pivot = partitionMedian(nums: &nums, left: left, right: right)
|
||||
// 递归左子数组、右子数组
|
||||
quickSortMedian(nums: &nums, left: left, right: pivot - 1)
|
||||
quickSortMedian(nums: &nums, left: pivot + 1, right: right)
|
||||
}
|
||||
|
||||
/* 快速排序类(尾递归优化) */
|
||||
// 快速排序类(尾递归优化)-哨兵划分
|
||||
func quickSortTailCallPartition(nums: inout [Int], left: Int, right: Int) -> Int {
|
||||
quickSortPartition(nums: &nums, left: left, right: right)
|
||||
}
|
||||
|
||||
// 快速排序类(尾递归优化)-快速排序(尾递归优化)
|
||||
/* 快速排序(尾递归优化) */
|
||||
func quickSortTailCall(nums: inout [Int], left: Int, right: Int) {
|
||||
var left = left
|
||||
var right = right
|
||||
// 子数组长度为 1 时终止
|
||||
while left < right {
|
||||
// 哨兵划分操作
|
||||
let pivot = quickSortTailCallPartition(nums: &nums, left: left, right: right)
|
||||
let pivot = partition(nums: &nums, left: left, right: right)
|
||||
// 对两个子数组中较短的那个执行快排
|
||||
if (pivot - left) < (right - pivot) {
|
||||
quickSortTailCall(nums: &nums, left: left, right: pivot - 1) // 递归排序左子数组
|
||||
|
|
|
@ -181,14 +181,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
|
|||
=== "Swift"
|
||||
|
||||
```swift title="array.swift"
|
||||
/* 随机返回一个数组元素 */
|
||||
func randomAccess(nums: [Int]) -> Int {
|
||||
// 在区间 [0, nums.count) 中随机抽取一个数字
|
||||
let randomIndex = nums.indices.randomElement()!
|
||||
// 获取并返回随机元素
|
||||
let randomNum = nums[randomIndex]
|
||||
return randomNum
|
||||
}
|
||||
[class]{}-[func]{randomAccess}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -281,17 +274,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
|
|||
=== "Swift"
|
||||
|
||||
```swift title="array.swift"
|
||||
/* 扩展数组长度 */
|
||||
func extend(nums: [Int], enlarge: Int) -> [Int] {
|
||||
// 初始化一个扩展长度后的数组
|
||||
var res = Array(repeating: 0, count: nums.count + enlarge)
|
||||
// 将原数组中的所有元素复制到新数组
|
||||
for i in nums.indices {
|
||||
res[i] = nums[i]
|
||||
}
|
||||
// 返回扩展后的新数组
|
||||
return res
|
||||
}
|
||||
[class]{}-[func]{extend}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -415,24 +398,9 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
|
|||
=== "Swift"
|
||||
|
||||
```swift title="array.swift"
|
||||
/* 在数组的索引 index 处插入元素 num */
|
||||
func insert(nums: inout [Int], num: Int, index: Int) {
|
||||
// 把索引 index 以及之后的所有元素向后移动一位
|
||||
for i in sequence(first: nums.count - 1, next: { $0 > index + 1 ? $0 - 1 : nil }) {
|
||||
nums[i] = nums[i - 1]
|
||||
}
|
||||
// 将 num 赋给 index 处元素
|
||||
nums[index] = num
|
||||
}
|
||||
[class]{}-[func]{insert}
|
||||
|
||||
/* 删除索引 index 处元素 */
|
||||
func remove(nums: inout [Int], index: Int) {
|
||||
let count = nums.count
|
||||
// 把索引 index 之后的所有元素向前移动一位
|
||||
for i in sequence(first: index, next: { $0 < count - 1 - 1 ? $0 + 1 : nil }) {
|
||||
nums[i] = nums[i + 1]
|
||||
}
|
||||
}
|
||||
[class]{}-[func]{remove}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -539,18 +507,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
|
|||
=== "Swift"
|
||||
|
||||
```swift title="array.swift"
|
||||
/* 遍历数组 */
|
||||
func traverse(nums: [Int]) {
|
||||
var count = 0
|
||||
// 通过索引遍历数组
|
||||
for _ in nums.indices {
|
||||
count += 1
|
||||
}
|
||||
// 直接遍历数组
|
||||
for _ in nums {
|
||||
count += 1
|
||||
}
|
||||
}
|
||||
[class]{}-[func]{traverse}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -644,15 +601,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
|
|||
=== "Swift"
|
||||
|
||||
```swift title="array.swift"
|
||||
/* 在数组中查找指定元素 */
|
||||
func find(nums: [Int], target: Int) -> Int {
|
||||
for i in nums.indices {
|
||||
if nums[i] == target {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
[class]{}-[func]{find}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
|
|
@ -572,17 +572,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="linked_list.swift"
|
||||
/* 访问链表中索引为 index 的结点 */
|
||||
func access(head: ListNode, index: Int) -> ListNode? {
|
||||
var head: ListNode? = head
|
||||
for _ in 0 ..< index {
|
||||
if head == nil {
|
||||
return nil
|
||||
}
|
||||
head = head?.next
|
||||
}
|
||||
return head
|
||||
}
|
||||
[class]{}-[func]{access}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -680,19 +670,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="linked_list.swift"
|
||||
/* 在链表中查找值为 target 的首个结点 */
|
||||
func find(head: ListNode, target: Int) -> Int {
|
||||
var head: ListNode? = head
|
||||
var index = 0
|
||||
while head != nil {
|
||||
if head?.val == target {
|
||||
return index
|
||||
}
|
||||
head = head?.next
|
||||
index += 1
|
||||
}
|
||||
return -1
|
||||
}
|
||||
[class]{}-[func]{find}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
|
|
@ -956,99 +956,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="my_list.swift"
|
||||
/* 列表类简易实现 */
|
||||
class MyList {
|
||||
private var nums: [Int] // 数组(存储列表元素)
|
||||
private var _capacity = 10 // 列表容量
|
||||
private var _size = 0 // 列表长度(即当前元素数量)
|
||||
private let extendRatio = 2 // 每次列表扩容的倍数
|
||||
|
||||
/* 构造函数 */
|
||||
init() {
|
||||
nums = Array(repeating: 0, count: _capacity)
|
||||
}
|
||||
|
||||
/* 获取列表长度(即当前元素数量)*/
|
||||
func size() -> Int {
|
||||
_size
|
||||
}
|
||||
|
||||
/* 获取列表容量 */
|
||||
func capacity() -> Int {
|
||||
_capacity
|
||||
}
|
||||
|
||||
/* 访问元素 */
|
||||
func get(index: Int) -> Int {
|
||||
// 索引如果越界则抛出错误,下同
|
||||
if index < 0 || index >= _size {
|
||||
fatalError("索引越界")
|
||||
}
|
||||
return nums[index]
|
||||
}
|
||||
|
||||
/* 更新元素 */
|
||||
func set(index: Int, num: Int) {
|
||||
if index < 0 || index >= _size {
|
||||
fatalError("索引越界")
|
||||
}
|
||||
nums[index] = num
|
||||
}
|
||||
|
||||
/* 尾部添加元素 */
|
||||
func add(num: Int) {
|
||||
// 元素数量超出容量时,触发扩容机制
|
||||
if _size == _capacity {
|
||||
extendCapacity()
|
||||
}
|
||||
nums[_size] = num
|
||||
// 更新元素数量
|
||||
_size += 1
|
||||
}
|
||||
|
||||
/* 中间插入元素 */
|
||||
func insert(index: Int, num: Int) {
|
||||
if index < 0 || index >= _size {
|
||||
fatalError("索引越界")
|
||||
}
|
||||
// 元素数量超出容量时,触发扩容机制
|
||||
if _size == _capacity {
|
||||
extendCapacity()
|
||||
}
|
||||
// 将索引 index 以及之后的元素都向后移动一位
|
||||
for j in sequence(first: _size - 1, next: { $0 >= index + 1 ? $0 - 1 : nil }) {
|
||||
nums[j + 1] = nums[j]
|
||||
}
|
||||
nums[index] = num
|
||||
// 更新元素数量
|
||||
_size += 1
|
||||
}
|
||||
|
||||
/* 删除元素 */
|
||||
@discardableResult
|
||||
func remove(index: Int) -> Int {
|
||||
if index < 0 || index >= _size {
|
||||
fatalError("索引越界")
|
||||
}
|
||||
let num = nums[index]
|
||||
// 将索引 index 之后的元素都向前移动一位
|
||||
for j in index ..< (_size - 1) {
|
||||
nums[j] = nums[j + 1]
|
||||
}
|
||||
// 更新元素数量
|
||||
_size -= 1
|
||||
// 返回被删除元素
|
||||
return num
|
||||
}
|
||||
|
||||
/* 列表扩容 */
|
||||
func extendCapacity() {
|
||||
// 新建一个长度为 size 的数组,并将原数组拷贝到新数组
|
||||
nums = nums + Array(repeating: 0, count: _capacity * (extendRatio - 1))
|
||||
// 更新列表容量
|
||||
_capacity = nums.count
|
||||
}
|
||||
}
|
||||
[class]{MyList}-[func]{}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
|
|
@ -665,22 +665,7 @@ $$
|
|||
=== "Swift"
|
||||
|
||||
```swift title="space_complexity.swift"
|
||||
/* 常数阶 */
|
||||
func constant(n: Int) {
|
||||
// 常量、变量、对象占用 O(1) 空间
|
||||
let a = 0
|
||||
var b = 0
|
||||
let nums = Array(repeating: 0, count: 10000)
|
||||
let node = ListNode(x: 0)
|
||||
// 循环中的变量占用 O(1) 空间
|
||||
for _ in 0 ..< n {
|
||||
let c = 0
|
||||
}
|
||||
// 循环中的函数占用 O(1) 空间
|
||||
for _ in 0 ..< n {
|
||||
function()
|
||||
}
|
||||
}
|
||||
[class]{}-[func]{constant}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -797,15 +782,7 @@ $$
|
|||
=== "Swift"
|
||||
|
||||
```swift title="space_complexity.swift"
|
||||
/* 线性阶 */
|
||||
func linear(n: Int) {
|
||||
// 长度为 n 的数组占用 O(n) 空间
|
||||
let nums = Array(repeating: 0, count: n)
|
||||
// 长度为 n 的列表占用 O(n) 空间
|
||||
let nodes = (0 ..< n).map { ListNode(x: $0) }
|
||||
// 长度为 n 的哈希表占用 O(n) 空间
|
||||
let map = Dictionary(uniqueKeysWithValues: (0 ..< n).map { ($0, "\($0)") })
|
||||
}
|
||||
[class]{}-[func]{linear}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -901,14 +878,7 @@ $$
|
|||
=== "Swift"
|
||||
|
||||
```swift title="space_complexity.swift"
|
||||
/* 线性阶(递归实现) */
|
||||
func linearRecur(n: Int) {
|
||||
print("递归 n = \(n)")
|
||||
if n == 1 {
|
||||
return
|
||||
}
|
||||
linearRecur(n: n - 1)
|
||||
}
|
||||
[class]{}-[func]{linearRecur}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -1004,11 +974,7 @@ $$
|
|||
=== "Swift"
|
||||
|
||||
```swift title="space_complexity.swift"
|
||||
/* 平方阶 */
|
||||
func quadratic(n: Int) {
|
||||
// 二维列表占用 O(n^2) 空间
|
||||
let numList = Array(repeating: Array(repeating: 0, count: n), count: n)
|
||||
}
|
||||
[class]{}-[func]{quadratic}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -1100,15 +1066,7 @@ $$
|
|||
=== "Swift"
|
||||
|
||||
```swift title="space_complexity.swift"
|
||||
/* 平方阶(递归实现) */
|
||||
func quadraticRecur(n: Int) -> Int {
|
||||
if n <= 0 {
|
||||
return 0
|
||||
}
|
||||
// 数组 nums 长度为 n, n-1, ..., 2, 1
|
||||
let nums = Array(repeating: 0, count: n)
|
||||
return quadraticRecur(n: n - 1)
|
||||
}
|
||||
[class]{}-[func]{quadraticRecur}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -1199,16 +1157,7 @@ $$
|
|||
=== "Swift"
|
||||
|
||||
```swift title="space_complexity.swift"
|
||||
/* 指数阶(建立满二叉树) */
|
||||
func buildTree(n: Int) -> TreeNode? {
|
||||
if n == 0 {
|
||||
return nil
|
||||
}
|
||||
let root = TreeNode(x: 0)
|
||||
root.left = buildTree(n: n - 1)
|
||||
root.right = buildTree(n: n - 1)
|
||||
return root
|
||||
}
|
||||
[class]{}-[func]{buildTree}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
|
|
@ -108,17 +108,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="leetcode_two_sum.swift"
|
||||
func twoSumBruteForce(nums: [Int], target: Int) -> [Int] {
|
||||
// 两层循环,时间复杂度 O(n^2)
|
||||
for i in nums.indices.dropLast() {
|
||||
for j in nums.indices.dropFirst(i + 1) {
|
||||
if nums[i] + nums[j] == target {
|
||||
return [i, j]
|
||||
}
|
||||
}
|
||||
}
|
||||
return [0]
|
||||
}
|
||||
[class]{}-[func]{twoSumBruteForce}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -229,18 +219,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="leetcode_two_sum.swift"
|
||||
func twoSumHashTable(nums: [Int], target: Int) -> [Int] {
|
||||
// 辅助哈希表,空间复杂度 O(n)
|
||||
var dic: [Int: Int] = [:]
|
||||
// 单层循环,时间复杂度 O(n)
|
||||
for i in nums.indices {
|
||||
if let j = dic[target - nums[i]] {
|
||||
return [j, i]
|
||||
}
|
||||
dic[nums[i]] = i
|
||||
}
|
||||
return [0]
|
||||
}
|
||||
[class]{}-[func]{twoSumHashTable}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
|
|
@ -868,15 +868,7 @@ $$
|
|||
=== "Swift"
|
||||
|
||||
```swift title="time_complexity.swift"
|
||||
/* 常数阶 */
|
||||
func constant(n: Int) -> Int {
|
||||
var count = 0
|
||||
let size = 100000
|
||||
for _ in 0 ..< size {
|
||||
count += 1
|
||||
}
|
||||
return count
|
||||
}
|
||||
[class]{}-[func]{constant}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -971,14 +963,7 @@ $$
|
|||
=== "Swift"
|
||||
|
||||
```swift title="time_complexity.swift"
|
||||
/* 线性阶 */
|
||||
func linear(n: Int) -> Int {
|
||||
var count = 0
|
||||
for _ in 0 ..< n {
|
||||
count += 1
|
||||
}
|
||||
return count
|
||||
}
|
||||
[class]{}-[func]{linear}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -1078,15 +1063,7 @@ $$
|
|||
=== "Swift"
|
||||
|
||||
```swift title="time_complexity.swift"
|
||||
/* 线性阶(遍历数组) */
|
||||
func arrayTraversal(nums: [Int]) -> Int {
|
||||
var count = 0
|
||||
// 循环次数与数组长度成正比
|
||||
for _ in nums {
|
||||
count += 1
|
||||
}
|
||||
return count
|
||||
}
|
||||
[class]{}-[func]{arrayTraversal}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -1191,17 +1168,7 @@ $$
|
|||
=== "Swift"
|
||||
|
||||
```swift title="time_complexity.swift"
|
||||
/* 平方阶 */
|
||||
func quadratic(n: Int) -> Int {
|
||||
var count = 0
|
||||
// 循环次数与数组长度成平方关系
|
||||
for _ in 0 ..< n {
|
||||
for _ in 0 ..< n {
|
||||
count += 1
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
[class]{}-[func]{quadratic}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -1341,24 +1308,7 @@ $$
|
|||
=== "Swift"
|
||||
|
||||
```swift title="time_complexity.swift"
|
||||
/* 平方阶(冒泡排序) */
|
||||
func bubbleSort(nums: inout [Int]) -> Int {
|
||||
var count = 0 // 计数器
|
||||
// 外循环:待排序元素数量为 n-1, n-2, ..., 1
|
||||
for i in sequence(first: nums.count - 1, next: { $0 > 0 + 1 ? $0 - 1 : nil }) {
|
||||
// 内循环:冒泡操作
|
||||
for j in 0 ..< i {
|
||||
if nums[j] > nums[j + 1] {
|
||||
// 交换 nums[j] 与 nums[j + 1]
|
||||
let tmp = nums[j]
|
||||
nums[j] = nums[j + 1]
|
||||
nums[j + 1] = tmp
|
||||
count += 3 // 元素交换包含 3 个单元操作
|
||||
}
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
[class]{}-[func]{bubbleSort}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -1485,20 +1435,7 @@ $$
|
|||
=== "Swift"
|
||||
|
||||
```swift title="time_complexity.swift"
|
||||
/* 指数阶(循环实现) */
|
||||
func exponential(n: Int) -> Int {
|
||||
var count = 0
|
||||
var base = 1
|
||||
// cell 每轮一分为二,形成数列 1, 2, 4, 8, ..., 2^(n-1)
|
||||
for _ in 0 ..< n {
|
||||
for _ in 0 ..< base {
|
||||
count += 1
|
||||
}
|
||||
base *= 2
|
||||
}
|
||||
// count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1
|
||||
return count
|
||||
}
|
||||
[class]{}-[func]{exponential}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -1594,13 +1531,7 @@ $$
|
|||
=== "Swift"
|
||||
|
||||
```swift title="time_complexity.swift"
|
||||
/* 指数阶(递归实现) */
|
||||
func expRecur(n: Int) -> Int {
|
||||
if n == 1 {
|
||||
return 1
|
||||
}
|
||||
return expRecur(n: n - 1) + expRecur(n: n - 1) + 1
|
||||
}
|
||||
[class]{}-[func]{expRecur}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -1698,16 +1629,7 @@ $$
|
|||
=== "Swift"
|
||||
|
||||
```swift title="time_complexity.swift"
|
||||
/* 对数阶(循环实现) */
|
||||
func logarithmic(n: Int) -> Int {
|
||||
var count = 0
|
||||
var n = n
|
||||
while n > 1 {
|
||||
n = n / 2
|
||||
count += 1
|
||||
}
|
||||
return count
|
||||
}
|
||||
[class]{}-[func]{logarithmic}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -1799,13 +1721,7 @@ $$
|
|||
=== "Swift"
|
||||
|
||||
```swift title="time_complexity.swift"
|
||||
/* 对数阶(递归实现) */
|
||||
func logRecur(n: Int) -> Int {
|
||||
if n <= 1 {
|
||||
return 0
|
||||
}
|
||||
return logRecur(n: n / 2) + 1
|
||||
}
|
||||
[class]{}-[func]{logRecur}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -1907,17 +1823,7 @@ $$
|
|||
=== "Swift"
|
||||
|
||||
```swift title="time_complexity.swift"
|
||||
/* 线性对数阶 */
|
||||
func linearLogRecur(n: Double) -> Int {
|
||||
if n <= 1 {
|
||||
return 1
|
||||
}
|
||||
var count = linearLogRecur(n: n / 2) + linearLogRecur(n: n / 2)
|
||||
for _ in 0 ..< Int(n) {
|
||||
count += 1
|
||||
}
|
||||
return count
|
||||
}
|
||||
[class]{}-[func]{linearLogRecur}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -2032,18 +1938,7 @@ $$
|
|||
=== "Swift"
|
||||
|
||||
```swift title="time_complexity.swift"
|
||||
/* 阶乘阶(递归实现) */
|
||||
func factorialRecur(n: Int) -> Int {
|
||||
if n == 0 {
|
||||
return 1
|
||||
}
|
||||
var count = 0
|
||||
// 从 1 个分裂出 n 个
|
||||
for _ in 0 ..< n {
|
||||
count += factorialRecur(n: n - 1)
|
||||
}
|
||||
return count
|
||||
}
|
||||
[class]{}-[func]{factorialRecur}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
|
|
@ -572,55 +572,9 @@ $$
|
|||
=== "Swift"
|
||||
|
||||
```swift title="array_hash_map.swift"
|
||||
/* 键值对 int->String */
|
||||
class Entry {
|
||||
var key: Int
|
||||
var val: String
|
||||
|
||||
init(key: Int, val: String) {
|
||||
self.key = key
|
||||
self.val = val
|
||||
}
|
||||
}
|
||||
|
||||
/* 基于数组简易实现的哈希表 */
|
||||
class ArrayHashMap {
|
||||
private var bucket: [Entry?] = []
|
||||
|
||||
init() {
|
||||
// 初始化一个长度为 100 的桶(数组)
|
||||
for _ in 0 ..< 100 {
|
||||
bucket.append(nil)
|
||||
}
|
||||
}
|
||||
|
||||
/* 哈希函数 */
|
||||
private func hashFunc(key: Int) -> Int {
|
||||
let index = key % 100
|
||||
return index
|
||||
}
|
||||
|
||||
/* 查询操作 */
|
||||
func get(key: Int) -> String? {
|
||||
let index = hashFunc(key: key)
|
||||
let pair = bucket[index]
|
||||
return pair?.val
|
||||
}
|
||||
|
||||
/* 添加操作 */
|
||||
func put(key: Int, val: String) {
|
||||
let pair = Entry(key: key, val: val)
|
||||
let index = hashFunc(key: key)
|
||||
bucket[index] = pair
|
||||
}
|
||||
|
||||
/* 删除操作 */
|
||||
func remove(key: Int) {
|
||||
let index = hashFunc(key: key)
|
||||
// 置为 nil ,代表删除
|
||||
bucket[index] = nil
|
||||
}
|
||||
}
|
||||
[class]{Entry}-[func]{}
|
||||
|
||||
[class]{ArrayHashMap}-[func]{}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
|
|
@ -350,27 +350,11 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="my_heap.swift"
|
||||
var maxHeap: [Int]
|
||||
[class]{MaxHeap}-[func]{left}
|
||||
|
||||
/* 构造函数,建立空堆 */
|
||||
init() {
|
||||
maxHeap = []
|
||||
}
|
||||
[class]{MaxHeap}-[func]{right}
|
||||
|
||||
/* 获取左子结点索引 */
|
||||
func left(i: Int) -> Int {
|
||||
2 * i + 1
|
||||
}
|
||||
|
||||
/* 获取右子结点索引 */
|
||||
func right(i: Int) -> Int {
|
||||
2 * i + 2
|
||||
}
|
||||
|
||||
/* 获取父结点索引 */
|
||||
func parent(i: Int) -> Int {
|
||||
(i - 1) / 2 // 向下整除
|
||||
}
|
||||
[class]{MaxHeap}-[func]{parent}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -437,10 +421,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="my_heap.swift"
|
||||
/* 访问堆顶元素 */
|
||||
func peek() -> Int {
|
||||
maxHeap[0]
|
||||
}
|
||||
[class]{MaxHeap}-[func]{peek}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -556,30 +537,9 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="my_heap.swift"
|
||||
/* 元素入堆 */
|
||||
func push(val: Int) {
|
||||
// 添加结点
|
||||
maxHeap.append(val)
|
||||
// 从底至顶堆化
|
||||
siftUp(i: size() - 1)
|
||||
}
|
||||
[class]{MaxHeap}-[func]{push}
|
||||
|
||||
/* 从结点 i 开始,从底至顶堆化 */
|
||||
func siftUp(i: Int) {
|
||||
var i = i
|
||||
while true {
|
||||
// 获取结点 i 的父结点
|
||||
let p = parent(i: i)
|
||||
// 当“越过根结点”或“结点无需修复”时,结束堆化
|
||||
if p < 0 || maxHeap[i] <= maxHeap[p] {
|
||||
break
|
||||
}
|
||||
// 交换两结点
|
||||
swap(i: i, j: p)
|
||||
// 循环向上堆化
|
||||
i = p
|
||||
}
|
||||
}
|
||||
[class]{MaxHeap}-[func]{siftUp}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -728,46 +688,9 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="my_heap.swift"
|
||||
/* 元素出堆 */
|
||||
func poll() -> Int {
|
||||
// 判空处理
|
||||
if isEmpty() {
|
||||
fatalError("堆为空")
|
||||
}
|
||||
// 交换根结点与最右叶结点(即交换首元素与尾元素)
|
||||
swap(i: 0, j: size() - 1)
|
||||
// 删除结点
|
||||
let val = maxHeap.remove(at: size() - 1)
|
||||
// 从顶至底堆化
|
||||
siftDown(i: 0)
|
||||
// 返回堆顶元素
|
||||
return val
|
||||
}
|
||||
[class]{MaxHeap}-[func]{poll}
|
||||
|
||||
/* 从结点 i 开始,从顶至底堆化 */
|
||||
func siftDown(i: Int) {
|
||||
var i = i
|
||||
while true {
|
||||
// 判断结点 i, l, r 中值最大的结点,记为 ma
|
||||
let l = left(i: i)
|
||||
let r = right(i: i)
|
||||
var ma = i
|
||||
if l < size(), maxHeap[l] > maxHeap[ma] {
|
||||
ma = l
|
||||
}
|
||||
if r < size(), maxHeap[r] > maxHeap[ma] {
|
||||
ma = r
|
||||
}
|
||||
// 若结点 i 最大或索引 l, r 越界,则无需继续堆化,跳出
|
||||
if ma == i {
|
||||
break
|
||||
}
|
||||
// 交换两结点
|
||||
swap(i: i, j: ma)
|
||||
// 循环向下堆化
|
||||
i = ma
|
||||
}
|
||||
}
|
||||
[class]{MaxHeap}-[func]{siftDown}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -842,15 +765,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="my_heap.swift"
|
||||
/* 构造函数,根据输入列表建堆 */
|
||||
init(nums: [Int]) {
|
||||
// 将列表元素原封不动添加进堆
|
||||
maxHeap = nums
|
||||
// 堆化除叶结点以外的其他所有结点
|
||||
for i in stride(from: parent(i: size() - 1), through: 0, by: -1) {
|
||||
siftDown(i: i)
|
||||
}
|
||||
}
|
||||
[class]{MaxHeap}-[func]{init}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
|
|
@ -137,25 +137,7 @@ $$
|
|||
=== "Swift"
|
||||
|
||||
```swift title="binary_search.swift"
|
||||
/* 二分查找(双闭区间) */
|
||||
func binarySearch(nums: [Int], target: Int) -> Int {
|
||||
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||
var i = 0
|
||||
var j = nums.count - 1
|
||||
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||
while i <= j {
|
||||
let m = (i + j) / 2 // 计算中点索引 m
|
||||
if nums[m] < target { // 此情况说明 target 在区间 [m+1, j] 中
|
||||
i = m + 1
|
||||
} else if nums[m] > target { // 此情况说明 target 在区间 [i, m-1] 中
|
||||
j = m - 1
|
||||
} else { // 找到目标元素,返回其索引
|
||||
return m
|
||||
}
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1
|
||||
}
|
||||
[class]{}-[func]{binarySearch}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -254,25 +236,7 @@ $$
|
|||
=== "Swift"
|
||||
|
||||
```swift title="binary_search.swift"
|
||||
/* 二分查找(左闭右开) */
|
||||
func binarySearch1(nums: [Int], target: Int) -> Int {
|
||||
// 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||
var i = 0
|
||||
var j = nums.count
|
||||
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||
while i < j {
|
||||
let m = (i + j) / 2 // 计算中点索引 m
|
||||
if nums[m] < target { // 此情况说明 target 在区间 [m+1, j) 中
|
||||
i = m + 1
|
||||
} else if nums[m] > target { // 此情况说明 target 在区间 [i, m) 中
|
||||
j = m
|
||||
} else { // 找到目标元素,返回其索引
|
||||
return m
|
||||
}
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1
|
||||
}
|
||||
[class]{}-[func]{binarySearch1}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
|
|
@ -82,12 +82,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="hashing_search.swift"
|
||||
/* 哈希查找(数组) */
|
||||
func hashingSearchArray(map: [Int: Int], target: Int) -> Int {
|
||||
// 哈希表的 key: 目标元素,value: 索引
|
||||
// 若哈希表中无此 key ,返回 -1
|
||||
return map[target, default: -1]
|
||||
}
|
||||
[class]{}-[func]{hashingSearchArray}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -167,12 +162,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="hashing_search.swift"
|
||||
/* 哈希查找(链表) */
|
||||
func hashingSearchLinkedList(map: [Int: ListNode], target: Int) -> ListNode? {
|
||||
// 哈希表的 key: 目标结点值,value: 结点对象
|
||||
// 若哈希表中无此 key ,返回 null
|
||||
return map[target]
|
||||
}
|
||||
[class]{}-[func]{hashingSearchLinkedList}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
|
|
@ -87,18 +87,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="linear_search.swift"
|
||||
/* 线性查找(数组) */
|
||||
func linearSearchArray(nums: [Int], target: Int) -> Int {
|
||||
// 遍历数组
|
||||
for i in nums.indices {
|
||||
// 找到目标元素,返回其索引
|
||||
if nums[i] == target {
|
||||
return i
|
||||
}
|
||||
}
|
||||
// 未找到目标元素,返回 -1
|
||||
return -1
|
||||
}
|
||||
[class]{}-[func]{linearSearchArray}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -185,20 +174,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="linear_search.swift"
|
||||
/* 线性查找(链表) */
|
||||
func linearSearchLinkedList(head: ListNode?, target: Int) -> ListNode? {
|
||||
var head = head
|
||||
// 遍历链表
|
||||
while head != nil {
|
||||
// 找到目标结点,返回之
|
||||
if head?.val == target {
|
||||
return head
|
||||
}
|
||||
head = head?.next
|
||||
}
|
||||
// 未找到目标结点,返回 null
|
||||
return nil
|
||||
}
|
||||
[class]{}-[func]{linearSearchLinkedList}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
|
|
@ -144,21 +144,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="bubble_sort.swift"
|
||||
/* 冒泡排序 */
|
||||
func bubbleSort(nums: inout [Int]) {
|
||||
// 外循环:待排序元素数量为 n-1, n-2, ..., 1
|
||||
for i in stride(from: nums.count - 1, to: 0, by: -1) {
|
||||
// 内循环:冒泡操作
|
||||
for j in stride(from: 0, to: i, by: 1) {
|
||||
if nums[j] > nums[j + 1] {
|
||||
// 交换 nums[j] 与 nums[j + 1]
|
||||
let tmp = nums[j]
|
||||
nums[j] = nums[j + 1]
|
||||
nums[j + 1] = tmp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
[class]{}-[func]{bubbleSort}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -293,25 +279,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="bubble_sort.swift"
|
||||
/* 冒泡排序(标志优化)*/
|
||||
func bubbleSortWithFlag(nums: inout [Int]) {
|
||||
// 外循环:待排序元素数量为 n-1, n-2, ..., 1
|
||||
for i in stride(from: nums.count - 1, to: 0, by: -1) {
|
||||
var flag = false // 初始化标志位
|
||||
for j in stride(from: 0, to: i, by: 1) {
|
||||
if nums[j] > nums[j + 1] {
|
||||
// 交换 nums[j] 与 nums[j + 1]
|
||||
let tmp = nums[j]
|
||||
nums[j] = nums[j + 1]
|
||||
nums[j + 1] = tmp
|
||||
flag = true // 记录交换元素
|
||||
}
|
||||
}
|
||||
if !flag { // 此轮冒泡未交换任何元素,直接跳出
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
[class]{}-[func]{bubbleSortWithFlag}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
|
|
@ -119,20 +119,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="insertion_sort.swift"
|
||||
/* 插入排序 */
|
||||
func insertionSort(nums: inout [Int]) {
|
||||
// 外循环:base = nums[1], nums[2], ..., nums[n-1]
|
||||
for i in stride(from: 1, to: nums.count, by: 1) {
|
||||
let base = nums[i]
|
||||
var j = i - 1
|
||||
// 内循环:将 base 插入到左边的正确位置
|
||||
while j >= 0, nums[j] > base {
|
||||
nums[j + 1] = nums[j] // 1. 将 nums[j] 向右移动一位
|
||||
j -= 1
|
||||
}
|
||||
nums[j + 1] = base // 2. 将 base 赋值到正确位置
|
||||
}
|
||||
}
|
||||
[class]{}-[func]{insertionSort}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
|
|
@ -54,27 +54,9 @@ comments: true
|
|||
=== "C++"
|
||||
|
||||
```cpp title="quick_sort.cpp"
|
||||
/* 元素交换 */
|
||||
void swap(vector<int>& nums, int i, int j) {
|
||||
int tmp = nums[i];
|
||||
nums[i] = nums[j];
|
||||
nums[j] = tmp;
|
||||
}
|
||||
[class]{QuickSort}-[func]{swap}
|
||||
|
||||
/* 哨兵划分 */
|
||||
int partition(vector<int>& nums, int left, int right) {
|
||||
// 以 nums[left] 作为基准数
|
||||
int i = left, j = right;
|
||||
while (i < j) {
|
||||
while (i < j && nums[j] >= nums[left])
|
||||
j--; // 从右向左找首个小于基准数的元素
|
||||
while (i < j && nums[i] <= nums[left])
|
||||
i++; // 从左向右找首个大于基准数的元素
|
||||
swap(nums, i, j); // 交换这两个元素
|
||||
}
|
||||
swap(nums, i, left); // 将基准数交换至两子数组的分界线
|
||||
return i; // 返回基准数的索引
|
||||
}
|
||||
[class]{QuickSort}-[func]{partition}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
|
@ -109,59 +91,17 @@ comments: true
|
|||
=== "JavaScript"
|
||||
|
||||
```javascript title="quick_sort.js"
|
||||
/* 元素交换 */
|
||||
function swap(nums, i, j) {
|
||||
let tmp = nums[i];
|
||||
nums[i] = nums[j];
|
||||
nums[j] = tmp;
|
||||
}
|
||||
|
||||
/* 哨兵划分 */
|
||||
function partition(nums, left, right) {
|
||||
// 以 nums[left] 作为基准数
|
||||
let i = left, j = right;
|
||||
while (i < j) {
|
||||
while (i < j && nums[j] >= nums[left]) {
|
||||
j -= 1; // 从右向左找首个小于基准数的元素
|
||||
}
|
||||
while (i < j && nums[i] <= nums[left]) {
|
||||
i += 1; // 从左向右找首个大于基准数的元素
|
||||
}
|
||||
// 元素交换
|
||||
swap(nums, i, j); // 交换这两个元素
|
||||
}
|
||||
swap(nums, i, left); // 将基准数交换至两子数组的分界线
|
||||
return i; // 返回基准数的索引
|
||||
}
|
||||
[class]{QuickSort}-[func]{swap}
|
||||
|
||||
[class]{QuickSort}-[func]{partition}
|
||||
```
|
||||
|
||||
=== "TypeScript"
|
||||
|
||||
```typescript title="quick_sort.ts"
|
||||
/* 元素交换 */
|
||||
function swap(nums: number[], i: number, j: number): void {
|
||||
let tmp = nums[i];
|
||||
nums[i] = nums[j];
|
||||
nums[j] = tmp;
|
||||
}
|
||||
[class]{QuickSort}-[func]{swap}
|
||||
|
||||
/* 哨兵划分 */
|
||||
function partition(nums: number[], left: number, right: number): number {
|
||||
// 以 nums[left] 作为基准数
|
||||
let i = left, j = right;
|
||||
while (i < j) {
|
||||
while (i < j && nums[j] >= nums[left]) {
|
||||
j -= 1; // 从右向左找首个小于基准数的元素
|
||||
}
|
||||
while (i < j && nums[i] <= nums[left]) {
|
||||
i += 1; // 从左向右找首个大于基准数的元素
|
||||
}
|
||||
// 元素交换
|
||||
swap(nums, i, j); // 交换这两个元素
|
||||
}
|
||||
swap(nums, i, left); // 将基准数交换至两子数组的分界线
|
||||
return i; // 返回基准数的索引
|
||||
}
|
||||
[class]{QuickSort}-[func]{partition}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
@ -202,30 +142,9 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="quick_sort.swift"
|
||||
/* 元素交换 */
|
||||
func swap(nums: inout [Int], i: Int, j: Int) {
|
||||
let tmp = nums[i]
|
||||
nums[i] = nums[j]
|
||||
nums[j] = tmp
|
||||
}
|
||||
[class]{}-[func]{swap}
|
||||
|
||||
/* 哨兵划分 */
|
||||
func partition(nums: inout [Int], left: Int, right: Int) -> Int {
|
||||
// 以 nums[left] 作为基准数
|
||||
var i = left
|
||||
var j = right
|
||||
while i < j {
|
||||
while i < j, nums[j] >= nums[left] {
|
||||
j -= 1 // 从右向左找首个小于基准数的元素
|
||||
}
|
||||
while i < j, nums[i] <= nums[left] {
|
||||
i += 1 // 从左向右找首个大于基准数的元素
|
||||
}
|
||||
swap(nums: &nums, i: i, j: j) // 交换这两个元素
|
||||
}
|
||||
swap(nums: &nums, i: i, j: left) // 将基准数交换至两子数组的分界线
|
||||
return i // 返回基准数的索引
|
||||
}
|
||||
[class]{}-[func]{partition}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -324,18 +243,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="quick_sort.swift"
|
||||
/* 快速排序 */
|
||||
func quickSort(nums: inout [Int], left: Int, right: Int) {
|
||||
// 子数组长度为 1 时终止递归
|
||||
if left >= right {
|
||||
return
|
||||
}
|
||||
// 哨兵划分
|
||||
let pivot = partition(nums: &nums, left: left, right: right)
|
||||
// 递归左子数组、右子数组
|
||||
quickSort(nums: &nums, left: left, right: pivot - 1)
|
||||
quickSort(nums: &nums, left: pivot + 1, right: right)
|
||||
}
|
||||
[class]{}-[func]{quickSort}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -475,26 +383,9 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="quick_sort.swift"
|
||||
/* 选取三个元素的中位数 */
|
||||
func medianThree(nums: [Int], left: Int, mid: Int, right: Int) -> Int {
|
||||
if (nums[left] < nums[mid]) != (nums[left] < nums[right]) {
|
||||
return left
|
||||
} else if (nums[mid] < nums[left]) != (nums[mid] < nums[right]) {
|
||||
return mid
|
||||
} else {
|
||||
return right
|
||||
}
|
||||
}
|
||||
[class]{}-[func]{medianThree}
|
||||
|
||||
/* 哨兵划分(三数取中值) */
|
||||
func partition(nums: inout [Int], left: Int, right: Int) -> Int {
|
||||
// 选取三个候选元素的中位数
|
||||
let med = medianThree(nums: nums, left: left, mid: (left + right) / 2, right: right)
|
||||
// 将中位数交换至数组最左端
|
||||
swap(nums: &nums, i: left, j: med)
|
||||
// 以 nums[left] 作为基准数
|
||||
// 下同省略...
|
||||
}
|
||||
[class]{}-[func]{partitionMedian}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -595,24 +486,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="quick_sort.swift"
|
||||
/* 快速排序(尾递归优化) */
|
||||
func quickSort(nums: inout [Int], left: Int, right: Int) {
|
||||
var left = left
|
||||
var right = right
|
||||
// 子数组长度为 1 时终止
|
||||
while left < right {
|
||||
// 哨兵划分操作
|
||||
let pivot = partition(nums: &nums, left: left, right: right)
|
||||
// 对两个子数组中较短的那个执行快排
|
||||
if (pivot - left) < (right - pivot) {
|
||||
quickSort(nums: &nums, left: left, right: pivot - 1) // 递归排序左子数组
|
||||
left = pivot + 1 // 剩余待排序区间为 [pivot + 1, right]
|
||||
} else {
|
||||
quickSort(nums: &nums, left: pivot + 1, right: right) // 递归排序右子数组
|
||||
right = pivot - 1 // 剩余待排序区间为 [left, pivot - 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
[class]{}-[func]{quickSortTailCall}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
|
|
@ -432,59 +432,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="linkedlist_queue.swift"
|
||||
/* 基于链表实现的队列 */
|
||||
class LinkedListQueue {
|
||||
private var front: ListNode? // 头结点
|
||||
private var rear: ListNode? // 尾结点
|
||||
private var _size = 0
|
||||
|
||||
init() {}
|
||||
|
||||
/* 获取队列的长度 */
|
||||
func size() -> Int {
|
||||
_size
|
||||
}
|
||||
|
||||
/* 判断队列是否为空 */
|
||||
func isEmpty() -> Bool {
|
||||
size() == 0
|
||||
}
|
||||
|
||||
/* 入队 */
|
||||
func push(num: Int) {
|
||||
// 尾结点后添加 num
|
||||
let node = ListNode(x: num)
|
||||
// 如果队列为空,则令头、尾结点都指向该结点
|
||||
if front == nil {
|
||||
front = node
|
||||
rear = node
|
||||
}
|
||||
// 如果队列不为空,则将该结点添加到尾结点后
|
||||
else {
|
||||
rear?.next = node
|
||||
rear = node
|
||||
}
|
||||
_size += 1
|
||||
}
|
||||
|
||||
/* 出队 */
|
||||
@discardableResult
|
||||
func poll() -> Int {
|
||||
let num = peek()
|
||||
// 删除头结点
|
||||
front = front?.next
|
||||
_size -= 1
|
||||
return num
|
||||
}
|
||||
|
||||
/* 访问队首元素 */
|
||||
func peek() -> Int {
|
||||
if isEmpty() {
|
||||
fatalError("队列为空")
|
||||
}
|
||||
return front!.val
|
||||
}
|
||||
}
|
||||
[class]{LinkedListQueue}-[func]{}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -692,64 +640,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="array_queue.swift"
|
||||
/* 基于环形数组实现的队列 */
|
||||
class ArrayQueue {
|
||||
private var nums: [Int] // 用于存储队列元素的数组
|
||||
private var front = 0 // 队首指针,指向队首元素
|
||||
private var queSize = 0 // 队列长度
|
||||
|
||||
init(capacity: Int) {
|
||||
// 初始化数组
|
||||
nums = Array(repeating: 0, count: capacity)
|
||||
}
|
||||
|
||||
/* 获取队列的容量 */
|
||||
func capacity() -> Int {
|
||||
nums.count
|
||||
}
|
||||
|
||||
/* 获取队列的长度 */
|
||||
func size() -> Int {
|
||||
queSize
|
||||
}
|
||||
|
||||
/* 判断队列是否为空 */
|
||||
func isEmpty() -> Bool {
|
||||
queSize == 0
|
||||
}
|
||||
|
||||
/* 入队 */
|
||||
func push(num: Int) {
|
||||
if size() == capacity() {
|
||||
print("队列已满")
|
||||
return
|
||||
}
|
||||
// 计算尾指针,指向队尾索引 + 1
|
||||
// 通过取余操作,实现 rear 越过数组尾部后回到头部
|
||||
let rear = (front + queSize) % capacity()
|
||||
// 尾结点后添加 num
|
||||
nums[rear] = num
|
||||
queSize += 1
|
||||
}
|
||||
|
||||
/* 出队 */
|
||||
@discardableResult
|
||||
func poll() -> Int {
|
||||
let num = peek()
|
||||
// 队首指针向后移动一位,若越过尾部则返回到数组头部
|
||||
front = (front + 1) % capacity()
|
||||
queSize -= 1
|
||||
return num
|
||||
}
|
||||
|
||||
/* 访问队首元素 */
|
||||
func peek() -> Int {
|
||||
if isEmpty() {
|
||||
fatalError("队列为空")
|
||||
}
|
||||
return nums[front]
|
||||
}
|
||||
}
|
||||
[class]{ArrayQueue}-[func]{}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
|
|
@ -422,48 +422,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="linkedlist_stack.swift"
|
||||
/* 基于链表实现的栈 */
|
||||
class LinkedListStack {
|
||||
private var _peek: ListNode? // 将头结点作为栈顶
|
||||
private var _size = 0 // 栈的长度
|
||||
|
||||
init() {}
|
||||
|
||||
/* 获取栈的长度 */
|
||||
func size() -> Int {
|
||||
_size
|
||||
}
|
||||
|
||||
/* 判断栈是否为空 */
|
||||
func isEmpty() -> Bool {
|
||||
size() == 0
|
||||
}
|
||||
|
||||
/* 入栈 */
|
||||
func push(num: Int) {
|
||||
let node = ListNode(x: num)
|
||||
node.next = _peek
|
||||
_peek = node
|
||||
_size += 1
|
||||
}
|
||||
|
||||
/* 出栈 */
|
||||
@discardableResult
|
||||
func pop() -> Int {
|
||||
let num = peek()
|
||||
_peek = _peek?.next
|
||||
_size -= 1
|
||||
return num
|
||||
}
|
||||
|
||||
/* 访问栈顶元素 */
|
||||
func peek() -> Int {
|
||||
if isEmpty() {
|
||||
fatalError("栈为空")
|
||||
}
|
||||
return _peek!.val
|
||||
}
|
||||
}
|
||||
[class]{LinkedListStack}-[func]{}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -624,47 +583,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="array_stack.swift"
|
||||
/* 基于数组实现的栈 */
|
||||
class ArrayStack {
|
||||
private var stack: [Int]
|
||||
|
||||
init() {
|
||||
// 初始化列表(动态数组)
|
||||
stack = []
|
||||
}
|
||||
|
||||
/* 获取栈的长度 */
|
||||
func size() -> Int {
|
||||
stack.count
|
||||
}
|
||||
|
||||
/* 判断栈是否为空 */
|
||||
func isEmpty() -> Bool {
|
||||
stack.isEmpty
|
||||
}
|
||||
|
||||
/* 入栈 */
|
||||
func push(num: Int) {
|
||||
stack.append(num)
|
||||
}
|
||||
|
||||
/* 出栈 */
|
||||
@discardableResult
|
||||
func pop() -> Int {
|
||||
if isEmpty() {
|
||||
fatalError("栈为空")
|
||||
}
|
||||
return stack.removeLast()
|
||||
}
|
||||
|
||||
/* 访问栈顶元素 */
|
||||
func peek() -> Int {
|
||||
if isEmpty() {
|
||||
fatalError("栈为空")
|
||||
}
|
||||
return stack.last!
|
||||
}
|
||||
}
|
||||
[class]{ArrayStack}-[func]{}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
|
|
@ -362,13 +362,7 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
|
|||
=== "Swift"
|
||||
|
||||
```swift title="avl_tree.swift"
|
||||
/* 获取平衡因子 */
|
||||
func balanceFactor(node: TreeNode?) -> Int {
|
||||
// 空结点平衡因子为 0
|
||||
guard let node = node else { return 0 }
|
||||
// 结点平衡因子 = 左子树高度 - 右子树高度
|
||||
return height(node: node.left) - height(node: node.right)
|
||||
}
|
||||
[class]{AVLTree}-[func]{balanceFactor}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -485,19 +479,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
|||
=== "Swift"
|
||||
|
||||
```swift title="avl_tree.swift"
|
||||
/* 右旋操作 */
|
||||
func rightRotate(node: TreeNode?) -> TreeNode? {
|
||||
let child = node?.left
|
||||
let grandChild = child?.right
|
||||
// 以 child 为原点,将 node 向右旋转
|
||||
child?.right = node
|
||||
node?.left = grandChild
|
||||
// 更新结点高度
|
||||
updateHeight(node: node)
|
||||
updateHeight(node: child)
|
||||
// 返回旋转后子树的根结点
|
||||
return child
|
||||
}
|
||||
[class]{AVLTree}-[func]{rightRotate}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -596,20 +578,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
|||
=== "Swift"
|
||||
|
||||
```swift title="avl_tree.swift"
|
||||
/* 左旋操作 */
|
||||
func leftRotate(node: TreeNode?) -> TreeNode? {
|
||||
let child = node?.right
|
||||
let grandChild = child?.left
|
||||
// 以 child 为原点,将 node 向左旋转
|
||||
child?.left = node
|
||||
node?.right = grandChild
|
||||
// 更新结点高度
|
||||
updateHeight(node: node)
|
||||
updateHeight(node: child)
|
||||
// 返回旋转后子树的根结点
|
||||
return child
|
||||
}
|
||||
|
||||
[class]{AVLTree}-[func]{leftRotate}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -768,35 +737,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
|||
=== "Swift"
|
||||
|
||||
```swift title="avl_tree.swift"
|
||||
/* 执行旋转操作,使该子树重新恢复平衡 */
|
||||
func rotate(node: TreeNode?) -> TreeNode? {
|
||||
// 获取结点 node 的平衡因子
|
||||
let balanceFactor = balanceFactor(node: node)
|
||||
// 左偏树
|
||||
if balanceFactor > 1 {
|
||||
if self.balanceFactor(node: node?.left) >= 0 {
|
||||
// 右旋
|
||||
return rightRotate(node: node)
|
||||
} else {
|
||||
// 先左旋后右旋
|
||||
node?.left = leftRotate(node: node?.left)
|
||||
return rightRotate(node: node)
|
||||
}
|
||||
}
|
||||
// 右偏树
|
||||
if balanceFactor < -1 {
|
||||
if self.balanceFactor(node: node?.right) <= 0 {
|
||||
// 左旋
|
||||
return leftRotate(node: node)
|
||||
} else {
|
||||
// 先右旋后左旋
|
||||
node?.right = rightRotate(node: node?.right)
|
||||
return leftRotate(node: node)
|
||||
}
|
||||
}
|
||||
// 平衡树,无需旋转,直接返回
|
||||
return node
|
||||
}
|
||||
[class]{AVLTree}-[func]{rotate}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
|
|
@ -120,27 +120,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="binary_search_tree.swift"
|
||||
/* 查找结点 */
|
||||
func search(num: Int) -> TreeNode? {
|
||||
var cur = root
|
||||
// 循环查找,越过叶结点后跳出
|
||||
while cur != nil {
|
||||
// 目标结点在 cur 的右子树中
|
||||
if cur!.val < num {
|
||||
cur = cur?.right
|
||||
}
|
||||
// 目标结点在 cur 的左子树中
|
||||
else if cur!.val > num {
|
||||
cur = cur?.left
|
||||
}
|
||||
// 找到目标结点,跳出循环
|
||||
else {
|
||||
break
|
||||
}
|
||||
}
|
||||
// 返回目标结点
|
||||
return cur
|
||||
}
|
||||
[class]{BinarySearchTree}-[func]{search}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -266,39 +246,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="binary_search_tree.swift"
|
||||
/* 插入结点 */
|
||||
func insert(num: Int) -> TreeNode? {
|
||||
// 若树为空,直接提前返回
|
||||
if root == nil {
|
||||
return nil
|
||||
}
|
||||
var cur = root
|
||||
var pre: TreeNode?
|
||||
// 循环查找,越过叶结点后跳出
|
||||
while cur != nil {
|
||||
// 找到重复结点,直接返回
|
||||
if cur!.val == num {
|
||||
return nil
|
||||
}
|
||||
pre = cur
|
||||
// 插入位置在 cur 的右子树中
|
||||
if cur!.val < num {
|
||||
cur = cur?.right
|
||||
}
|
||||
// 插入位置在 cur 的左子树中
|
||||
else {
|
||||
cur = cur?.left
|
||||
}
|
||||
}
|
||||
// 插入结点 val
|
||||
let node = TreeNode(x: num)
|
||||
if pre!.val < num {
|
||||
pre?.right = node
|
||||
} else {
|
||||
pre?.left = node
|
||||
}
|
||||
return node
|
||||
}
|
||||
[class]{BinarySearchTree}-[func]{insert}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -530,71 +478,9 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="binary_search_tree.swift"
|
||||
/* 删除结点 */
|
||||
@discardableResult
|
||||
func remove(num: Int) -> TreeNode? {
|
||||
// 若树为空,直接提前返回
|
||||
if root == nil {
|
||||
return nil
|
||||
}
|
||||
var cur = root
|
||||
var pre: TreeNode?
|
||||
// 循环查找,越过叶结点后跳出
|
||||
while cur != nil {
|
||||
// 找到待删除结点,跳出循环
|
||||
if cur!.val == num {
|
||||
break
|
||||
}
|
||||
pre = cur
|
||||
// 待删除结点在 cur 的右子树中
|
||||
if cur!.val < num {
|
||||
cur = cur?.right
|
||||
}
|
||||
// 待删除结点在 cur 的左子树中
|
||||
else {
|
||||
cur = cur?.left
|
||||
}
|
||||
}
|
||||
// 若无待删除结点,则直接返回
|
||||
if cur == nil {
|
||||
return nil
|
||||
}
|
||||
// 子结点数量 = 0 or 1
|
||||
if cur?.left == nil || cur?.right == nil {
|
||||
// 当子结点数量 = 0 / 1 时, child = null / 该子结点
|
||||
let child = cur?.left != nil ? cur?.left : cur?.right
|
||||
// 删除结点 cur
|
||||
if pre?.left === cur {
|
||||
pre?.left = child
|
||||
} else {
|
||||
pre?.right = child
|
||||
}
|
||||
}
|
||||
// 子结点数量 = 2
|
||||
else {
|
||||
// 获取中序遍历中 cur 的下一个结点
|
||||
let nex = getInOrderNext(root: cur?.right)
|
||||
let tmp = nex!.val
|
||||
// 递归删除结点 nex
|
||||
remove(num: nex!.val)
|
||||
// 将 nex 的值复制给 cur
|
||||
cur?.val = tmp
|
||||
}
|
||||
return cur
|
||||
}
|
||||
[class]{BinarySearchTree}-[func]{remove}
|
||||
|
||||
/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */
|
||||
func getInOrderNext(root: TreeNode?) -> TreeNode? {
|
||||
var root = root
|
||||
if root == nil {
|
||||
return root
|
||||
}
|
||||
// 循环访问左子结点,直到叶结点时为最小结点,跳出
|
||||
while root?.left != nil {
|
||||
root = root?.left
|
||||
}
|
||||
return root
|
||||
}
|
||||
[class]{BinarySearchTree}-[func]{getInOrderNext}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
|
|
@ -110,24 +110,7 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="binary_tree_bfs.swift"
|
||||
/* 层序遍历 */
|
||||
func hierOrder(root: TreeNode) -> [Int] {
|
||||
// 初始化队列,加入根结点
|
||||
var queue: [TreeNode] = [root]
|
||||
// 初始化一个列表,用于保存遍历序列
|
||||
var list: [Int] = []
|
||||
while !queue.isEmpty {
|
||||
let node = queue.removeFirst() // 队列出队
|
||||
list.append(node.val) // 保存结点值
|
||||
if let left = node.left {
|
||||
queue.append(left) // 左子结点入队
|
||||
}
|
||||
if let right = node.right {
|
||||
queue.append(right) // 右子结点入队
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
[class]{}-[func]{hierOrder}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
@ -286,38 +269,11 @@ comments: true
|
|||
=== "Swift"
|
||||
|
||||
```swift title="binary_tree_dfs.swift"
|
||||
/* 前序遍历 */
|
||||
func preOrder(root: TreeNode?) {
|
||||
guard let root = root else {
|
||||
return
|
||||
}
|
||||
// 访问优先级:根结点 -> 左子树 -> 右子树
|
||||
list.append(root.val)
|
||||
preOrder(root: root.left)
|
||||
preOrder(root: root.right)
|
||||
}
|
||||
[class]{}-[func]{preOrder}
|
||||
|
||||
/* 中序遍历 */
|
||||
func inOrder(root: TreeNode?) {
|
||||
guard let root = root else {
|
||||
return
|
||||
}
|
||||
// 访问优先级:左子树 -> 根结点 -> 右子树
|
||||
inOrder(root: root.left)
|
||||
list.append(root.val)
|
||||
inOrder(root: root.right)
|
||||
}
|
||||
[class]{}-[func]{inOrder}
|
||||
|
||||
/* 后序遍历 */
|
||||
func postOrder(root: TreeNode?) {
|
||||
guard let root = root else {
|
||||
return
|
||||
}
|
||||
// 访问优先级:左子树 -> 右子树 -> 根结点
|
||||
postOrder(root: root.left)
|
||||
postOrder(root: root.right)
|
||||
list.append(root.val)
|
||||
}
|
||||
[class]{}-[func]{postOrder}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
|
|
@ -14,6 +14,7 @@ from docs.utils.extract_code_python import ExtractCodeBlocksPython
|
|||
from docs.utils.extract_code_java import ExtractCodeBlocksJava
|
||||
from docs.utils.extract_code_cpp import ExtractCodeBlocksCpp
|
||||
from docs.utils.extract_code_jsts import ExtractCodeBlocksJSTS
|
||||
from docs.utils.extract_code_swift import ExtractCodeBlocksSwift
|
||||
|
||||
|
||||
def build_markdown(md_path):
|
||||
|
@ -88,6 +89,7 @@ extractor_dict = {
|
|||
"cpp": ExtractCodeBlocksCpp(),
|
||||
"javascript": ExtractCodeBlocksJSTS(),
|
||||
"typescript": ExtractCodeBlocksJSTS(),
|
||||
"swift": ExtractCodeBlocksSwift(),
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
"""
|
||||
File: extract_code_python.py
|
||||
File: extract_code_cpp.py
|
||||
Created Time: 2023-02-07
|
||||
Author: Krahets (krahets@163.com)
|
||||
"""
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
"""
|
||||
File: extract_code_python.py
|
||||
File: extract_code_java.py
|
||||
Created Time: 2023-02-07
|
||||
Author: Krahets (krahets@163.com)
|
||||
"""
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
"""
|
||||
File: extract_code_python.py
|
||||
File: extract_code_jsts.py
|
||||
Created Time: 2023-02-07
|
||||
Author: Krahets (krahets@163.com)
|
||||
"""
|
||||
|
@ -17,10 +17,10 @@ class ExtractCodeBlocksJSTS(ExtractCodeBlocksJava):
|
|||
|
||||
# Pattern to match function names and class names
|
||||
self.func_pattern = r'(\s*)(function|private|public|)\s*(\S*)\(.*\)(:|)\s*(.*)\s+{\s*\n'
|
||||
self.class_pattern = r'class\s+(\w+)\s*\{'
|
||||
self.class_pattern = r'(public|)\s*class\s+(\w+)\s*\{'
|
||||
|
||||
self.func_pattern_keys = ["total", "ind", "prefix", "label", ":", "return"]
|
||||
self.class_pattern_keys = ["total", "label"]
|
||||
self.class_pattern_keys = ["total", "scope", "label"]
|
||||
|
||||
|
||||
# for code_path in glob.glob("codes/cpp/chapter_*/my_heap.cpp"):
|
||||
|
|
28
docs/utils/extract_code_swift.py
Normal file
28
docs/utils/extract_code_swift.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
"""
|
||||
File: extract_code_swift.py
|
||||
Created Time: 2023-02-08
|
||||
Author: Krahets (krahets@163.com)
|
||||
"""
|
||||
|
||||
import re
|
||||
import glob
|
||||
import sys, os.path as osp
|
||||
sys.path.append(osp.dirname(osp.dirname(osp.dirname(osp.abspath(__file__)))))
|
||||
from docs.utils.extract_code_java import ExtractCodeBlocksJava
|
||||
|
||||
|
||||
class ExtractCodeBlocksSwift(ExtractCodeBlocksJava):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
# Pattern to match function names and class names
|
||||
self.func_pattern = r'(\s*)(public|private|)\s*(static|)\s*(func|)\s*(\w+)\(.*\).+{\s*\n'
|
||||
self.class_pattern = r'(public|)\s*class\s+(\w+)\s*\{'
|
||||
|
||||
self.func_pattern_keys = ["total", "ind", "scope", "static", "func", "label"]
|
||||
self.class_pattern_keys = ["total", "scope", "label"]
|
||||
|
||||
|
||||
# for code_path in glob.glob("codes/cpp/chapter_*/my_heap.cpp"):
|
||||
# ext = ExtractCodeBlocksCpp()
|
||||
# ext.extract(code_path)
|
Loading…
Reference in a new issue