数据结构链表之单向链表:Python3 实现单向链表——1

本文详细介绍Python中单向链表的数据结构实现,包括节点定义、链表操作及增删改查等常用功能,对比链表与顺序表的特性。

Python3 实现单向链表

链表定义与简介

  • 定义:链表与顺序表(Python中列表)性质相反,链表是物理单元上非顺序的、非连续的,在逻辑顺序上其数据元素是通过指针实现的,组成链表的每一个元素也可以叫做链表的节点,节点可以在运行时动态生成
    在这里插入图片描述
    单向链表中所有的元素也可以称之为节点,每个节点包含两个区域,如上图item区域称为数据域,next区域为指针域,单向链表中尾节点的判断只需判断该节点的指针(next)是否指向空即可。

链表(Linked list)与顺序表(Sequence list)的主要差异

  • 顺序表的内存地址是连续的,其数据元素有对应唯一的索引,搜索时非常方便,但进行元素插入时较麻烦,每次插入元素,其后所有元素都要移动一位。
  • 而链表内存地址是非连续、非顺序的,逻辑顺序由指针实现,在插入元素时只需将指定位置的前一个元素的指针断开,并指向要插入的元素的节点,然后插入的元素指针再指向下一个节点即可,但是在查询元素时,需要从头结点开始一个一个遍历寻找。

由于链表不是必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。

定义单链表

# 定义节点
class Node:
    def __init__(self, item):
        self.item = item
        self.next = None


# 定义链表
class SingleLinkList:
    def __init__(self):
        self._head = None


if __name__ == '__main__':
    # 创建链表
    link_list = SingleLinkList()

    # 创建结点
    node1 = Node(1)
    node2 = Node(2)

    # 将结点添加到链表
    link_list._head = node1

    # 将第一个结点的next指针指向下一结点
    node1.next = node2

    # 访问链表
    print("head", link_list._head)  # 访问第一个结点数据
    print(link_list._head.item)  # 访问第一个结点数据
    print(link_list._head.next.item)  # 访问第二个结点数据

一个简单的链表,没有增删改查等功能,操作十分不便

接下来对其,进行一部分常用功能实现:

  1. 清空元素clear(),断开头结点的指针,长度为0
  2. 展示元素的值show_items()
  3. 获取元素get_value_by_index(),以偏移量获取元素的值,超出偏移量会报错IndexErorr,可以是负偏移
  4. 判断链表是否为空is_empty()
  5. 返回链表长度length()
  6. 在指定位置插入insert(),当超过实际长度,在最后插入;当为负数倒序选择插入,负数的绝对值大于实际长度则在最前面插入
  7. 在末尾追加元素append()
  8. 指定偏移量移除元素remove(),超过偏移量,抛出IndexErorr,可以使用负偏移
  9. 判断一个元素是否存在于链表is_exist(),存在返回True,否则返回False
  10. 返回元素的偏移indexOf()

代码实现

class Node:
    """The nodes of single linked list"""
    def __init__(self, item):
        self.item = item
        self.next = None


