当前位置: 首页 > news >正文

【4】数据结构的循环链表章

目录标题

    • 循环链表的定义
      • 循环链表的初始化
      • 循环链表的创建
      • 循环链表的插入
      • 循环链表的删除
    • 循环链表总代码与调试
    • 顺序表与链表的比较
    • 链式存储方式的比较

循环链表的定义

  • 循环链表的结点定义与单链表一致,只包含数据域(data)和指针域(next)。
  • 定义:循环链表作为一种首尾相接的链表,其尾结点的后继指针又指向链表的第一个结点,形成一个闭环。
  • 循环链表逻辑结构示意图

在这里插入图片描述

  • 代码定义循环链表结点
class Node:
    """
    定义循环链表结点类型
    """
    def __init__(self, data):
        # 存储结点中的数据域
        self.data = data
        # 指向后继结点的指针域next
        self.next = None

循环链表的初始化

  • 初始化循环链表
class CLinkedList:
    """
    循环链表的定义
    """
    def __init__(self):
        """
        循环链表的初始化
        """
        # 声明头指针,将头结点的后继结点指向自己
        self.head = Node(None)
        self.head.next = self.head
  • 判断循环链表是否为空
    def isEmpty(self):
        """
        判断是否为空
        :return: true or false
        """
        return self.head.next is self.head
  • 求循环链表的长度
    def getLength(self):
        """
        获取循环链表的长度
        :return: 当前循环链表中元素的个数
        """
        # length用来计算循环链表的长度
        length = 0
        # 声明cur指针,用于遍历链表
        cur = self.head.next
        # 若cur没有指向自己,则表明未遍历完成
        while cur != self.head:
            length += 1
            cur = cur.next
        return length
  • 打印循环链表
    def display(self):
        """
        遍历循环链表,进行展示
        :return:
        """
        if self.isEmpty():
            print("当前循环链表为空!")
            return
        print("循环链表的元素为:", end='')
        # 遍历循环链表
        cur = self.head.next
        while cur != self.head:
            print(cur.data, end='')
            cur = cur.next
        print()

循环链表的创建

  • 使用尾插法实现循环链表的创建

  • 核心思想:

    • 查找到链表的尾结点
    • 将尾结点的后继结点指针指向新结点
    • 将新结点的后继指针指向头结点
  • 代码实现

    def append(self, data):
        """
        建立循环链表
        :param data: 待插入的元素
        :return:
        """
        # 查找尾结点
        rear = self.head
        while rear.next != self.head:
            rear = rear.next
        # 创建新结点
        newNode = Node(data)
        # 将尾结点的后继结点指针指向新结点
        rear.next = newNode
        # 将新结点的后继结点指针指向头结点
        newNode.next = self.head

循环链表的插入

  • 核心思想
    • 声明指针pre与递增变量i变量循环链表,找到需插入位置的前一结点;
    • 创建新结点,将元素值赋予结点;
    • 将新结点的后继指针指向指针pre的后继结点;
    • 将第index个结点的后继指针指向新结点
  • 插入示意图

在这里插入图片描述

  • 代码实现
    def insert(self, index, data):
        """
        在循环链表中任一位置插入元素
        :param index: 待插入的位置
        :param data: 待插入的元素值
        :return:
        """
        i = 1
        # 声明指针pre,用于遍历循环链表
        pre = self.head.next
        # 遍历停止的条件,pre为空,或指向下标为index-1的结点
        while pre != self.head and i != index-1:
            pre = pre.next
            i += 1
        # index非法
        if pre == self.head or i > self.getLength():
            raise IndexError("index 非法")
        # 创建新结点
        newNode = Node(data)
        # 将新结点的后继指针指向指针pre的后继结点
        newNode.next = pre.next
        # 将第index个结点的后继指针指向新结点
        pre.next = newNode

循环链表的删除

  • 核心思想

    • 声明指针pre与递增变量i变量循环链表,找到需删除位置的前一结点;
    • 保留被删元素的值,再对结点进行删除;
    • 将pre的后继结点指向pre指针后继结点的后继结点;
    • 实现被删结点的断连。
  • 删除示意图
    在这里插入图片描述

  • 代码实现

    def delete(self, index):
        """
        在循环链表中任一位置删除元素
        :param index: 删除下标index的元素
        :return: 被删的元素值
        """
        if self.isEmpty():
            raise IndexError("当前循环链表为空!")
        i = 1
        # 声明指针pre,用来遍历循环链表
        pre = self.head.next
        # 遍历停止的条件,pre为空,或指向下标为index-1的结点
        while pre != self.head and i != index - 1:
            pre = pre.next
            i += 1
        # index非法
        if pre == self.head or i > self.getLength():
            raise IndexError("index 非法")
        # 获取被删元素的值
        data = pre.next.data
        # 将要删结点从循环链表中断开
        pre.next = pre.next.next
        return data

循环链表总代码与调试

# 6.循环链表的实现
class Node:
    """
    定义循环链表结点类型
    """
    def __init__(self, data):
        # 存储结点中的数据域
        self.data = data
        # 指向后继结点的指针域next
        self.next = None


