スウィフトリアライズLRUキャッシュ置換アルゴリズム

LRUは=最低使用、最低使用します

使用されるデータ構造:リンクリスト、ハッシュテーブル

使用するプログラミング言語:スウィフト

アイデアの説明:

  • (私は二重にリンクされたリストを使用)順序付きリストを維持
    • 尾に近いノードは、時間の早いがアクセスされ、
  • 新しいデータは、最初からリストを横断するとき
    • データがキャッシュ内にすでにある場合
      • どここの場所から削除ノードを通過した後にデータを取得します
      • 最後に、リストの先頭に挿入
    • データがキャッシュにない場合は、再度、2例に分け
      • キャッシュスペースがいっぱいになっていない場合
        • ヘッド部分は、リスト内に挿入されたノードに直接このデータ
      • キャッシュがいっぱいになっている場合
        • まずテール・ノードを削除します
        • 新しいノードは、リスト・ヘッダ・データに挿入されている(このアイデアは、ハッシュ・テーブルが含まれていません)

いくつかの詳細

  1. この演習の目的は、LRUキャッシュアルゴリズムを達成するために:コードのおなじみのリストを特定の実装二重にリンクされたリストを達成するために
  2. リストが、また、ハッシュテーブルの使用を使用します。
    • あなたはハッシュテーブルを使用しない場合
      • たびに新しいデータがリンクリストを横断する必要があるため、時間の複雑さはO(n)があります
    • あなたはハッシュテーブルを含める場合
      • データは、ハッシュ・テーブルがあるかどうかを照会することができるので、新たなデータがあるときはいつでも、時間の複雑さはO(1)に還元されます
      • 時間の思考のためのスペースをここで使用
  3. リンクリストの実装を使用しての欠点
    • 1)ポインタ情報を格納するための余分な空間を、より多くのメモリ空間を消費します。
    • 2)頻繁な挿入および欠失のリストは、頻繁なメモリ割り当てを引き起こし、Java言語は、また頻繁にGC(自動ガベージコレクタ)動作を引き起こす可能性がある場合、メモリの断片化を引き起こす可能性、放出します。
  4. 配列の実装を使用しての欠点
    • 1)このよう100Mのような大きなメモリ空間のためのアプリケーション、もし、時間のない連続空間の100Mメモリ空間が存在しない場合、アプリケーションはさらに100M上で利用可能なメモリ空間が、失敗します。
    • 2)サイズは収納スペースが不足している場合、拡大の必要性は、拡張は、データ・レプリケーション一度行われるが、今回は非常に時間がかかり、固定です。

(リスト及びハッシュテーブルに基づいて)特定のコード

リスト:

// 节点
public class LinkedListNode<K, V> {
    
    var key: K?
    var value: V?
    var next: LinkedListNode?
    weak var previous: LinkedListNode?
    
    public init(key: K? ,value: V?) {
        self.key = key
        self.value = value
    }
}


// 双向链表
class LinkedList<K, V> : NSObject {
    
    public typealias Node = LinkedListNode<K, V>
    
    // 头节点,私有
    private var head: Node?
    
    // 获取链表第一个元素
    public var first: Node? {
        return head
    }
    
