怎么通过Python创建一个循环链表、双向循环链表? *-* Python学数据结构与算法 - 4 - 数据结构线性表

循环链表与双向循环链表

循环链表

循环链表相较于单链表,将末尾结点的连接域指向了头结点,就类似于将播放器的顺序播放改成了列表循环
在这里插入图片描述

双向循环链表

双向链表相较于之前的链表多了上一节点连接域,在双向链表中,游标的移动方向可以不只是单一的向后移动,还增加了向前移动的功能。
在这里插入图片描述

在这里插入图片描述

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. del_add(self) 删除首结点
  11. del_app(self) 删除尾结点
  12. remove(elem) 指定元素删除节点
  13. delete(pos)根据位置删除
  14. clear()清空链表

Python制作

python实现循环链表

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

class LoopLinked:

    def __init__(self, node=None):
        self.__head = node
        if node:
            node.next = self.__head

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

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

    def add(self, elem):
        """头部添加元素"""
        # 创建新结点
        newNode = Node(elem)
        # 判断是否为空链表
        if self.is_empty():
            self.__head = newNode
            newNode.next = self.__head
        else:
            # 创建游标
            cur = self.__head
            # 将原头结点坐标给新结点,同时将新结点坐标给头结点,再将尾结点指向新结点
            while cur.next != self.__head:
                cur = cur.next
            newNode.next, self.__head = self.__head, newNode
            cur.next = newNode

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

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

    def insert(self, pos, elem):
        """指定位置添加元素"""
        # 判断插入位置
        if pos <= 0:
            self.add(elem)
        elif pos > (self.length() - 1):
            self.append(elem)
        else:
            # 新建结点
            newNode = Node(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 self.__head:
                return False
            cur = cur.next
            count += 1

    def del_add(self):
        """删除首结点"""
        # 创建游标
        cur = self.__head
        # 将尾结点重新指向新的头结点
        while cur.next != self.__head:
            cur = cur.next
        # 将首节点后移
        self.__head = self.__head.next
        # 让尾结点指向新的首节点
        cur.next = self.__head

    def del_app(self):
        """删除尾结点"""
        # 创建游标
        cur = self.__head
        pre = None
        while cur.next != self.__head:
            pre, cur = cur, cur.next
        pre.next = self.__head

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

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

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

双向循环链表

结点

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

我们将双向循环链表和循环链表对比,如有相同的就不在重复编写。
双向结点和单向结点主要在添加和删除结点的时候有所不同。

添加元素

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

    def add(self, elem):
        """头部添加元素"""
        # 创建新结点
        newNode = DoubleNode(elem)
        # 判断是否为空链表
        if self.is_empty():
            self.__head = newNode
            newNode.prev, newNode.next = self.__head, self.__head
        else:
            # 将新结点指向原头结点
            newNode.next = self.__head
            # 将尾结点指向新结点
            self.__head.prev.next = newNode
            # 将新结点指向尾结点
            newNode.prev = self.__head.prev
            # 将原头结点指向新结点
            self.__head.prev = newNode
            # 将原头结点定义为新结点
            self.__head = newNode

    def append(self, elem):
        """尾部添加元素"""
        # 新建结点
        newNode = DoubleNode(elem)
        # 判断是否为空链表
        if self.is_empty():
            self.__head = newNode
            newNode.prev, newNode.next = self.__head, self.__head
        else:
            # 将原尾结点指向新结点
            self.__head.prev.next = newNode
            # 将新结点指向原尾结点
            newNode.prev = self.__head.prev
            # 将尾结点指向头结点
            newNode.next = self.__head
            # 将头结点指向尾结点
            self.__head.prev = newNode

    def insert(self, pos, elem):
        """指定位置添加元素"""
        # 判断插入位置
        if pos <= 0:
            self.add(elem)
        elif pos > (self.length() - 1):
            self.append(elem)
        else:
            # 新建结点
            newNode = DoubleNode(elem)
            # 创建游标以及副游标
            cur = self.__head
            # 创建计数器
            count = 0
            # 将游标定位到指定位置前一位结点上
            while count < (pos - 1):
                count += 1
                cur = cur.next
            # 将新结点指向游标以及游标之后的结点
            newNode.prev, newNode.next = cur, cur.next
            # 将游标所在结点之后的结点指向新结点
            cur.next.prev = newNode
            # 将指针所在结点指向新结点
            cur.next = newNode

删除元素

    def del_add(self):
        """删除首结点"""
        # 创建指向尾结点的游标
        cur = self.__head.prev
        # 将头结点后移一位
        self.__head = self.__head.next
        # 将尾结点指向新的头结点
        cur.next = self.__head
        # 将新的头结点执行尾结点
        self.__head.prev = self.__head

    def del_app(self):
        """删除尾结点"""
        # 创建游标并且指向尾结点
        cur = self.__head.prev
        # 将游标前移一位
        cur = cur.prev
        # 将游标所在结点指向头结点
        cur.next = self.__head
        # 将头结点指向游标所在位置
        self.__head.prev = cur

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

    def delete(self, pos):
        """根据位置删除"""
        # 判断输入是否在链表中
        if 0 <= pos <= (self.length() - 1):
            # 判断是否为首结点
            if pos == 0:
                self.del_add()
                return
            # 判断是否为尾结点
            elif pos == self.length():
                self.del_app()
                return
            else:
                # 创建游标以及计数器
                cur = self.__head
                count = 0
                while count < pos:
                    count += 1
                    cur = cur.next
                cur.next.prev = cur.prev
                cur.prev.next = cur.next
发布了47 篇原创文章 · 获赞 23 · 访问量 3422

猜你喜欢

转载自blog.csdn.net/qq_39611230/article/details/103018989