链表

作者: 乔一波一 | 来源:发表于2023-08-21 18:57 被阅读0次

    一、 链表的基本操作

    • 本题考察链表的基本操作:打印链表所有元素,查询指定位置的样本,插入指定位置样本,和删除指定位置样本;
    • 输入:输入数据只有一组,第一行有n+1个整数,第一个整数是这行余下的整数数目n,后面是n个整数。
      这一行整数是用来初始化列表的,并且输入的顺序与列表中的顺序相反,也就是说如果列表中是1、2、3那么输入的顺序是3、2、1。第二行有一个整数m,代表下面还有m行。每行有一个字符串,字符串是“get”,“insert”,“delete”,“show”中的一种。如果是“get”,代表获得第a个元素。(a从1开始计数);如果是“delete”,代表删除第a个元素。(a从1开始计数);如果是“insert”,则其后跟着两个整数a和e,代表在第a个位置前面插入e。(a从1开始计数) ;“show”之后没有正数,直接打印链表全部内容。
    • 输出:如果获取成功,则输出该元素;如果删除成功,则输出“delete OK”;如果获取失败,则输出“get fail”;
      如果删除失败,则输出“delete fail”;如果插入成功,则输出“insert OK”,否则输出“insert fail”;如果是“show”,则输出列表中的所有元素;如果列表是空的,则输出“Link list is empty”。注:所有的双引号均不输出。
    • 样例输入:
      3 3 2 1
      21
      show
      delete 1
      show
      delete 2
      show
      delete 1
      show
      delete 2
      insert 2 5
      show
      insert 1 5
      show
      insert 1 7
      show
      insert 2 5
      show
      insert 3 6
      show
      insert 1 8
      show
      get 2

    解题思路:

    注意插入删除位置的判断,然后是移位保持正确。

    #定义链表节点
    class LinkedNode:
        def __init__(self, val = 0, next = None):
            self.val = val
            self.next = next
    
    #定义链表基本操作
    class MyLinkedList:
        def __init__(self):
            self._size = 0
            self._dummyHead = LinkedNode(0)
        #获取到第index个节点数值,如果index是非法数值直接返回-1, 注意index是从0开始的,第0个节点就是头结点 
        def get(self, index):
            if index > (self._size - 1) or index < 0:
                return -1
            cur = self._dummyHead.next
            while index:
                cur = cur.next
                index -= 1
            return cur.val
        #在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点
        def addAtHead(self, val):
            newNode = LinkedNode(val)
            newNode.next = self._dummyHead.next
            self._dummyHead.next = newNode
            self._size += 1
        #在链表最后面添加一个节点
        def addAtTail(self, val):
            newNode = LinkedNode(val)
            cur = self._dummyHead
            while cur.next:
                cur = cur.next
            cur.next = newNode
            self._size += 1
        #在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。
        def addAtIndex(self, index, val):
            if index > self._size:
                return -1
            if index < 0:
                return -1
            newNode = LinkedNode(val)
            cur = self._dummyHead
            while index:
                cur = cur.next
                index -= 1
            newNode.next = cur.next
            cur.next = newNode
            self._size += 1
            return 0
        #删除第index个节点,如果index 大于等于链表的长度,直接return,注意index是从0开始的
        def deleteAtIndex(self, index):
            if index >= self._size or index < 0:
                return -1
            cur = self._dummyHead
            while index:
                cur = cur.next
                index -= 1
            tmp = cur.next
            cur.next = cur.next.next
            del tmp
            self._size -= 1
            return 0
        #打印链表
        def printLinkedList(self):
            cur = self._dummyHead
            if cur.next == None:
                return -1
            while cur.next:
                print(cur.next.val, end = ' ')
                cur = cur.next
            print()
            return 0
    
    if __name__ == "__main__":
        while True:
            mylinklist = MyLinkedList()
            try:
                # 读取链表长度和链表数值
                n, *nums = list(map(int, input().split()))
                # 初始化链表
                for i in range(n):
                    mylinklist.addAtHead(nums[i])
                # 读取操作的个数
                m = int(input())
                for i in range(m):
                    s = input().split()
                    if s[0] == "show":
                        if mylinklist.printLinkedList() == -1:
                            print("Link list is empty")
                    if s[0] == "delete":
                        t = int(s[1])
                        if mylinklist.deleteAtIndex(t - 1) == -1:
                            print("delete fail")
                        else:
                            print("delete OK")
                    if s[0] == "insert":
                        t = int(s[1])
                        z = int(s[2])
                        if mylinklist.addAtIndex(t - 1, z) == -1:
                            print("insert fail")
                        else:
                            print("insert OK")
                    if s[0] == "get":
                        t = int(s[1])
                        getValue = mylinklist.get(t - 1)
                        if getValue == -1:
                            print("get fail")
                        else:
                            print(getValue)
            except:
                break
    

    二、单链表反转

    • 题目表述:根据一个整数序列构造一个单链表,然后将其反转。例如:原单链表为 2 3 4 5 ,反转之后为5 4 3 2
    • 输入:输入包括多组测试数据,每组测试数据占一行,第一个为大于等于0的整数n,表示该单链表的长度,后面跟着n个整数,表示链表的每一个元素。整数之间用空格隔开。
    • 输出: 针对每组测试数据,输出包括两行,分别是反转前和反转后的链表元素,用空格隔开。如果链表为空,则只输出一行,list is empty。
    • 样例输入:
      5 1 2 3 4 5
      0

    解题思路

    单链表反转其实就是将链表中当前元素的指针指向前一个元素;中间需要使用temp保存当前元素以保证能够访问链表中下一个元素,以此迭代下去。

    class LinkNode:
        def __init__(self, val, next=None) -> None:
            self.val = val
            self.next = next
    
    
    def printLinkList(node):
        while node.next:
            print(node.val, end=" ")
            node = node.next
        print(node.val)
    
    
    def reverseLinkList(node):
        pre = None
        cur = node
        temp = None
        while cur:
            temp = cur.next
            cur.next = pre  # 翻转操作
            pre = cur  # 更新pre 和 cur指针
            cur = temp
        return pre
    
    if __name__ == "__main__":
        while True:
            try:
                # 输入5 1 2 3 4 5,表示链表有5个节点,值分别为1 2 3 4 5
                n, *nums = map(int, input().split())
            except:
                break
            if n == 0:
                print("list is empty")
                continue
            dummyHead = LinkNode(0)  # 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点
            cur = dummyHead
            for i in range(n):  # 开始构造节点
                cur.next = LinkNode(nums[i])
                cur = cur.next
            printLinkList(dummyHead.next)  # 打印链表
            printLinkList(reverseLinkList(dummyHead.next))  # 打印翻转后的链表
    

    三、删除链表中的重复元素

    • 题目描述:根据一个递增的整数序列构造有序单链表,删除其中的重复元素
    • 输入:输入包括多组测试数据,每组测试数据占一行,第一个为大于等于0的整数n,表示该单链表的长度,后面跟着n个整数,表示链表的每一个元素。整数之间用空格隔开
    • 输出:针对每组测试数据,输出包括两行,分别是删除前和删除后的链表元素,用空格隔开。如果链表为空,则只输出一行,list is empty。

    解题思路

    链表中连续两个节点的值相等,则前一个节点的指针指向下下个节点,再接着判断。

    class LinkNode:
        def __init__(self, val, next=None) -> None:
            self.val = val
            self.next = next
    
    def printLinkList(node): # 打印当前链表
        while node.next:
            print(node.val, end=" ")
            node = node.next
        print(node.val)
    
    def removeSame(head):
        if not head:
            return None
        cur = head
        while cur and cur.next:
            if cur.val == cur.next.val: # 如果当前元素和下一个元素值相等
                cur.next = cur.next.next # 当前元素的指针跳过下一个元素,指向下下个。
            else:
                cur = cur.next
        return head
    
    if __name__ == "__main__":
        while True:
            try:
                n, *nums = map(int, input().split())
            except:
                break
            if n == 0:
                print("list is empty")
                continue
            dummyHead = LinkNode(0)  # 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点
            cur = dummyHead
            for i in range(n):  # 开始构造节点
                cur.next = LinkNode(nums[i])
                cur = cur.next
            printLinkList(dummyHead.next)  # 打印链表
            printLinkList(removeSame(dummyHead.next))  # 打印去重后的链表
    

    相关文章

      网友评论

          本文标题:链表

          本文链接:https://www.haomeiwen.com/subject/qskymdtx.html