IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> LRU算法-golang -> 正文阅读

[数据结构与算法]LRU算法-golang

1.思路

? a.以内要快速访问,查找,删除,查询操作要快,首先想到的就kv存储,即map数据结构。同时要删除和插入的时间复杂度o(1),链表具有该种特性。但是缓存中需要有顺序之分,而链表也是有序的,并且为了区分最近使用跟许久未使用的情况。使用头部作为最近使用的节点,而尾部都是许久未使用的,并且设置淘汰容量,当加入新元素,发现容量满了,就将许久未使用的淘汰掉,腾出空间,再存储新的即可。

? b.使用双向链表的原因是,移动节点到头部or淘汰元素时,需要前驱节点的支撑,所有在链表中使用双向链表。

? c.map控制缓存节点的快速访问,查找与删除,双向链表设置头尾指针控制访问时的节点移动到头部分,以及淘汰时的尾部节点的的淘汰处理。

? d.新加入节点,直接头插法插入链表中。访问某个节点,并将该节点设置为最新访问的头节点。更新节点,同样需要将该节点移动到头部,设置成最新访问节点。

? e.存储的结构图形:

2.代码:

package main

import (
	"fmt"
)

type Node struct {
	Key, Val   interface{}
	Prev, Next *Node
}

type LRUCache struct {
	Size       int // 节点的数量
	Cap        int // 容量
	Cache      map[interface{}]*Node
	Head, Tail *Node // 头尾节点

}

func CreateCache(cap int) *LRUCache {
	return &LRUCache{
		Size:  0,
		Cap:   cap,
		Cache: map[interface{}]*Node{},
		Head:  nil,
		Tail:  nil,
	}
}

// 设置当前节点为新的头节点
func (l *LRUCache) SetHead(node *Node) {
	node.Next = l.Head
	node.Prev = nil
	if l.Head == nil {
		l.Head = node
	} else {
		l.Head.Prev = node
		l.Head = node
	}
	if l.Tail == nil {
		l.Tail = node
	}
}

// 移动当前节点到头节点
func (l *LRUCache) MoveNodeToHead(node *Node) {
	// 更新节点,头节点不为空,并且移动的节点非头节点
	// 如果是本身就是头节点,或者此时头尾相同,不作处理,如果是尾节点,需要移动
	if l.Head != node && l.Tail == node {
		// Tail的前缀节点跟Tail断链
		prefix := l.Tail.Prev
		l.Tail.Prev = nil
		prefix.Next = nil
		// 移动至头
		l.Tail.Next = l.Head
		l.Head.Prev = l.Tail
		l.Tail = prefix // 尾部节点上移动
	}
	// 处于中间节点
	if l.Head != node && l.Tail != node {
		// 拆出来node
		prefix := node.Prev
		prefix.Next = node.Next
		node.Next.Prev = prefix

		// 移动到头部
		node.Next = l.Head
		node.Prev = nil
		l.Head.Prev = node
		l.Head = node
	}
}

// Add Node
func (l *LRUCache) AddNode(key, val interface{}) {
	if _, ok := l.Cache[key]; ok {
		// 如果存在,直接更新
		l.Cache[key].Val = val
		// 移动该节点至头部
		l.MoveNodeToHead(l.Cache[key])
	} else {
		node := &Node{
			Key: key,
			Val: val,
		}
		// 检查容量是否超标
		if l.Size >= l.Cap {
			delNode := l.RemoveLastNode() // 链表断链
			delete(l.Cache, delNode.Key)  // Cache清理
			l.Size--                      // 节点数量递减
		}
		// map中存储节点
		l.Cache[key] = node
		// 将节点移动到头部
		l.SetHead(node)
		// 节点数量
		l.Size++
	}
}

// 移除很久没访问的节点,腾出空间
func (l *LRUCache) RemoveLastNode() *Node {
	delNode := l.Tail
	if l.Tail != nil {
		l.Tail = l.Tail.Prev   // tail指向最近没访问的倒数第二节点
		l.Tail.Next.Prev = nil // 当前节点的prev断链
		l.Tail.Next = nil
	}
	return delNode
}

// 访问某个节点,访问之后,同样将访问的节点移动到头部
func (l *LRUCache) GetNode(key interface{}) *Node {
	var retNode *Node
	if _, ok := l.Cache[key]; ok {
		retNode = l.Cache[key]
		// 移动当前节点至头部
		l.MoveNodeToHead(l.Cache[key])
	}
	return retNode
}

func (l *LRUCache) Show() {
	for k, _ := range l.Cache {
		fmt.Println(l.Cache[k].Key, "=", l.Cache[k].Val)
	}
}

func (l *LRUCache) ShowList() {
	for h := l.Head; h != nil; h = h.Next {
		fmt.Println(h.Key, "+", h.Val)
	}
}

func main() {

	// 创建一个哈希链表
	lru := CreateCache(2)

	// lru.AddNode(1, 1)
	// lru.AddNode(2, 2)
	// lru.AddNode(3, 3) // 调用淘汰
	// lru.AddNode(4, 4) // 调用淘汰

	for i := 0; i < 10; i++ {
		lru.AddNode(i, i)
	}
	// lru.Show()
	lru.ShowList()

}

运行结果:

9 + 9
8 + 8

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-02-28 15:50:37  更:2022-02-28 15:53:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 16:44:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码