Heap(堆结构/优先队列)-Swift实现
生活随笔
收集整理的這篇文章主要介紹了
Heap(堆结构/优先队列)-Swift实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
特性
堆結構很像二叉樹,堆也是一個近似樹形結構,堆的每個節點也最多有左、右兩個孩子,但是堆實質是存儲在數組中的結構,所以他和二叉樹只是近似的有某些共同的特性。
- 第一特性,堆結構是存儲在數組中的。
- 堆通過 priority 優先事項進行排序,可以分為,max-priority(最高優先級)、和 max-priority(最低優先級)兩種
- 二叉搜索樹中,有left<parent<right 的特性,但是在堆中,只是只能保證孩子一定是小于或大于父節點的。
- 二叉樹在存儲的過程中需要更多的內存,因為節點需要存儲指向父節點,子節點等的指針,但是堆不需要,他存儲在數組中
- 二叉樹中的一些特別樹,如紅黑樹,AVL樹等,刪除,插入,及搜索的多度都很快,但是,堆結構的搜索相對來說會慢很多,但是堆結構對于查找,最大或者最小等需求時,查找速度是很快的。
- 堆有一個很重要的特性,就是只有在上一層完全滿之后,才能到下一層來進行存儲,不允許中間某個節點的子節點為空,因為是通過數組存儲的嘛
前面說過堆結構實際存儲在數組中,他具體的形式如下
從上面的圖中可以推導出,一個重要的公式: 節點 node 的孩子在數組中的位置: 左孩子:index = 2 * i + 1 右孩子:index = 2 * i + 2 其中i為當前節點n在數組中的下標
插入及刪除
堆結構的插入及刪除操作的基本思路如下:
- 插入: 插入時一定是從最后面開始插入,類似入隊操作,插入后,用新節點和父節點比,如果優先級大于父節點,則和父節點交互位置后,繼續和新的父節點比較,依次類推
- 刪除:刪除通常為刪除最大的節點,即根節點,過程為,先將根節點和最后面的節點互換位置后,在刪除最后面的節點,即原來的根節點,然后用根節點和子節點向下進行比較,如果小于子節點,則互換位置,依次類推。 時刻謹記,堆結構是存儲在數組中的。
實現
struct Heap<Element> {///存放元素的數組var elements: [Element]//比較兩個元素大小的方法let priorityFunction: (Element, Element) -> Boolinit(elements: [Element] = [], priorityFunction: @escaping (Element, Element) -> Bool) { // 1 // 2self.elements = elementsself.priorityFunction = priorityFunction // 3buildHeap() // 4}mutating func buildHeap() {for index in (0 ..< count / 2).reversed() { // 5siftDown(index) // 6}}var isEmpty : Bool {return elements.isEmpty}var count : Int {return elements.count}func peek() -> Element? {return elements.first}func isRoot(_ index: Int) -> Bool {return (index == 0)}///當前節點的左孩子func leftChildIndex(of index: Int) -> Int {return (2 * index) + 1}///當前節點的右孩子func rightChildIndex(of index: Int) -> Int {return (2 * index) + 2}///當前節點的父節點func parentIndex(of index: Int) -> Int {return (index - 1) / 2}//插入 mutating func equeue(_ element: Element) {elements.append(element)siftUP(elementAtIndex: elements.count - 1)}//刪除mutating func dequeue() -> Element? {//判空guard !isEmpty else { return nil }//將第一個節點和最后一個節點交換位置swapElement(at: 0, with: count - 1)//刪除原本的第一個,現在的最后一個elements.removeLast()guard !isEmpty else { return nil }//向下判斷,新的節點是不是優先級最高的節點return nil} }private extension Heap {func isHigherPriority(firstIndex: Int, secondIndex: Int) -> Bool{return priorityFunction(elements[firstIndex], elements[secondIndex])}func highestPriorityIndex(of parentIndex: Int, and childIndex: Int) -> Int {guard childIndex < count && isHigherPriority(firstIndex: childIndex, secondIndex: parentIndex)else { return parentIndex }return childIndex}func highestPriorityIndex(for parent: Int) -> Int {return highestPriorityIndex(of: highestPriorityIndex(of: parent, and: leftChildIndex(of: parent)), and: rightChildIndex(of: parent))}mutating func swapElement(at firstIndex: Int, with secondIndex: Int) {guard firstIndex != secondIndexelse { return }elements.swapAt(firstIndex, secondIndex)}mutating func siftDown(_ elementIndex: Int) {//從當前節點及子節點中找出優先級最高的節點let highestIndex = highestPriorityIndex(for: elementIndex)//如果當前節點就是優先級最高的節點,直接放回if highestIndex == elementIndex { return }//如果不是優先級最高的節點,和優先級最高的節點對換位置swapElement(at: elementIndex, with: highestIndex)//從新的節點開始遞歸的向下判斷優先級siftDown(highestIndex)}mutating func siftUP(elementAtIndex: Int) {//獲得父節點的索引let parentIndex = self.parentIndex(of: elementAtIndex)//如果當前節點不是根節點,比較當前節點和父節點的優先級guard !isRoot(elementAtIndex), isHigherPriority(firstIndex: elementAtIndex, secondIndex: parentIndex) else {return}//如果當前節點的優先級高于父節點,兌換位置swapElement(at: elementAtIndex, with: parentIndex)//遞歸的從新的父節點開始向上比較siftUP(elementAtIndex: parentIndex)} } 復制代碼總結
以上是生活随笔為你收集整理的Heap(堆结构/优先队列)-Swift实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vscode中PyLint报错Unabl
- 下一篇: Linux input子系统 io控制字