iOS 数据结构&算法

246 阅读3分钟

参考来源:

stack

// 用数组实现栈-简易
class Stack {
    var stack: [AnyObject]
    var isEmpty: Bool {return stack.isEmpty}
    var size: Int { return stack.count }
    var peek: AnyObject? {return stack.last}
    init() {
        stack = [AnyObject]()
    }
    func push(object: AnyObject) {
        stack.append(object)
    }
    func pop() -> AnyObject? {
        if (!isEmpty) {
            return stack.removeLast()
        } else {
            return nil
        }
    }
}
// 用数组实现栈-全面
protocol Stack {
    // 持有的数据类型
    associatedtype Element
    // 是否为空
    var isEmpty: Bool {get}
    // 栈大小
    var size: Int {get}
    // 栈顶元素
    var peek: Element? {get}
    // 进栈
    mutating func push(_ newElement: Element)
    // 出栈
    mutating func pop() -> Element?
}
struct IntegerStack: Stack {
    typealias Element = Int
    private var stack = [Element]()
    var isEmpty: Bool { return stack.isEmpty }
    var size: Int { return stack.count }
    var peek: Element? { return stack.first }
    mutating func push(_ newElement: Element) {
        stack.append(newElement)
    }
    mutating func pop() -> Element? {
        return stack.popLast()
    }
}

队列

image.png

protocol Queue {
    // 持有的数据类型
    associatedtype Element
    // 是否为空
    var isEmpty: Bool { get }
    // 队列长度
    var size: Int { get }
    // 队首元素
    var peek: Element? { get }
    // 入队
    mutating func enqueue(_ newElement: Element)
    // 出队
    mutating func dequeue() -> Element?
}
struct IntegerQueue: Queue {
    typealias Element = Int
    private var left = [Element]()
    private var right = [Element]()
    var isEmpty: Bool { return left.isEmpty && right.isEmpty }
    var size: Int { return left.count + right.count }
    var peek: Element? {return left.isEmpty ? right.first : left.first }
    mutating func enqueue(_ newElement: Int) {
        right.append(newElement)
    }
    mutating func dequeue() -> Element? {
        if left.isEmpty {
            left = right.reversed()
            right.removeAll()
        }
        return left.popLast()
    }
}

栈和队列互相转换

// 用栈实现队列
struct MyQueue {
    var stackA: Stack //上文的简易Stack
    var stackB: Stack
    init() {
        stackA = Stack()
        stackB = Stack()
    }
    var isEmpty: Bool {
        return stackA.isEmpty && stackB.isEmpty
    }
    var size: Int {
        get {
            return stackA.size + stackB.size
        }
    }
    fileprivate mutating func shift() {
        if stackB.isEmpty {
            while !stackA.isEmpty {
                stackB.push(stackA.pop()!)
            }
        }
    }
    var peek: Any? {
        mutating get {
            shift()
            return stackB.peek
        }
    }
    mutating func enqueue(object: AnyObject) {
        stackA.push(object);
    }
    mutating func dequeue() -> Any? {
        shift()
        return stackB.pop()
    }
}

// 用队列实现栈
struct MyStack {
    var queueA: IntegerQueue
    var queueB: IntegerQueue
    init() {
        queueA = IntegerQueue()
        queueB = IntegerQueue()
    }
    var isEmpty: Bool {
        return queueA.isEmpty && queueB.isEmpty
    }
    var size: Int {
        return queueA.size
    }
    private mutating func shift() {
        while queueA.size != 1 {
            queueB.enqueue(queueA.dequeue()!)
        }
    }
    private mutating func swap() {
        (queueA, queueB) = (queueB, queueA)
    }
    var peek: Any? {
        mutating get {
            shift()
            let peekObj = queueA.peek
            queueB.enqueue(queueA.dequeue()!)
            swap()
            return peekObj
        }
    }
    mutating func push(object: Int) {
        queueA.enqueue(object)
    }
    mutating func pop() -> Any? {
        shift()
        let popObj = queueA.dequeue()
        swap()
        return popObj
    }
}

链表

// 链表
class ListNode {
    var val: Int
    var next: ListNode?
    init(_ val: Int) {
        self.val = val
        self.next = nil
    }
}
class List {
    var head: ListNode?
    var tail: ListNode?
    // 尾插法
    func appendToTail(_ val: Int) {
        if tail == nil {
            tail = ListNode(val)
            head = tail
        } else {
            tail!.next = ListNode(val)
            tail = tail!.next
        }
    }
    // 头插法
    func appendToHead(_ val: Int) {
        if head == nil {
            head = ListNode(val)
            tail = head
        } else {
            let tmp = ListNode(val)
            tmp.next = head
            head = tmp
        }
    }
}

