链表

作者: 乔一波一 | 来源:发表于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))  # 打印去重后的链表

相关文章

  • 链表基础

    链表基础 链表长度 链表为空 链表结构 链表增加

  • 双向链表&双向循环链表

    链表分为:单链表、单向循环链表、双向链表、双向循环链表本节主要说明:双向链表、双向循环链表 定义结点 一、双向链表...

  • 算法与数据结构:链表

    链表 链表还分为单向链表和双向链表, 但是这篇文章只说单向链表 , 下次再讲双向链表 . 链表和数组的区别 ? 链...

  • 链表

    链表 单链表反转链表中环的检测两个有序链表合并删除链表倒数第n个节点求链表的元素总个数 一.单向链表 链表共有特征...

  • 五、双向链表

    双向链表 此前介绍的链表,也叫做单向链表使用双向链表可以提升链表的综合性能 修改之前的单链表的源码: 双向链表 –...

  • 链表

    内容 链表数据结构 向链表添加元素 从链表移除元素 使用 LinkedList 表 双向链表 循环链表 链表数据结...

  • 数据与算法结构

    线性表 顺序表 链表(物理上离散,逻辑上连续) 链表的类别 单链表 循环链表 双链表 链表的操作 顺序表与链表的比...

  • 数据结构——链表

    本文所讲的链表是单链表,链表采用无头链表 科普下:一般链表可以分为有头节点的链表与无头节点的链表 有头节点的链表:...

  • 链表

    文章结构 链表的定义 链表的插入和删除操作 链表的特性 常见的链表结构 自定义链表 链表的经典操作 使用链表实现L...

  • Algorithm小白入门 -- 单链表

    单链表递归反转链表k个一组反转链表回文链表 1. 递归反转链表 单链表节点的结构如下: 1.1 递归反转整个单链表...

网友评论

      本文标题:链表

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