链表

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

一、单链表

单链表:从两点出发,节点、链表;每个节点具有两个属性: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
原文地址:https://www.cnblogs.com/byy521/p/15080318.html