Swift堆数据结构

时间:2020-02-23 14:44:01  来源:igfitidea点击:

在本教程中,我们将讨论并在Swift中实现Heap数据结构。

Swift堆

堆可以是最大堆,也可以是最小堆。
在最大堆中,根节点是最大的元素,所有子节点必须小于父节点。
最小堆的工作方式恰恰相反。
堆是一种特殊的基于树的数据结构。
堆数据结构可用于有效地找到数组中第k个最小(或者最大)的元素。

堆属性:如果P是C的父节点,则P的键(值)大于或者等于(在最大堆中)或者小于或者等于(在最小堆中)C的键。

顶部的节点是最高优先级的节点。

堆化

删除元素需要重新排列堆数据结构。
这称为堆化。

例如,如果删除堆的根节点。
为此,我们需要将其与根节点之间的最低节点交换,然后在整个过程中递归检查堆属性。

heapifyUp()从底部开始,并一直检查堆属性。

heapifyDown()恰好相反

N处的节点的子代将在最大堆中定位为" 2n + 1"和" 2n + 2"。

让我们启动XCode运动场,并使用Swift创建我们的堆。
我们将使用数组构建堆结构。

建立一个堆

struct Heap<T> {
  var elements = [T]()
  
  var isEmpty: Bool { return elements.isEmpty }
  var count: Int { return elements.count }
  var isOrdered: (T, T) -> Bool
  
  public init(sort: @escaping (T, T) -> Bool) {
      self.isOrdered = sort
  }

}

传递了转义的闭包,用于保存函数值。
它比较传递的两个值。

在结构中添加以下函数以获取父节点,左节点和右节点的索引:

func parentOf(_ index: Int) -> Int {
      return (index - 1)/2
  }
  func leftOf(_ index: Int) -> Int {
      return (2 * index) + 1
  }
  func rightOf(_ index: Int) -> Int {
      return (2 * index) + 2
  }

heapifyDown():

mutating func heapifyDown(index: Int, heapSize: Int) {

      var parentIndex = index
      
      while true {
          let leftIndex = self.leftOf(parentIndex)
          let rightIndex = leftIndex + 1
          
          var first = parentIndex
          if leftIndex < heapSize && isOrdered(elements[leftIndex], elements[first]) {
              first = leftIndex
          }
          if rightIndex < heapSize && isOrdered(elements[rightIndex], elements[first]) {
              first = rightIndex
          }
          if first == parentIndex { return }
          
          elements.swapAt(parentIndex, first)
          parentIndex = first
      }
  }

mutating func shiftDown() {
      heapifyDown(index: 0, heapSize: elements.count)
  }

在删除元素时使用heapifyDown()。
插入时使用heapifyUp()。

以下函数用于从数组构建堆:

mutating func buildHeap(fromArray array: [T]) {
      elements = array
      for i in stride(from: (elements.count/2 - 1), through: 0, by: -1) {
          heapifyDown(index: i, heapSize: elements.count)
      }
  }

heapifyUp():

mutating func heapifyUp(index: Int) {
      var nodeIndex = index
      
      while true {
          let parentIndex = self.parentOf(nodeIndex)
          
          var first = parentIndex
          if parentIndex >= 0 && isOrdered(elements[nodeIndex], elements[first]) {
              first = nodeIndex
          }
          if first == parentIndex { return }
          

          elements.swapAt(parentIndex, first)
          nodeIndex = first
      }
  }

以下函数用于从堆中插入和删除元素:

插入:

mutating func insert(value: T) {
      self.elements.append(value)
      
      heapifyUp(index: self.elements.count - 1)
  }

删除:

public mutating func remove(at index: Int) -> T? {
      let temp: T
      
      if index < 0 && count - 1 <= index {
          return nil
      }
      temp = elements[index]
      elements[index] = elements[count - 1]
      elements.removeLast()
      shiftDown()
      return temp
  }

让我们使用示例输入来测试我们创建的上述结构:

let array: [Int] = [12,3,6,15,45,1,2]
var heap = Heap<Int>(sort: >)
heap.buildHeap(fromArray: array)
heap.insert(value: 23)
print(heap.elements)
print(heap.remove(at: 0))
print(heap.elements)