    // 获取链表最后一个元素
    public var last: Node? {
        
        guard var node = head else {
            return nil
        }
        
        while let next = node.next {
            node = next
        }
        return node
    }
    
    
    // 检查链表是否为空
    public var isEmpty: Bool {
        return head == nil
    }
    
    
    // 获取链表的长度
    public var count: Int {
        
        guard var node = head else {
            // head为nil,空链表
            return 0
        }
        
        // 循环,知道node为nil为止
        var count = 1
        while let next = node.next {
            node = next
            count += 1
        }
        return count
    }
    
    
    // 在指定的index获取node
    public func node(atIndex index: Int) ->Node? {
        
        guard index != 0 else {
            // 是head
            return head
        }
        
        var node = head!.next
        
        guard index < 0 else {
            return nil
        }
        
        for _ in 1..<index {
            node = node?.next
            if node == nil {
                break
            }
        }
        return node!
    }
    
    
    // 在链表尾部插入元素
    public func appendToTail(node: Node) {
        
        let newNode = node
        
        if let lastNode = last {
            
            // 尾节点存在
            newNode.previous = lastNode
            lastNode.next = newNode
            
        } else {
            
            // 尾节点不存在
            head = newNode
            
        }
    }
    
    
    // 在链表的头部插入元素
    public func insertToHead(node: Node) {
        
        let newNode = node
        
        if head == nil {
            
            head = newNode
            
        } else {
            
            newNode.next = head
            head?.previous = newNode
            head = newNode
            
        }
        
    }
    
    
    // 在指定位置插入元素
    public func insert(_ node: Node, atIndex index: Int) {
        
        if (index < 0) {
            print("invalid input index")
            return
        }
        
        let newNode = node
        
        if count == 0 {
            
            head = newNode
            
        } else {
            
            if index == 0 {
                
                // 插入到链表头部,特殊处理
                newNode.next = head
                head?.previous = newNode
                head = newNode
                
            } else {
                
                guard index <= count else {
                    print("out of range")
                    return
                }
                
                let prev = self.node(atIndex: index - 1)
                let next = prev?.next
                
                newNode.previous = prev
                newNode.next = prev?.next
                prev?.next = newNode
                next?.previous = newNode
                
            }
            
        }
        
    }
    
    
    // 删除全部元素
    public func removeAll() {
        head = nil
    }
    
    
    // 删除最后一个元素
    public func removeLast() -> V? {
        guard !isEmpty else {
            return nil
        }

        return remove(node: last!)
    }
    
    
    // 删除指定的元素
    public func remove(node: Node) -> V? {
        
        guard head != nil else {
            print("链表为空")
            return nil
        }
        
        
        let prev = node.previous
        let next = node.next
        
        
        if let prev = prev {
            prev.next = next
        } else {
            head = next
        }
        
        
        next?.previous = prev
        
        node.previous = nil
        node.next = nil
        
        return node.value
    }
    
    
    // 删除指定index的元素
    public func removeAt(_ index: Int) -> V? {
        
        guard head != nil else {
            print("linked list is empty")
            return nil
        }
        
        let node = self.node(atIndex: index)
        guard node != nil else {
            return nil
        }
        return remove(node: node!)
    }
}
复制代码

LRUキャッシュアルゴリズム:

class LRUStrategy<K: Hashable, V>: NSObject {

    let capacity: Int
    var length = 0
    
    private let queue: LinkedList<K, V>
    private var hashtable: [K: LinkedListNode<K, V>]
    
    
    /*
      LRU(Least Recently Used) Cache, 
		capacity是确定缓存的最大值
     */
    init(capacity: Int) {
        self.capacity = capacity
        
        self.queue = LinkedList()
        self.hashtable = [K: LinkedListNode<K, V>](minimumCapacity: self.capacity)
    }
    
    // swift的下标语法,在这是LRUStrategy类哈希化后,get set的语法糖
    subscript (key: K) -> V? {
        get {
            if let node = self.hashtable[key] {
                _ = self.queue.remove(node: node)
                self.queue.insertToHead(node: node)
                return node.value
            } else {
                return nil
            }
        }
        
        set(value) {
            if let node = self.hashtable[key] {
                node.value = value
                
                _ = self.queue.remove(node: node)
                self.queue.insertToHead(node: node)
            } else {
                let node = LinkedListNode(key: key, value: value)
                
                if self.length < capacity {
                    // 队列还没有满
                    self.queue.insertToHead(node: node)
                    self.hashtable[key] = node
                    
                    self.length = self.length + 1
                } else {
                    // 队列满了
                    self.hashtable.removeValue(forKey: self.queue.last!.key!)
                    _ = self.queue.removeLast()
                    
                    if let node = self.queue.last {
                        node.next = nil
                    }
                    
                    self.queue.insertToHead(node: node)
                    self.hashtable[key] = node
                }
            }
        }
    }
}

复制代码

おすすめ

転載: blog.csdn.net/weixin_34037173/article/details/91368727