链表

链表
单链表
循环链表
双向链表

顺序表的中将数据存放在一起,但凡事都有利有弊这种做法,这种做法虽然有利于数据的寻找,但是在大量数据的增加或者删除的时候需要对数据进行整体迁移。
链表在大量数据的增加或者删除时处理的就更加得心应手,链表是由无数个节点构成,每个节点中都存入这数据和下一结点的地址

单链表

单链表(单向列表),顾名思义,这类链表只能单向访问,就类似于音乐播放器中的顺序播放,当播放列表中最后一首音乐播放完成后不会像循环播放一样再次从头播放,而是直接结束播放。

结点

在这里插入图片描述
这里科普一下结点和节点的区别

  1. 结点:在数据结构中经常使用,常用于形容的东西大多是比较虚拟的,没有实体的。比如单链表的结点,在现实生活中是不存在的,是我们想象出来的一个虚拟区域。
  2. 节点:在网络中经常用到,常用于形容有实体的,真实存在的东西。比如网络中的一个通信设备就可以被称之为节点。

Python编写单链表结点

class SingleNode:
    def __init__(self, elem):
        self.elem = elem
        self.next = None

单链表的操作

在这里插入图片描述
对链表的操作,需要用到游标(指针)这类东西来实现定位。在Python中我们需要自己创建游标。
游标,初始指向头结点,当需要对链表操作需要用到游标时,游标开始遍历链表。
我们就来对单链表实现以下操作。

  1. is_empty() 链表是否为空
  2. length() 链表长度
  3. add(elem) 链表头部添加元素
  4. append(elem) 链表尾部添加元素
  5. travel() 遍历整个链表
  6. position(pos)根据位置读取指定元素
  7. element(elem)输出元素所在位置
  8. search(elem) 查找节点是否存在
  9. insert(pos, elem) 指定位置添加元素
  10. remove(elem) 指定元素删除节点
  11. delete(pos)根据位置删除
  12. clear()清空链表

在这里插入图片描述

Python编写链表操作

class Linked:
    def __init__(self, node=None):
        self.__head = node

    def is_empty(self):
        """判断链表是否为空"""
        # 判断头结点的值是否为空
        return self.__head is None

    def length(self):
        """判断链表长度"""
        # 初始化游标
        cur = self.__head
        # 长度计算变量
        count = 0
        # 判断游标指向是否为空
        while cur is not None:
            # 指向下一个结点,同时计数器加一
            cur = cur.next
            count += 1
        return count

    def add(self, elem):
        """
        头部添加元素
        :param elem: 元素
        """
        # 创建新结点
        newNode = SingleNode(elem)
        # 将原头结点坐标给新结点,同时将新结点坐标给头结点
        newNode.next, self.__head = self.__head, newNode

    def append(self, elem):
        """
        尾部添加元素
        :param elem: 元素
        """
        # 新建结点
        newNode = SingleNode(elem)
        # 判断是否为空链表
        if self.is_empty():
            # 如果是空链表就将头指针指向新结点
            self.__head = newNode
        else:
            # 初始化游标
            cur = self.__head
            # 将游标移动到末尾
            while cur.next is not None:
                cur = cur.next
            # 将末尾元素的next设置为新建节点
            cur.next = newNode

    def travel(self):
        """遍历整个链表"""
        # 初始化游标
        cur = self.__head
        # 输出每个结点的elem
        while cur is not None:
            print(cur.elem, end=' ')
            cur = cur.next
        print('')

指定位置添加元素难道算是所以难度中最高的,这里的操作需要两个游标来完成,同时也特别注意:先把新结点的链接指向需要的位置,再将原位置指向新结点,如果顺序错误将会导致结点丢失。
在这里插入图片描述

    def insert(self, pos, elem):
        """
        指定位置添加元素
        :param pos: 指定位置(添加元素在指定位置之后)
        :param elem: 元素
        """
        # 判断插入位置
        if pos <= 0:
            self.add(elem)
        elif pos > (self.length() - 1):
            self.length(elem)
        else:
            # 新建结点
            newNode = SingleNode(elem)
            # 创建指针
            cur = self.__head
            # 创建计数器
            count = 0
            # 将游标定位到指定位置前一位结点上
            while count < (pos - 1):
                count += 1
                cur = cur.next
            # 将游标位置的的next给新结点,将新结点的位置给游标
            newNode.next, cur.next = cur.next, newNode
    def position(self, pos):
        """根据位置读取元素"""
        # 判断输入位置是否在链表中
        if 0 < pos < (self.length() - 1):
            # 创建游标
            cur = self.__head
            # 创建计数器
            count = 0
            # 将游标移动到指定位置
            while count < pos:
                count += 1
                cur = cur.next
            return cur.elem
        else:
            return False

    def element(self, elem):
        """输出元素所在位置"""
        # 创建游标和计数器
        cur = self.__head
        count = 0
        while True:
            # 判断游标指向元素是否为输入元素
            if cur.elem == elem:
                return count
            # 判断测试的长度是否已经超出
            elif cur.next is None:
                return False
            cur = cur.next
            count += 1

    def remove(self, elem):
        """
        根据指定元素删除
        :param elem: 元素
        """
        cur = self.__head
        pre = None
        while cur is not None:
            # 判断游标指向元素是否为输入元素
            if cur.elem == elem:
                # 判断是否删除的为首节点
                if pre is None:
                    self.__head = cur.next
                else:
                    pre.next = cur.next
                break
            elif cur is None:
                break
            # 游标后移
            else:
                pre, cur = cur, cur.next

    def delete(self, pos):
        """
        根据位置删除
        :param pos: 位置
        """
        # 创建游标以及副游标
        cur = self.__head
        pre = None
        # 判断输入是否在链表中
        if 0 <= pos < (self.length() - 1):
            if pos == 0:
                self.__head = cur.next
            else:
                count = 0
                while count < pos:
                    count += 1
                    pre, cur = cur, cur.next
                pre.next = cur.next

    def clear(self):
        """清空链表"""
        self.__head = None