二叉树

class TreeNode {
    public var val: Int
    public var left: TreeNode?
    public var right: TreeNode?
    public init(_ val: Int) {
        self.val = val
    }
}

排序

归并排序

func mergeSort(_ array: [Int]) -> [Int] {
    var helper = Array(repeating: 0, count: array.count), array = array
    mergeSort(&array, &helper, 0, array.count - 1)
    return array
}
func mergeSort(_ array: inout [Int], _ helper: inout [Int], _ low: Int, _ high: Int) {
    guard low < high else {
        return
    }
    let middle = (high - low) / 2 + low
    mergeSort(&array, &helper, low, middle)
    mergeSort(&array, &helper, middle+1, high)
    mergeSort(&array, &helper, low, middle, high)
}
func mergeSort(_ array: inout [Int], _ helper: inout [Int], _ low: Int, _ middle: Int, _ high: Int) {
    // copy both halves into a helper array
    for i in low ... high {
        helper[i] = array[i]
    }
    var heplerLeft = low, helperRight = middle + 1
    var current = low
    // iterate through helper array and copy the right one to original array
    while heplerLeft <= middle && helperRight <= high {
        if helper[heplerLeft] <= helper[helperRight] {
            array[current] = helper[heplerLeft]
            heplerLeft += 1
        } else {
            array[current] = helper[helperRight]
            helperRight += 1
        }
        current += 1
    }
    // handle the rest
    guard middle - heplerLeft >= 0 else {
        return
    }
    for i in 0 ... middle - heplerLeft {
        array[current + i] = helper[heplerLeft + i]
    }
}
print(mergeSort([9,11,3,7,6,5]))

快速排序

func quicksort(_ array:[Int]) -> [Int] {
    guard array.count > 1 else {
        return array
    }
    let pivot = array[array.count / 2]
    let left = array.filter { $0 <  pivot }
    let middle = array.filter { $0 == pivot }
    let right = array.filter {$0 > pivot }
    return quicksort(left) + middle + quicksort(right)
}
print(quicksort([1,3,5,4,2]))

搜索

二分搜索

// 假设 nums 是一个升序数组
func binarySearch(_ nums: [Int], _ target: Int) -> Bool {
    var left = 0, mid = 0, right = nums.count - 1
    while left <= right {
        mid = (right - left) / 2 + left
        if nums[mid] == target {
            return true
        } else if nums[mid] < target {
            left = mid + 1
        } else {
            right = mid - 1
        }
    }
    return false
}
print(binarySearch([1,2,5,6,8], 3))

深度优先搜索和广度优先搜索

DFS

// DFS 实现
func dfs(_ root: Node?) {
    guard let root = root else {
        return
    }
    visit(root)
    root.visited = true
    for node in root.neighbors {
        if !node.visited {
            dfs(node)
        }
    }
}

BFS

// BFS 实现
func bfs(_ root: Node?) {
    var queue = [Node]()
    if let root = root {
        queue.append(root)
    }
    while !queue.isEmpty {
        let current = queue.removeFirst()
        visit(current)
        current.visited = true 
        for node in current.neighbors {
            if !node.visited {
                queue.append(node)
            }
        }
    }
}

动态规划

斐波拉契数列问题

// F(n) = F(n-1) + F(n-2), n >= 2
// 简单粗暴的办法。-- 爆炸💥
func Fib() -> Int {
    var (prev, curr) = (0, 1)
    for _ in 1 ..< 100 {
        (curr, prev) = (curr + prev, curr)
    }
    return curr
}
// 动态规划解法
func Fib(_ n: Int) -> Int {
    // 定义初始状态
    guard n > 0 else {
        return 0
    }
    if n == 1 || n == 2 {
        return 1
    }
    // 调用动态转化方程
    return Fib(n - 1) + Fib(n - 2)
}
//print(Fib(100)) // -- 电脑爆炸

// 用一个数组将计算过的值存起来,牺牲内存换效率
var nums = Array(repeating: 0, count: 100)
func Fib1(_ n: Int) -> Int {
    // 定义初始状态
    guard n > 0 else {
        return 0
    }
    if n == 1 || n == 2 {
        return 1
    }
    // 如果已经计算过,则直接调用,无需重复计算
    if  nums[n - 1] != 0 {
        return nums[n - 1]
    }
    // 将计算后的值存入数组
    nums[n - 1] = Fib1(n - 1) + Fib1(n - 2)

    return nums[n - 1]
}
//Fib1(100)