zoukankan      html  css  js  c++  java
  • 03-链表

    链表的存储结构如图所示:

    单链表:

    循环链表:

     双向链表:

    双向循环链表

    单向链表添加数据动图:

    单链表代码实现:

    #单链表的实现
    class ListNode:
        def __init__(self,data=None):
            self.data = data
            self.next = None
    
        def __repr__(self):
            """
            输出格式化信息
            :return:
            """
            return "node: {}".format(self.data)
    
    
    class SingelLinkedList:
        def __init__(self, node=None):
            '''创建头节点_head指向第一个节点node'''
            self.__head = node
    
        def is_empty(self):
            '''判断是否空链表'''
            return self.__head is None
    
        def length(self):
            '''链表的长度'''
            current = self.__head  # 表示当前节点
            count = 0  # 用来统计已遍历的节点数目
            while current is not None:
                count += 1
                current = current.next  # 向后移动游标
            return count
    
        def ergodic(self):
            '''遍历整个链表'''
            current = self.__head  # 游标,用来表示当前节点
            while current is not None:
                yield current.data  # 生成当前节点的值
                current = current.next  # 向后移动游标
    
        def append(self, data):
            '''链表尾部添加节点'''
            node = ListNode(data)
            if self.is_empty():  # 如果是空链表
                self.__head = node
            else:
                current = self.__head
                while current.next is not None:
                    current = current.next
                # 此时,current 表示尾节点,将它的 next 指向新增的节点即可
                current.next = node
    
        def head_add(self, data):
            '''在链表的头部添加节点'''
            node = ListNode(data)
            node.next = self.__head  # 将新增节点的 next 指向原来的头节点
            self.__head = node  # 再将链表的 __head 属性指向新增节点即可
    
        def insert(self, pos, data):
            '''在指定位置添加节点。 pos 表示节点的下标,为了跟列表等一样,这里规定 pos 从0开始计数,即头节点的 pos 为0'''
            if pos <= 0:  # 暂时不支持负数的下标。如果传入负数或者0,统一在头部插入
                self.head_add(data)
            elif pos > self.length() - 1:  # 如果传入的下标大于链表的长度减去1,默认使用在尾部插入
                self.append(data)
            else:
                pre = self.__head  # 用来表示 pos - 1 位置的节点
                count = 0
                while count < pos - 1:  # 当count = pos - 1时,表示已经找到了 pos - 1 的节点,退出循环
                    count += 1
                    pre = pre.next  # 向后移动游标
                # 退出循环后,pre 指向 pos - 1 所在的节点
                node = ListNode(data)
                node.next = pre.next  # 将新增节点的 next 指向 pre 的下一节点
                pre.next = node  # 再将 pre 的 next 重新指向新增的节点即可
    
        def search(self, data):
            '''查找元素'''
            current = self.__head
            while current is not None:
                if current.data == data:
                    return True
                else:
                    current = current.next
            return False
    
        def remove(self, data):
            '''链表中删除元素,跟列表中的 remove() 类似,也是删除第一个遇到的元素'''
            pre = None
            current = self.__head
            while current is not None:  # 遍历整个链表
                if current.data == data:  # 表示找到了要删除的节点
                    #特殊1.要删除的节点是头节点时
                    #特殊2.链表只有一个节点,刚好它就是要删除的节点,其实跟上面一样,也是头节点
                    if current == self.__head:
                        self.__head = current.next
                    else:  # 此时,current 指向要删除的节点,pre 指向要删除的节点的前一节点
                        pre.next = current.next  # 特殊情况3: 如果要删除的节点是尾节点时,也适合
                    # 当找到要删除的节点时,需要退出 while 循环
                    break
                else:
                    pre = current  # 先让 pre 指向当前节点
                    current = current.next  # 再让 current 向后移动

    缓存是一种提高数据读取性能的技术,在硬件设计、软件开发中都有着非常广泛的应用,比如常见的 CPU(内存) 缓存、数据库缓存、浏览器缓存等等。

    1、先进先出策略 FIFO(First In,First Out)

    2、最少使用策略 LFU(Least Frequently Used)

    3、最近最少使用策略 LRU(Least Recently Used)

    LRU缓存代码实现:

    class ListNode(object):
        def __init__(self, val, n=None):
            self.val = val
            self.next = n
    
    
    class LRUCache:
        """
        一个 LRU 缓存
        维护了一个有序单链表,越靠近链表尾部的结点是越早之前访问的。
        """
    
        def __init__(self, capacity: int = 10):
            self.cap = capacity
            # 哨兵节点, 本身不存储任何数据
            self.head = ListNode(None, None)
            self.length = 0
    
        def __len__(self):
            return self.length
    
        def get(self, val: object) -> bool:
            '''获取指定缓存数据
            思路:从链表头开始顺序遍历链表:
            1. 如果此数据之前已经被缓存在链表中了,遍历得到这个数据对应的结点,并将其从原来的位置删除,然后再插入到链表的头部。
            2. 如果此数据没有在缓存链表中,则将新的数据结点插入链表的头部:
               - 如果此时缓存已满已超过容量,则将链表尾结点删除,
            参数:
                val:要获取的数据
            返回:
                存在于缓存中,返回True,否则返回 False。
            '''
            prev = None  # 用于记录尾节点的前一个节点
            p = self.head
            # 如果此数据之前已经被缓存在链表中了
            while p.next:
                if p.next.val == val:
                    # 将目标节点从原来的位置删除
                    dest = p.next  # dest临时保存目标节点
                    p.next = dest.next
                    # 将目标节点插入到头部
                    self.insert_to_head(self.head, dest)
                    return True
                prev = p
                p = p.next
    
            # 如果此数据没有缓存在链表中
            self.insert_to_head(self.head, ListNode(val))
            self.length += 1
            # 添加数据导致超过容量则要删除尾节点
            if self.length > self.cap:
                prev.next = None
            return False
    
        @staticmethod
        def insert_to_head(head, node):
            """将指定节点插入到头部"""
            node.next = head.next
            head.next = node
    
        def __str__(self):
            vals = []
            p = self.head.next
            while p:
                vals.append(str(p.val))
                p = p.next
            return '->'.join(vals)
  • 相关阅读:
    day10 基本数据类型介绍-整形的魔法
    python 快捷键
    F5负载均衡 简要原理解析以及命令行命令
    Python之路(2)
    Pycharm的安装
    集合框架(Collection和Collections的区别)
    集合框架(04)HashMap扩展知识
    集合框架(04)HashMap
    集合框架(03)泛型
    MVC
  • 原文地址:https://www.cnblogs.com/lishuntao/p/12832393.html
Copyright © 2011-2022 走看看