Python创建一个循环链表、双向循环链表

枫铃3年前 (2021-09-30)Python239

循环链表与双向循环链表

循环链表

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

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

Python创建循环链表与双向循环链表

计划实现以下功能

  • is_empty() 链表是否为空
  • length() 链表长度
  • add(elem) 链表头部添加元素
  • append(elem) 链表尾部添加元素
  • travel() 遍历整个链表
  • position(pos)根据位置读取指定元素
  • element(elem)输出元素所在位置
  • search(elem) 查找节点是否存在
  • insert(pos, elem) 指定位置添加元素
  • del_add(self) 删除首结点
  • del_app(self) 删除尾结点
  • remove(elem) 指定元素删除节点
  • delete(pos)根据位置删除
  • 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

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

添加元素

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:531509025
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
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

相关文章

利用python同步windows和linux文件

写python脚本的初衷,每次在windows编辑完文件后,想同步到linux上去,只能够登录服务器,...

爬虫基本原理

爬虫基本原理 一、爬虫是什么? 百度百科和维基百科对网络爬虫的定义:简单来说爬虫就是抓取目标网站内容的工具,一般是根据定义的行...

Django 函数和方法的区别

函数和方法的区别 1、函数要手动传self,方法不用传 2、如果是一个函数,用类名去调用,如果是一个方法...

Django 知识补漏单例模式

单例模式:(说白了就是)创建一个类的实例。在 Python 中,我们可以用多种方法来实现单例模式&#x...

Django基础知识MTV

Django简介 Django是使用Python编写的一个开源Web框架。可以用它来快速搭建一个高性能的网站。 Django也是一个MVC框架。但是在Dj...

Python mysql 索引原理与慢查询优化

一 介绍 为何要有索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。