• python实现双向链表以及fifo缓存置换算法


    双向链表:

    设计想法:

    实现链表节点:可以存放Key-Value数据

    实现双向链表:往头部增加节点、往尾部增加节点、删除任意节点、弹出尾部节点、弹出头部节点

    代码实现:

    #! -*- encoding=utf-8 -*-
    
    #prve和next是迭代器的方法
    
    # 链表节点:
    class Node:
        def __init__(self, key, value):
            self.key = key      #
            self.value = value      #
            self.prev = None
            self.next = None
    
        def __str__(self):  # print实例时打印出来的内容,不定义可以调用,重新定义后则可以定制打印内容
            val = '{%d: %d}' % (self.key, self.value)
            return val
    
        def __repr__(self):  # 直接输出实例名打印出来的内容,不定义可以调用,重新定义后则可以定制打印内容
            val = '{%d: %d}' % (self.key, self.value)
            return val
    
    
    class DoubleLinkList:
        def __init__(self, capacity=0xffff):  # capacity是容量值
            self.capacity = capacity
            self.head = None
            self.tail = None
            self.size = 0  # 以上都是默认
    
        # 从头部添加:
        def __add_head(self, node):
            if not self.head:  # 没有节点
                self.head = node
                self.tail = node
                self.head.next = None
                self.head.prev = None
            else:
                node.next = self.head  # 新节点的next指向现在的head
                self.head.prev = node  # 把head的前向指针指向新节点
                self.head = node  # 把head指向新节点
                self.head.prev = None  # 把head的前向指针指向空
                self.size += 1
                return node
    
        # 从尾部添加节点:
        def __add_tail(self, node):
            if not self.tail:
                self.tail = node
                self.head = node
                self.tail.next = None
                self.tail.prev = None
            else:
                self.tail.next = node
                node.prev = self.tail
                self.tail = node
                self.tail.next = None
            self.size += 1
            return node
    
        #从尾部删除(弹出尾部节点)
        def __del_tail(self):
            if not self.tail:
                return
            node = self.tail
            if node.prev:
                self.tail = node.prev
                self.tail.next = None
            else:
                self.head = self.tail = None
            self.size -= 1
            return node
    
        # 从头部删除(弹出头部节点)
        def __del_head(self):
            if not self.head:   #没有头部节点
                return
            node = self.head    #取出头部节点
            if node.next:   #如果头部节点有下一个节点
                self.head = node.next
                self.head.prev = None
            else:   #如果头部节点没有下一个节点
                self.tail = self.head = None
            self.size -= 1
            return node
    
        # 任意节点删除:
        def __remove(self, node):
            # 如果node=None,默认删除尾部节点
            if not node:
                node = self.tail
            if node == self.tail:
                self.__del_tail()
            elif node == self.head:
                self.__del_head()
            else:
                node.prev.next = node.next  #被删除节点的上一个节点的next指针指向被删除节点的下一个节点
                node.next.prev = node.prev
                self.size -= 1
            return node
    
    
        #对外实现的api:
    
        #弹出头部节点:
        def pop(self):
            return  self.__del_head()
    
        #往尾部添加节点:
        def append(self, node):
            return self.__add_tail(node)
    
        #往头部添加节点:
        def append_front(self, node):
            return self.__add_head(node)
    
        #删除节点:
        def remove(self, node=None):    #默认为空
            return self.__remove(node)
    
        #打印当前链表
        def print(self):
            p = self.head
            line = ''   #存储链表的字符串
            while p:
                line += '%s' % p
                p = p.next
                if p:
                    line += '=>'
            print(line)
    
    
    #简单测试:#
    if __name__ == '__main__':
        l = DoubleLinkList(10)
        nodes = []
        for i in range(10):
            node = Node(i, i)
            nodes.append(node)      #往nodes列表的尾部增加
    
        l.append(nodes[0])
        l.print()
        l.append(nodes[1])
        l.print()
        l.pop()     #弹出头部节点
        l.print()
        l.append(nodes[2])  #尾部增加一个节点
        l.print()
        l.append_front(nodes[3])    #头部增加一个节点
        l.print()
        l.append(nodes[4])
        l.print()
        l.remove(nodes[2])  #删除节点2
        l.print()
        l.remove()  #默认删除尾部节点
        l.print()

    测试结果:

    {0: 0}
    {0: 0}=>{1: 1}
    {1: 1}
    {1: 1}=>{2: 2}
    {3: 3}=>{1: 1}=>{2: 2}
    {3: 3}=>{1: 1}=>{2: 2}=>{4: 4}
    {3: 3}=>{1: 1}=>{4: 4}
    {3: 3}=>{1: 1}


    FIFO(先进先出)缓存置换算法:

    #! -*- encoding=utf-8 -*-
    
    from computer_principle.doublelinkedlist import DoubleLinkedList, Node
    
    
    class FIFOCache(object):
        def __init__(self, capacity):
            self.capacity = capacity  # 容量大小
            self.size = 0
            self.map = {}  # 保存key和value的映射关系
            self.list = DoubleLinkedList(self.capacity)
    
        # 从缓存中获取key对应的value内容,如果key不存在就返回-1
        def get(self, key):
            if key not in self.map:
                return -1
            else:
                node = self.map.get(key)  # get是dict的方法,取出key对应的value
                return node.value
    
        # 添加一个缓存
        def put(self, key, value):
            if self.capacity == 0:
                return
            if key in self.map:  # 如果key已经存在,就把它的先删掉掉再放新的到最后
                node = self.map.get(key)
                self.list.remove(node)
                node.value = value  # 覆盖
                self.list.append(node)
            else:
                if self.size == self.capacity:  # 如果该key是新的,先判断缓存是否满了,满了要pop头部节点
                    node = self.list.pop()
                    del self.map[node.key]  # 本地映射map中删除这个head节点
                    self.size -= 1
                node = Node(key, value)  # 新增一个节点
                self.list.append(node)
                self.map[key] = node  # 本地map中增加这个节点的映射
                self.size += 1
    
        def print(self):
            self.list.print()
    
    
    # test:
    if __name__ == '__main__':
        cache = FIFOCache(2)
        cache.put(1, 1)
        cache.print()
        cache.put(2, 2)
        cache.print()
        print(cache.get(1))
        cache.put(3, 3)     # 淘汰了(1,1)
        cache.print()
        print(cache.get(2))
        cache.print()
        cache.put(4, 4)
        cache.print()
        print(cache.get(1))

    结果:

    {1: 1}
    {1: 1}=>{2: 2}
    1
    {2: 2}=>{3: 3}
    2
    {2: 2}=>{3: 3}
    {3: 3}=>{4: 4}
    -1

  • 相关阅读:
    Android 再次打开APP进入按Home键退出时的界面(thisTaskRoot)
    SQL server 安装成功到使用Sa SQL server验证登录等一系列问题
    Android JSON解析插件
    Android utils 工具类之MD5加密 MD5Utils
    Android 避免内存泄漏
    Android utils 之 日志工具类
    Android Studio 第一个Android项目
    Android Studio安装
    JDK 安装与环境配置配置——Android开发第一步
    U盘启动安装系统之旅----记录自己的第一次操作
  • 原文地址:https://www.cnblogs.com/marvintang1001/p/11125619.html
Copyright © 2020-2023  润新知