数据结构:链表

链表(Linked List)是一种基础的数据结构,用于存储一系列有序的元素。与数组不同,链表中的元素存储在不连续的内存位置,元素通过指针(或引用)连接,允许动态地插入和删除元素。

一、链表的基本概念

1. 节点(Node)

        链表的基本组成单元,通常包含两个部分:
        数据部分:存储链表节点的数据。
        指针部分:指向下一个节点的引用。

2. 头节点

        链表的第一个节点,标识链表的开始。

3. 尾节点

        链表的最后一个节点,其指针部分指向`None`(空),表示链表的结束。

二、链表的类型

1. 单链表(Singly Linked List)

        每个节点只有一个指向下一个节点的指针。
        优点:实现简单,插入和删除操作相对高效。
        缺点:只能单向遍历,不能快速访问前一个节点。

2. 双链表(Doubly Linked List)

        每个节点有两个指针,分别指向前一个节点和下一个节点。
        优点:支持双向遍历,可以方便地进行插入和删除操作。
        缺点:额外需要存储一个指向前节点的指针,增加了内存使用。

3. 循环链表(Circular Linked List)

        链表的最后一个节点指向头节点,而不是指向`None`。可以是单向或双向。
        优点:实现循环遍历。
         缺点:可能会导致链表遍历时的复杂性增加。

三、链表的基本操作

1. 插入(Insert)

        头部插入:在链表的最前面插入一个新节点。
        尾部插入:在链表的最后添加一个新节点。
        中间插入:在指定位置插入新的节点。

2. 删除(Delete)

        从链表中删除指定位置的节点,更新相邻节点的指针。

3. 查找(Search)

        遍历链表,查找指定值的节点。

4. 遍历(Traversal)

        从头节点开始,依次访问链表中的每个节点。

四、链表的优缺点

优点:
        动态大小:链表的大小可以在运行时动态调整,避免了数组固定大小的问题。
        高效插入和删除:在已知节点位置时,插入和删除操作只需要更新指针,不必移动数据,时间复杂度为 O(1) 。

缺点:
        随机访问效率低:链表不支持高效的随机访问,查找某个节点的时间复杂度为 O(n) 。
        额外空间开销:每个节点需要额外的空间来存储指针,导致相对于数组来说,内存使用更高。

五、示例代码(Python)

以下是一个简单的单链表实现示例:

# 链表节点实现
class SingleNode(object):
    def __init__(self, item):
        # item: 存放元素(数据部分)
        self.item = item
        # next:标识下一个节点(指针部分)
        self.next = None


# 单链表实现
class SingleLinkList(object):
    def __init__(self, node=None):
        # head:首节节点
        self.head = node

    # 判断是否为空
    def is_empty(self):
        if self.head is None:
            return True
        else:
            return False

    # 获取链表长度
    def leng(self):
        # 游标记录当前所在位置
        cur = self.head
        # 记录链表长度
        count = 0

        while cur is not None:
            cur = cur.next
            count += 1

        return count

    # 遍历
    def travel(self):
        # 游标标记当前所在的位置
        cur = self.head
        # 循环打印数据
        while cur is not None:
            print(cur.item)
            cur = cur.next

    # 头部增加节点
    def add(self, item):
        node = SingleNode(item)
        node.next = self.head
        self.head = node

    # 尾部增加节点
    def append(self, item):
        # 尾部增加节点
        node = SingleNode(item)
        if self.is_empty():
            # 如果链表为空
            self.head = node
        else:
            # 如果链表不为空
            cur = self.head
            # 找到尾部节点
            while cur.next is not None:
                cur = cur.next

            cur.next = node

    def insert(self, postion, item):
        if postion <= 0:
            self.add(item)
        elif postion >= self.leng():
            self.append(item)
        else:
            # 游标
            cur = self.head
            # 计数
            count = 0
            # 新节点
            node = SingleNode(item)
            # 找到插入位置的前一个节点
            while count < postion - 1:
                cur = cur.next
                count += 1

            # 完成插入新节点
            node.next = cur.next
            cur.next = node

    # 删除节点
    def remove(self, item):
        cur = self.head
        pre = None
        while cur is not None:
            if cur.item == item:
                if cur == self.head:
                    self.head = cur.next
                else:
                    pre.next = cur.next
                return
            else:
                pre = cur
                cur = cur.next

    # 查找节点是否存在
    def search(self, item):
        cur = self.head
        while cur is not None:
            if cur.item == item:
                return True
            cur = cur.next

        return False


if __name__ == '__main__':
    # 节点
    node1 = SingleNode(10)
    print(node1.item)  # 10
    print(node1.next)  # None
    # 链表
    link1 = SingleLinkList()
    print(link1.head)  # None
    link2 = SingleLinkList(node1)
    print(link2.head.item)  # 10
    # 判断是否为空
    print(link1.is_empty())  # True
    print(link2.is_empty())  # False
    # 获取链表长度
    print(link1.leng())
    print(link2.leng())
    # 遍历
    link2.travel()
    # 头部增加节点
    print('-' * 20)
    link2.add(11)
    link2.travel()
    # 尾部添加节点
    print('-' * 20)
    link2.append(20)
    link2.travel()
    # 插入数据
    print('-' * 20)
    link2.insert(2, 30)
    link2.travel()
    # 删除节点
    print('-' * 20)
    link2.remove(30)
    link2.travel()
    # 查询节点是否存在
    print('-'*20)
    print(link2.search(10))  # True
    print(link2.search(2))   # False

六、总结

链表是一种强大而灵活的数据结构,适合于需要频繁插入和删除操作的场景。理解链表的基本概念和操作对学习和实现其他更复杂的数据结构(如树、图)非常重要。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值