class SingleLinkedList:
    def __init__(self):
        """Initialize the head and the length of single linked list"""
        self.head = None

    def clear(self):
        """CLear a linked list"""
        self.head = None

    def show_items(self):
        """Show all the elements of linked list"""
        if self.is_empty():
            return None
        cur = self.head
        while cur.next:
            yield cur.item
            cur = cur.next
        yield cur.item

    def get_value_by_index(self, index):
        """Get a value by index"""
        node = self.head
        index = self.length()+index if index < 0 else index
        if index < 0:
            raise IndexError('index out of range')
        try:
            for i in range(index):
                node = node.next
            return node.item
        except AttributeError as e:
            raise IndexError('index out of range')

    def is_empty(self):
        """Judge if a linked list is empty"""
        return self.head is None

    def length(self):
        """Return the elements number of a linked list"""
        cur = self.head
        if not cur:
            return 0
        count = 1
        while cur.next:
            count += 1
            cur = cur.next
        return count

    def insert(self, index, item):
        """Insert an element before the given index of a node"""
        node = Node(item)
        length = self.length()
        # Empty list, append directly
        if not self.head:
            self.append(item)
        if index < 0 and (index + length) >= 0:
            index += length
        # index>0
        if index > 0:
            cur = self.head
            while cur.next:
                if index <= 1:
                    break
                cur = cur.next
                index -= 1
            node.next = cur.next
            cur.next = node
        elif index == 0 or index + length < 0:
            temp = self.head
            node.next = temp
            self.head = node

    def append(self, item):
        """Append elements to the end of a linked list"""
        node = Node(item)
        if self.is_empty():
            self.head = node
        else:
            cur = self.head
            while cur.next:
                cur = cur.next
            cur.next = node

    def remove(self, index):
        """Remove an element by index"""
        if not -self.length() - 1 < index < self.length():
            raise IndexError('remove index out of range')
        if index < 0:
            index += self.length()
        print(f"index", index)
        if index == 0:
            print("Get into ")
            self.head = self.head.next
        else:
            cur = self.head
            pre = cur
            while index > 0:
                pre = cur
                cur = cur.next
                index -= 1
            pre.next = cur.next

    def is_exist(self, item):
        """Judge if an element in linked-list"""
        return item in self.show_items()

    def indexOf(self, item):
    	"""Return a given item's index where is the first appearance in the list"""
        return list(self.show_items()).index(item)

验证功能

if __name__ == '__main__':
    SLL = SingleLinkedList()

    print(f"If the linked list is empty?: {SLL.is_empty()}")

    # Append elements to the end
    for i in range(5):
        SLL.append(i)

    print(f"Show all items:{list(SLL.show_items())}")

    print(f"The length of {SLL.__class__.__name__}: {SLL.length()}")

    # _index>0
    _index, _item = 9, 11
    SLL.insert(_index, _item)
    print(f"Insert {_item} before linked list[{_index}]: {list(SLL.show_items())}")
    # _index=0
    _index, _item = 0, 22
    SLL.insert(_index, _item)
    print(f"Insert {_item} before linked list[{_index}]: {list(SLL.show_items())}")
    # _index<0 and length+_index>0
    _index, _item = -3, 33
    SLL.insert(_index, _item)
    print(f"Insert {_item} before linked list[{_index}]: {list(SLL.show_items())}")
    # _index<0 and length+_index<0
    _index, _item = -21, 44
    SLL.insert(_index, _item)
    print(f"Insert {_item} before linked list[{_index}]: {list(SLL.show_items())}")

    _index = -5
    SLL.remove(_index)
    print(f"Remove an element by index[{_index}]: {list(SLL.show_items())}")

    # Get a value by index, if index out of range, throw a IndexError
    _index = 3
    print(f"Get a value by index[{_index}], its value: {SLL.get_value_by_index(3)}")

    _item = 44
    print(f"If item:[{_item}] in linked list {SLL.__class__.__name__}? {SLL.is_exist(_item)} ")

    # CLear a linked list
    print(f"The linked list has been cleared: {SLL.__class__.__name__}: {SLL.clear()}")

    print(f"The length of {SLL.__class__.__name__}: {SLL.length()}")

结果

If the linked list is empty?: True
Show all items:[0, 1, 2, 3, 4]
The length of SingleLinkedList: 5
Insert 11 before linked list[9]: [0, 1, 2, 3, 4, 11]
Insert 22 before linked list[0]: [22, 0, 1, 2, 3, 4, 11]
Insert 33 before linked list[-3]: [22, 0, 1, 2, 33, 3, 4, 11]
Insert 44 before linked list[-21]: [44, 22, 0, 1, 2, 33, 3, 4, 11]
Remove an element by index[-5]: [44, 22, 0, 1, 33, 3, 4, 11]
Get a value by index[3], its value: 1
If item:[44] in linked list SingleLinkedList? True 
The linked list has been cleared: SingleLinkedList: None
The length of SingleLinkedList: 0
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值