golang使用双向链表实现LRU算法

使用双向链表实现LRU算法

//使用双向链表实现的LRU算法
type LRUCache struct {
   Capacity int
   Store    map[int]*DbNode
   List     *DbList
}

//链表节点
type DbNode struct {
   Key  int
   Data int
   Pre  *DbNode
   Next *DbNode
}
//双向链表
type DbList struct {
   Size  int
   mutex *sync.RWMutex
   Head  *DbNode
   Tail  *DbNode
}

//往链表头部插入数据
func (d *DbList) AppendFront(node *DbNode) bool {
   if node == nil {
      return false
   }
   d.mutex.RLock()
   defer d.mutex.RUnlock()

   if d.Size == 0 {
      d.Head, d.Tail = node, node
      d.Size++
   } else {
      node.Next = d.Head
      d.Head.Pre = node
      d.Head = node
      d.Size++
   }

   return true
}

//将指定的链表节点移动到头部
func (d *DbList) MoveFront(node *DbNode) bool {
   if node == nil {
      return false
   }

   if d.Size <= 1 {
      return true
   }
   d.mutex.Lock()
   defer d.mutex.Unlock()

   switch node {
   case d.Head:
      return true
   case d.Tail:
      node.Pre.Next = nil
      d.Tail = node.Pre
      node.Pre, node.Next, d.Head.Pre = nil, d.Head, node
      d.Head = node
      return true
   default:
      node.Pre.Next, node.Next.Pre = node.Next, node.Pre
      d.Head.Pre, node.Next, node.Pre = node, d.Head, nil
      d.Head = node
      return true
   }
}

//删除指定的节点
func (d *DbList) Remove(node *DbNode) bool {
   if node == nil {
      return false
   }

   if d.Size == 0 {
      return true
   }
   d.mutex.Lock()
   defer d.mutex.Unlock()

   defer func(d *DbList, node *DbNode) {
      if err := recover(); err != nil {
         fmt.Println(err)
      }
   }(d, node)

   if node == d.Head && node == d.Tail {
      d.Head, d.Tail = nil, nil
   } else if node == d.Head {
      node.Next.Pre = nil
      d.Head = node.Next
   } else if node == d.Tail {
      node.Pre.Next = nil
      d.Tail = node.Pre
   } else {
      node.Pre.Next, node.Next.Pre = node.Next, node.Pre
   }

   d.Size--
   return true
}

//初始化LRU缓存
func Constructor(capacity int) LRUCache {
   return LRUCache{
      Capacity: capacity,
      Store:    make(map[int]*DbNode),
      List: &DbList{
         Size:  0,
         mutex: new(sync.RWMutex),
      },
   }
}

//获取LRU缓存数据
func (this *LRUCache) Get(key int) int {
   if node, ok := this.Store[key]; ok {
      if ok := this.List.MoveFront(node); ok {
         return node.Data
      }
   }

   return -1
}

//插入或者更新缓存
func (this *LRUCache) Put(key int, value int) {
   //判断是否有数据
   if node, ok := this.Store[key]; ok {
      this.List.MoveFront(node)
      node.Data = value
      return
   }

   //判断是否超过了容量,超过则清除最久
   if this.List.Size >= this.Capacity {
      delete(this.Store, this.List.Tail.Key)
      this.List.Remove(this.List.Tail)
   }

   //新增数据
   node := &DbNode{
      Key:  key,
      Data: value,
   }
   this.Store[key] = node
   this.List.AppendFront(node)
}

//
//["LRUCache","put","get","put","get","get"]
//[[1],[2,1],[2],[3,2],[2],[3]]

func main() {
   var str = "[[1],[2,1],[2],[3,2],[2],[3]]"
   var value [][]int
   var once sync.Once
   var cache LRUCache

   if err := json.Unmarshal([]byte(str), &value); err != nil {
      log.Printf("[ERROR] 反序列化失败, 错误信息:%s \n", err.Error())
      return
   }

   for index, item := range value {
      once.Do(func() {
         cache = Constructor(item[0])
      })

      switch len(item) {
      case 1:
         fmt.Println(cache.Get(item[0]))
      case 2:
         cache.Put(item[0], item[1])
      }
   }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值