class CLinkedList:
    """
    循环链表的定义
    """
    def __init__(self):
        """
        循环链表的初始化
        """
        # 声明头指针,将头结点的后继结点指向自己
        self.head = Node(None)
        self.head.next = self.head
    def isEmpty(self):
        """
        判断是否为空
        :return: true or false
        """
        return self.head.next is self.head
    def getLength(self):
        """
        获取循环链表的长度
        :return: 当前循环链表中元素的个数
        """
        # length用来计算循环链表的长度
        length = 0
        # 声明cur指针,用于遍历链表
        cur = self.head.next
        # 若cur没有指向自己,则表明未遍历完成
        while cur != self.head:
            length += 1
            cur = cur.next
        return length
    def display(self):
        """
        遍历循环链表,进行展示
        :return:
        """
        if self.isEmpty():
            print("当前循环链表为空!")
            return
        print("循环链表的元素为:", end='')
        # 遍历循环链表
        cur = self.head.next
        while cur != self.head:
            print(cur.data, end='')
            cur = cur.next
        print()
    def append(self, data):
        """
        建立循环链表
        :param data: 待插入的元素
        :return:
        """
        # 查找尾结点
        rear = self.head
        while rear.next != self.head:
            rear = rear.next
        # 创建新结点
        newNode = Node(data)
        # 将尾结点的后继结点指针指向新结点
        rear.next = newNode
        # 将新结点的后继结点指针指向头结点
        newNode.next = self.head
    def insert(self, index, data):
        """
        在循环链表中任一位置插入元素
        :param index: 待插入的位置
        :param data: 待插入的元素值
        :return:
        """
        i = 1
        # 声明指针pre,用于遍历循环链表
        pre = self.head.next
        # 遍历停止的条件,pre为空,或指向下标为index-1的结点
        while pre != self.head and i != index-1:
            pre = pre.next
            i += 1
        # index非法
        if pre == self.head or i > self.getLength():
            raise IndexError("index 非法")
        # 创建新结点
        newNode = Node(data)
        # 将新结点的后继指针指向指针pre的后继结点
        newNode.next = pre.next
        # 将第index个结点的后继指针指向新结点
        pre.next = newNode

    def delete(self, index):
        """
        在循环链表中任一位置删除元素
        :param index: 删除下标index的元素
        :return: 被删的元素值
        """
        if self.isEmpty():
            raise IndexError("当前循环链表为空!")
        i = 1
        # 声明指针pre,用来遍历循环链表
        pre = self.head.next
        # 遍历停止的条件,pre为空,或指向下标为index-1的结点
        while pre != self.head and i != index - 1:
            pre = pre.next
            i += 1
        # index非法
        if pre == self.head or i > self.getLength():
            raise IndexError("index 非法")
        # 获取被删元素的值
        data = pre.next.data
        # 将要删结点从循环链表中断开
        pre.next = pre.next.next
        return data


if __name__ == '__main__':

    print('PyCharm')
    # 循环链表调试
    # 1.初始化
    list = CLinkedList()
    list.display()
    # 2. 创建循环链表,尾插法
    for i in range(10):
        list.append(chr(ord('A') + i))
    print('尾插法结果:', end='')
    list.display()
    # 3.获取循环链表长度
    length = list.getLength()
    print('循环链表长度', length)
    # 4.在表中插入元素
    list.insert(2, 'Y')
    list.display()
    # 5.在表中删除元素
    data = list.delete(3)
    print('被删除元素值为:', data)
    list.display()

顺序表与链表的比较

  • 空间上:顺序表存储空间静态分配;动态链表的存储空间为动态分配。
  • 时间上:顺序表随机存取,链式表需从头指针开始取得。
  • 插入删除上:顺序表平均需移动近一半元素;链式表只需修改指针。
  • 操作上:顺序表的存储等操作较为简单,而链式表中指针的操作较为复杂,难操作。

链式存储方式的比较

在这里插入图片描述

  • 带头结点的循环链表
    在这里插入图片描述
  • 带尾结点的循环链表
    在这里插入图片描述

相关文章:

  • MySQL 存储过程的实用技巧与最佳实践
  • Business English Certificates (BEC) 高频词汇背诵
  • 【C / C++】蓝桥第27场月赛
  • vue2 vue3 响应式差异
  • Android NDK C/C++交叉编译脚本
  • c++使用gstreamer录屏+声音
  • JVM中常见的垃圾回收器(Garbage Collectors)
  • Angular 项目使用 pdf.js 及批注插件Elasticpdf 教程
  • React框架的Concurrent Mode
  • ROS Bag 数据裁剪教程
  • 1. 标准库的强依赖(核心原因)
  • Kafka 中的事务
  • C++抽卡模拟器
  • testflight上架ipa包-只有ipa包的情况下如何修改签名信息为苹果开发者账户对应的信息-ipa苹果包如何手动改签或者第三方工具改签-优雅草卓伊凡
  • 搭建自己的企业知识库系统:基于 Wiki.js 的云服务器部署实战
  • Qt 入门 1 之第一个程序 Hello World
  • ABAP 新语法 - corresponding
  • 基于混合模型的三步优化框架在人形机器人跳跃运动中的应用
  • 代码随想录算法训练营--打卡day6
  • Unity检索一个物体下所有的子物体,包括未激活
  • 建设银行官方网站个人系统板块修改/搜索推广
  • 网址站/重庆网站优化
  • 小程序游戏定制开发/seo网站分析报告
  • 网站建设营业执照/最近一周新闻大事件
  • 做PS的赚钱的网站/百度收录查询接口
  • 二级域名网站建设/自己建网站