• 链表


    链表: 常用于经常添加或删除节点

    一、单链表

    单链表:从两点出发,节点、链表;每个节点具有两个属性:val和next

    1、设计链表并实现以下功能:

    '''
    设计单链表, 链表的节点包含两个属性:val和next,
    '''
    
    class Node(object):   # 节点
        def __init__(self, val):
            self.val = val  # 使用参数值来初始化一个节点
            self.next = None
    
    
    class MyLinkedList(object):  # 链表
    
        def __init__(self):
            """
            初始化链表
            """
            self.head = Node(0)  # 初始化一个数据为0的空节点作为头部, 本身不算节点
            self.size = 0  # 整个链表的长度初始化为0
    
        def get(self, index: int) -> int:
            """
            获取链表中第index个节点的值,如果无该索引则返回-1
            """
            if index < 0 or index >= self.size:
                return -1
            cur = self.head
            for i in range(index+1):  # 获取第index个节点
                cur = cur.next
            return(cur.val)
    
        def addAtHead(self, val: int) -> None:
            """
            在链表的第一个元素之前添加一个值为val的节点,插入后,新节点将成为链表的第一个节点
            """
            head = self.head
            cur = Node(val)  # 初始化新节点
            cur.next = head.next
            head.next = cur
            self.size += 1
            # self.addAtIndex(0, val)  #可直接调用函数addAtIndex
    
        def addAtTail(self, val: int) -> None:
            """
            将值为val的节点追加到链表的末尾
            """
            prev = self.head
            for i in range(self.size):  # 获取最后一个节点
                prev = prev.next
            cur = Node(val)  # 初始化新节点
            cur.next = prev.next
            prev.next = cur
            self.size += 1
            # self.addAtIndex(self.size, val)
    
        def addAtIndex(self, index: int, val: int):
            """
           在链表的第index个节点之前添加值为val的节点,
           如果index=size,则该节点附加到链表的末尾;如果index>size,则不插入; 如果index<0,则在头部插入
            """
            if index < 0:
                index = 0
            prev = self.head
            for i in range(index):
                prev = prev.next
            cur = Node(val)
            cur.next = prev.next
            prev.next = cur
            self.size += 1
    
        def deleteAtIndex(self, index: int) -> None:
            """
            如果索引有效,则删除链表中的第index个节点
            """
            if index < self.size:
                prev = self.head
                for i in range(index):
                    prev = prev.next
                prev.next = prev.next.next
    
    # list = MyLinkedList()
    # print(MyLinkedList)
    # print(list.addAtHead(1))
    # print(list.addAtTail(3))
    # print(list.addAtIndex(1, 2))
    # print(list.get(1))
    # print(list.deleteAtIndex(1))
    # print(list.get(1))

    2、环形链表(双指针)

    #  判断链表中是否有环
    #  1、使用快慢指针,如果快指针循环赶上了慢指针,则代表链表中有环
    #  2、使用哈希表,哈希表中不允许有重复元素(若链表有环,则有重复节点)
    
    
    class Solution:  # 使用快慢指针判断链表是否有环
        def hasCycle_fs(self, head: Node) -> bool:   # head:Node(初始化head节点)
            fast = head
            slow = head
            while fast and slow and fast.next:  # 需判断若链表为空/下一个节点为None(while fast and None )或只有一个节点的情况(while fast.next)
                fast = fast.next.next
                slow = slow.next
                if fast.val == slow.val:
                    return True
            return False
    
        def hascycle_set(self,head: Node) -> bool:  # 使用哈希表
            s1 = set()
            s1.add(head)
            cur = head
            while cur and cur.next:
                cur = cur.next
                if cur.next in s1:
                    return True
                s1.add(cur)
            return False

    3、反转链表:可使用迭代的方法,也可使用栈实现

    # 反转链表, 使用next记录链表的下一个节点并迭代链表的节点, 将当前节点插入返回的链表的头部
    class Node(object):   # 节点
        def __init__(self, val):
            self.val = val  # 使用参数值来初始化一个节点
            self.next = None
    class Solution():
        def reverseList(self, head: Node) -> Node:
            head_ret = Node(None)
            cur = head
            while cur:
                next = cur.next # 将next指向下个节点
                cur.next = head_ret.next  # 将当前节点插入head_ret链表头部的后面(返回时不返回定义的头部)
                head_ret.next = cur
                cur = next  # 迭代当前链表的节点(知道当前节点为空)
            return head_ret.next
    
    l1 = Node(1)
    l2 =Node(2)
    l3 =Node(3)
    
    l1.next = l2
    l2.next = l3
    l3.next = None
    
    m = Solution()
    head = m.reverseList(l1)
    print(head.val)
    print(head.next.val)
    print(head.next.next.val)

     二、双链表

    class double_Node:
    
        def __init__(self, val=0):
            self.val = val
            self.next = None
            self.prev = None
    
    class double_linklist:
        def __init__(self):
            self.size = 0
            self.head, self.tail = double_Node(), double_Node()# 给该链表初始化一个虚拟头节点, 该头节点不作数,因此size = 0
            self.head.next = self.tail
            self.tail.prev = self.head
    
        def get(self, index: int) -> int:
            """
            获取链表中的index个节点的值,如果索引无效,则返回-1
            """
            if index >= self.size or index < 0:
                return -1
            cur = self.head
            for i in range(index + 1):
                cur = cur.next
            return cur.val
    
        def addAtHead(self, val: int) -> None:
            self.addAtIndex(0, val)
    
        def addAtTail(self, val: int) -> None:
            self.addAtIndex(self.size, val)
    
        def addAtIndex(self, index: int, val: int) -> None:
            """
            在链表中的第index个节点之前添加值为val的节点,如果index>size, 则不插入,如果index<0,则在头部插入
            """
            if index < 0:
                index = 0
            pred = self.head
            for i in range(index):
                pred = pred.next
    
            cur = double_Node(val)
            next = pred.next
    
            cur.next = next
            cur.prev = pred
            next.prev = cur
            pred.next = cur
            self.size+=1
    
        def deleteAtIndex(self, index: int) -> None:
            """
            若索引有效,删除链表中第index个节点
            """
            pred = self.head
            if index >= 0  and index < self.size:
                for i in range(index):
                    pred = pred.next
    
                next=pred.next.next
                pred.next = next
                next.prev = pred
                self.size -= 1
  • 相关阅读:
    前端面试题六
    前端面试题五
    前端面试题四
    前端面试题之三
    前端面试题分享二
    前端面试题分享一
    JS学习笔记一
    git使用学习笔记一
    常见User-Agent
    ado.net之SQLServer和Oracle (sys_cursor) 数据库链接——获取结果集方式对比
  • 原文地址:https://www.cnblogs.com/byy521/p/15080318.html
Copyright © 2020-2023  润新知