1.1 概念

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。

1.2 存储原则 

(1)用一组任意的存储单元来存放线性表的结点(这组存储单元既可以是连续的,也可以是不连续的)

(2)链表中结点的逻辑次序和物理次序不一定相同。为了能正确表示结点间的逻辑关系,在存储每个结点值的同时,还必须存储指示其后继结点的地址(或位置)信息(称为指针(pointer)或链(link))

​注:链式存储是数据结构中最常用的存储方式之一,它不仅可表示线性表,而且可表示各种非线性的数据结构。

1.3 单链表结构

datanext

data域--存放结点值的数据域

next域--存放结点的直接后继的地址(位置)的指针域(链域)

头指针——单链表中每个结点的存储地址是存放在它的前趋结点next域中,而开始结点没有前趋,所以应设头指针head指向开始结点。链表由头指针唯一确定,单链表可以用头指针的名字来命名。

终端节点——终端节点没有后继,故终端结点的指针域为空,即NULL。

1.4 单链表插入、删除操作

(1)插入节点操作

①  插入指针s指向的节点X

 ② 令s-->next = p-->next 

p-->next = s  插入后

 

(2) 删除节点操作

 

①删除节点b

令p-->next = p-->next-->next

 1.5 代码实现

class Node:
    """链表节点类"""
    def __init__(self, data):
        self.data = data  # 节点数据
        self.next = None  # 指向下一个节点的指针

class LinkedList:
    """单链表类"""
    def __init__(self):
        """初始化空链表"""
        self.head = None  # 链表头节点
        self.size = 0    # 链表长度

    def __len__(self):
        """返回链表长度"""
        return self.size

    def is_empty(self):
        """检查链表是否为空"""
        return self.size == 0

    def insert_at_beginning(self, data):
        """在链表头部插入新节点"""
        new_node = Node(data)
        new_node.next = self.head
        self.head = new_node
        self.size += 1

    def insert_at_end(self, data):
        """在链表尾部插入新节点"""
        new_node = Node(data)
        if self.is_empty():
            self.head = new_node
        else:
            current = self.head
            while current.next:
                current = current.next
            current.next = new_node
        self.size += 1

    def insert_at_position(self, position, data):
        """在指定位置插入新节点"""
        if position < 0 or position > self.size:
            raise IndexError("位置超出链表范围")
        
        if position == 0:
            self.insert_at_beginning(data)
        elif position == self.size:
            self.insert_at_end(data)
        else:
            new_node = Node(data)
            current = self.head
            for _ in range(position - 1):
                current = current.next
            new_node.next = current.next
            current.next = new_node
            self.size += 1

    def delete_at_beginning(self):
        """删除链表头部节点"""
        if self.is_empty():
            raise Exception("链表为空")
        self.head = self.head.next
        self.size -= 1

    def delete_at_end(self):
        """删除链表尾部节点"""
        if self.is_empty():
            raise Exception("链表为空")
        
        if self.size == 1:
            self.head = None
        else:
            current = self.head
            while current.next.next:
                current = current.next
            current.next = None
        self.size -= 1

    def delete_at_position(self, position):
        """删除指定位置的节点"""
        if position < 0 or position >= self.size:
            raise IndexError("位置超出链表范围")
        
        if position == 0:
            self.delete_at_beginning()
        elif position == self.size - 1:
            self.delete_at_end()
        else:
            current = self.head
            for _ in range(position - 1):
                current = current.next
            current.next = current.next.next
            self.size -= 1

    def delete_by_value(self, value):
        """删除包含特定值的第一个节点"""
        if self.is_empty():
            return False
        
        if self.head.data == value:
            self.delete_at_beginning()
            return True
            
        current = self.head
        while current.next:
            if current.next.data == value:
                current.next = current.next.next
                self.size -= 1
                return True
            current = current.next
        return False

    def search(self, value):
        """查找链表中是否存在特定值"""
        current = self.head
        position = 0
        while current:
            if current.data == value:
                return position
            current = current.next
            position += 1
        return -1

    def get_at_position(self, position):
        """获取指定位置的节点值"""
        if position < 0 or position >= self.size:
            raise IndexError("位置超出链表范围")
        
        current = self.head
        for _ in range(position):
            current = current.next
        return current.data

    def update_at_position(self, position, new_value):
        """更新指定位置的节点值"""
        if position < 0 or position >= self.size:
            raise IndexError("位置超出链表范围")
        
        current = self.head
        for _ in range(position):
            current = current.next
        current.data = new_value

    def reverse(self):
        """反转链表"""
        prev = None
        current = self.head
        while current:
            next_node = current.next
            current.next = prev
            prev = current
            current = next_node
        self.head = prev

    def display(self):
        """打印链表内容"""
        current = self.head
        elements = []
        while current:
            elements.append(str(current.data))
            current = current.next
        print(" -> ".join(elements))

    def clear(self):
        """清空链表"""
        self.head = None
        self.size = 0


# 测试单链表
if __name__ == "__main__":
    print("创建链表并插入元素")
    ll = LinkedList()
    
    # 在头部插入
    ll.insert_at_beginning(10)
    ll.insert_at_beginning(20)
    print("头部插入后:", end=" ")
    ll.display()  # 20 -> 10
    
    # 在尾部插入
    ll.insert_at_end(30)
    ll.insert_at_end(40)
    print("尾部插入后:", end=" ")
    ll.display()  # 20 -> 10 -> 30 -> 40
    
    # 在指定位置插入
    ll.insert_at_position(2, 50)
    print("位置2插入50:", end=" ")
    ll.display()  # 20 -> 10 -> 50 -> 30 -> 40
    
    # 删除操作
    ll.delete_at_beginning()
    print("删除头部后:", end=" ")
    ll.display()  # 10 -> 50 -> 30 -> 40
    
    ll.delete_at_end()
    print("删除尾部后:", end=" ")
    ll.display()  # 10 -> 50 -> 30
    
    ll.delete_at_position(1)
    print("删除位置1后:", end=" ")
    ll.display()  # 10 -> 30
    
    # 删除特定值
    ll.insert_at_end(60)
    ll.insert_at_end(70)
    print("插入60和70后:", end=" ")
    ll.display()  # 10 -> 30 -> 60 -> 70
    
    ll.delete_by_value(60)
    print("删除值60后:", end=" ")
    ll.display()  # 10 -> 30 -> 70
    
    # 查找操作
    print("值30的位置:", ll.search(30))  # 1
    print("值100的位置:", ll.search(100))  # -1
    
    # 获取和更新
    print("位置1的值:", ll.get_at_position(1))  # 30
    ll.update_at_position(1, 35)
    print("更新位置1为35后:", end=" ")
    ll.display()  # 10 -> 35 -> 70
    
    # 反转链表
    ll.reverse()
    print("反转链表后:", end=" ")
    ll.display()  # 70 -> 35 -> 10
    
    # 清空链表
    ll.clear()
    print("清空链表后:", end=" ")
    ll.display()  # (空)
    print("链表长度:", len(ll))  # 0

代码运行效果:

操作时间复杂度分析: 

头部插入O(1)直接修改头指针
尾部插入O(n)需要遍历到链表尾部
指定位置插入O(n)最坏情况需要遍历到指定位置
头部删除O(1)直接修改头指针
尾部删除O(n)需要遍历到倒数第二个节点
指定位置删除O(n)最坏情况需要遍历到指定位置
搜索O(n)需要遍历链表
反转O(n)需要遍历整个链表

 

更多推荐