数据结构之循环链表和栈

news2024/11/29 20:21:47

一、循环链表

1、概念

循环链表:就是首尾相连的链表,通过任意一个节点,都能将整个链表遍历一遍

分类:单向循环链表、双向循环链表

2、单向循环链表的类格式

单向循环链表也就是单向链表的最后一个节点的next域不再为None,而是第一个节点

3、单向循环链表操作

①创建

#封装节点的类
class Node:
    def __init__(self,data):
        self.data = data
        self.next = None

#封装单向循环链表类
class LinkList:
    def __init__(self,node = None):
        self.size = 0
        self.head = node

②判空

    #判空
    def is_empty(self):
        return self.size == 0

③尾插

    #尾插
    def add_tail(self,data):
        #创建一个新的节点
        node = Node(data)
        #判空
        if self.is_empty():
            self.head = node
            node.next = node
        else:
            #找到最后一个节点
            q = self.head
            while q.next != self.head:
                q = q.next

            q.next = node
            node.next = self.head
        #链表长度自增
        self.size += 1
尾插效果

④遍历

    #遍历
    def show(self):
        #判空
        if self.is_empty():
            print("失败")
        else:
            #两种: 长度遍历   位置遍历(循环结束 多打印一次)
            q = self.head
            while q.next != self.head:
                print("%d"%(q.data),end=" ")
                q = q.next
            print("%d"%(q.data),end=" ")
            print()
遍历效果

 ⑤尾删

    #尾删
    def del_tail(self):
        #判空
        if self.is_empty():
            print("删除失败,列表为空!")
        else:
            #判断长度是否为1  是否只有一个节点
            if self.size == 1:
                deleted_value = self.head.next.data
                self.head = None
            else:
                q = self.head
                i=1
                while i<self.size-1:
                    q = q.next
                    i+=1
                deleted_value = q.next.data
                q.next = self.head
            #删除成功 链表长度自减
            self.size -=1
            print(f"删除成功,值{deleted_value}已被删除!")
尾删效果

 ⑥完整代码

#判断输入是否为整数
def get_int(prompt):
    while True:
        try:
            value = int(input(prompt))
            return value
        except ValueError:
            print("无效输入,请输入一个整数。")

#判断输入是否在合理的范围内
def get_choice(prompt, min_val, max_val):
    while True:
        try:
            value = int(input(prompt))
            if min_val <= value <= max_val:
                return value
            else:
                print("无法处理您的指令,请重新输入。")
        except ValueError:
            print("无效输入,请输入一个整数。")

#封装节点的类
class Node:
    def __init__(self,data):
        self.data = data
        self.next = None

#封装单向循环链表类
class LinkList:
    def __init__(self,node = None):
        self.size = 0
        self.head = node

    #判空
    def is_empty(self):
        return self.size == 0

    #尾插
    def add_tail(self,data):
        #创建一个新的节点
        node = Node(data)
        #判空
        if self.is_empty():
            self.head = node
            node.next = node
        else:
            #找到最后一个节点
            q = self.head
            while q.next != self.head:
                q = q.next

            q.next = node
            node.next = self.head
        #链表长度自增
        self.size += 1

    #遍历
    def show(self):
        #判空
        if self.is_empty():
            print("失败")
        else:
            #两种: 长度遍历   位置遍历(循环结束 多打印一次)
            q = self.head
            while q.next != self.head:
                print("%d"%(q.data),end=" ")
                q = q.next
            print("%d"%(q.data),end=" ")
            print()
    #尾删
    def del_tail(self):
        #判空
        if self.is_empty():
            print("删除失败,列表为空!")
        else:
            #判断长度是否为1  是否只有一个节点
            if self.size == 1:
                deleted_value = self.head.next.data
                self.head = None
            else:
                q = self.head
                i=1
                while i<self.size-1:
                    q = q.next
                    i+=1
                deleted_value = q.next.data
                q.next = self.head
            #删除成功 链表长度自减
            self.size -=1
            print(f"删除成功,值{deleted_value}已被删除!")

linkList = LinkList()

linkList.add_tail(1)
linkList.add_tail(2)
linkList.add_tail(3)
linkList.add_tail(4)
linkList.add_tail(5)

# 菜单
while True:
    print("\n菜单:")
    print("1. 显示所有数据")
    print("2. 添加数据")
    print("3. 删除数据")
    print("4. 退出")
    choice = get_choice("请选择操作:", 1, 4)

    if choice == 1: # 显示所有数据
        linkList.show()
    elif choice == 2: # 添加数据
        value = get_int("请输入一个整数:")
        linkList.add_tail(value)
        print(f"数字{value}加入成功。")
    elif choice == 3: # 删除数据
        a = input("删除后无法恢复,你确定吗?: ")
        if a.lower() in ["y", "yes", "Y", "Yes", "YES", "确定", "我确定", ""]:
            linkList.del_tail()
        else:
            print("删除操作已取消。")
    elif choice == 4: # 退出程序
        print("程序已退出。")
        break

4、双向循环链表操作

①创建

class Node:
    def __init__(self, data):
        self.data = data
        self.next = None
        self.prior = None  # 新增前驱指针

#封装双向循环链表类
class DoubleCircularLinkList:
    def __init__(self, node=None):
        self.size = 0
        self.head = node

②判空

    #判空
    def is_empty(self):
        return self.size == 0

③尾插

    #尾插
    def add_tail(self, data):
        #创建一个新的节点
        node = Node(data)
        #判空
        if self.is_empty():
            # 初始化双向循环链表
            self.head = node
            node.next = node
            node.prior = node
        else:
            tail = self.head.prior  # 获取尾节点
            tail.next = node
            node.prior = tail
            node.next = self.head
            self.head.prior = node
        #链表长度自增
        self.size += 1
尾插效果

 ④遍历

    #遍历
    def show(self):
        #判空
        if self.is_empty():
            print("链表为空,显示失败!")
        else:
            #两种: 长度遍历   位置遍历(循环结束 多打印一次)
            q = self.head
            for _ in range(self.size):
                print(f"{q.data}", end=" ")
                q = q.next
            print()
遍历效果

⑤尾删

    #尾删
    def del_tail(self):
        #判空
        if self.is_empty():
            print("删除失败,列表为空!")
        else:
            tail = self.head.prior
            #判断长度是否为1  是否只有一个节点
            if self.size == 1:
                deleted_value = tail.data
                self.head = None
            else:
                deleted_value = tail.data
                new_tail = tail.prior
                new_tail.next = self.head
                self.head.prior = new_tail
            #删除成功 链表长度自减
            self.size -= 1
            print(f"删除成功,值{deleted_value}已被删除!")

尾删效果

⑥完整代码

#判断输入是否为整数
def get_int(prompt):
    while True:
        try:
            value = int(input(prompt))
            return value
        except ValueError:
            print("无效输入,请输入一个整数。")

#判断输入是否在合理的范围内
def get_choice(prompt, min_val, max_val):
    while True:
        try:
            value = int(input(prompt))
            if min_val <= value <= max_val:
                return value
            else:
                print("无法处理您的指令,请重新输入。")
        except ValueError:
            print("无效输入,请输入一个整数。")

#封装节点的类
class Node:
    def __init__(self, data):
        self.data = data
        self.next = None
        self.prior = None  # 新增前驱指针

#封装双向循环链表类
class DoubleCircularLinkList:
    def __init__(self, node=None):
        self.size = 0
        self.head = node

    #判空
    def is_empty(self):
        return self.size == 0

    #尾插
    def add_tail(self, data):
        #创建一个新的节点
        node = Node(data)
        #判空
        if self.is_empty():
            # 初始化双向循环链表
            self.head = node
            node.next = node
            node.prior = node
        else:
            tail = self.head.prior  # 获取尾节点
            tail.next = node
            node.prior = tail
            node.next = self.head
            self.head.prior = node
        #链表长度自增
        self.size += 1

    #遍历
    def show(self):
        #判空
        if self.is_empty():
            print("链表为空,显示失败!")
        else:
            #两种: 长度遍历   位置遍历(循环结束 多打印一次)
            q = self.head
            for _ in range(self.size):
                print(f"{q.data}", end=" ")
                q = q.next
            print()

    #尾删
    def del_tail(self):
        #判空
        if self.is_empty():
            print("删除失败,列表为空!")
        else:
            tail = self.head.prior
            #判断长度是否为1  是否只有一个节点
            if self.size == 1:
                deleted_value = tail.data
                self.head = None
            else:
                deleted_value = tail.data
                new_tail = tail.prior
                new_tail.next = self.head
                self.head.prior = new_tail
            #删除成功 链表长度自减
            self.size -= 1
            print(f"删除成功,值{deleted_value}已被删除!")

linkList = DoubleCircularLinkList()

linkList.add_tail(1)
linkList.add_tail(2)
linkList.add_tail(3)
linkList.add_tail(4)
linkList.add_tail(5)

while True:
    print("\n菜单:")
    print("1. 显示所有数据")
    print("2. 添加数据")
    print("3. 删除数据")
    print("4. 退出")
    choice = get_choice("请选择操作:", 1, 4)

    if choice == 1: # 显示所有数据
        linkList.show()
    elif choice == 2: # 添加数据
        value = get_int("请输入一个整数:")
        linkList.add_tail(value)
        print(f"数字{value}加入成功。")
    elif choice == 3: # 删除数据
        a = input("删除后无法恢复,你确定吗?: ")
        if a.lower() in ["y", "yes", "Y", "Yes", "YES", "确定", "我确定", ""]:
            linkList.del_tail()
        else:
            print("删除操作已取消。")
    elif choice == 4: # 退出程序
        print("程序已退出。")
        break

二、栈

1、概念

栈的概念:操作受限的线性表,对数据的插入和删除操作只能在同一端操作

栈的特点:先进后出(FILO ---->First In Last Out) 、后进先出(LIFO ---->Last In First Out)

栈顶:能够被操作的一端称为栈顶

栈底:不能被操作的一端,称为栈底

种类:顺序栈、链式栈

基本操作:创建栈、判空、入栈、出栈、获取栈顶元素、求栈的大小、遍历栈

2、顺序栈

①概念

顺序存储的栈 叫顺序栈

②顺序栈的组成

需要使用一个容器存储一个栈,例如列表

③栈的实例

# 判断选择是否合理
def get_choice(prompt, min_val, max_val):
    while True:
        try:
            value = int(input(prompt))
            if min_val <= value <= max_val:
                return value
            else:
                print(f"输入不在范围{min_val}-{max_val}之间,请重新输入。")
        except ValueError:
            print("无效输入,请输入一个整数。")


# 定义链式栈的节点
class Node:
    def __init__(self, data):
        self.data = data
        self.next = None


# 定义链式栈
class Stack:
    def __init__(self):
        self.top = None  # 栈顶节点
        self.size = 0    # 栈的大小

# 判断栈是否为空
    def is_empty(self):
        return self.top is None

# 入栈操作
    def push(self, value):
        new_node = Node(value)
        new_node.next = self.top
        self.top = new_node
        self.size += 1

# 弹出栈顶元素
    def pop(self):
        if self.is_empty():
            print("栈为空,无法弹出元素!")
        else:
            popped_value = self.top.data
            self.top = self.top.next
            self.size -= 1
            print(f"弹出元素:{popped_value}")

# 返回栈顶元素
    def peek(self):
        if self.is_empty():
            print("栈为空,无栈顶元素!")
            return None
        return self.top.data

# 遍历栈
    def show(self):
        if self.is_empty():
            print("栈为空,无法遍历!")
        else:
            current = self.top
            print("当前栈元素:", end=" ")
            while current:
                print(current.data, end=" ")
                current = current.next
            print()

# 返回栈的大小
    def get_size(self):
        return self.size

# 创建栈对象
stack = Stack()

stack.push("hello")
stack.push("world")
stack.push("hello")
stack.push("meimei")

# 菜单
while True:
    print("\n菜单:")
    print("1. 显示所有数据")
    print("2. 显示栈的大小")
    print("3. 添加数据")
    print("4. 删除数据")
    print("5. 返回栈顶元素")
    print("6. 退出")
    choice = get_choice("请选择操作:", 1, 6)

    if choice == 1:  # 显示所有数据
        stack.show()
    elif choice == 2:  # 显示栈的大小
        print(f"栈的大小:{stack.get_size()}")
    elif choice == 3:  # 添加数据
        value = input("请在这里输入你想入栈的数据:")
        stack.push(value)
        print(f"数据“{value}”已添加到栈。")
    elif choice == 4:  # 删除数据
        stack.pop()
    elif choice == 5:  # 返回栈顶元素
        top_value = stack.peek()
        if top_value is not None:
            print(f"栈顶元素:{top_value}")
    elif choice == 6:  # 退出程序
        print("程序已退出。")
        break
程序演示

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2249974.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux安装部署mysql资料

安装虚拟机 等待检查完成 选择中文 软件选择 网络和主机名 开始安装 设置root密码 ADH-password 创建用户 等待安装完成 重启 接受许可证 Centos 7 64安装完成 安装mysql开始 Putty连接指定服务器 在 opt目录下新建download目录 将mysql文件传到该目录下 查看linux服务器的…

HTML 霓虹灯开关效果

HTML 霓虹灯开关效果 1.简介&#xff1a;该代码为纯html&#xff0c;CSS写在了内部&#xff0c;不需要额外引入&#xff0c;霓虹灯开关效果很漂亮&#xff0c;应用在个人物联网项目中是一个比较不错的选择。 2.运行效果&#xff1a; 3.源码&#xff1a; <!DOCTYPE html&g…

uniapp开发支付宝小程序自定义tabbar样式异常

解决方案&#xff1a; 这个问题应该是支付宝基础库的问题&#xff0c;除了依赖于官方更新之外&#xff0c;开发者可以利用《自定义 tabBar》曲线救国 也就是创建一个空内容的自定义tabBar&#xff0c;这样即使 tabBar 被渲染出来&#xff0c;但从视觉上也不会有问题 1.官方文…

24/11/26 视觉笔记 通过特征提取和透视变换查找对象

在本节中我们将检测和跟踪任意大小的对象&#xff0c;这些对象可能是在不同角度或者在部分遮挡的情况下观察到的。 为此我们将运用特征描述子&#xff08;Feature Descriptor&#xff09;&#xff0c;这是捕获感兴趣对象的重要属性的一种方式。我们这样是为了即使将对象嵌入繁…

【单片机毕业设计12-基于stm32c8t6的智能称重系统设计】

【单片机毕业设计12-基于stm32c8t6的智能称重系统设计】 前言一、功能介绍二、硬件部分三、软件部分总结 前言 &#x1f525;这里是小殷学长&#xff0c;单片机毕业设计篇12-基于stm32c8t6的智能称重系统设计 &#x1f9ff;创作不易&#xff0c;拒绝白嫖可私 一、功能介绍 ----…

ubuntu中使用ffmpeg和nginx推http hls视频流

视频流除了rtmp、rtsp&#xff0c;还有一种是http的hls流&#xff0c;使用http协议传输hls格式的视频数据。 nginx支持推送hls视频流&#xff0c;使用的是rtmp模块&#xff0c;即rtmp流推送成功了&#xff0c;hls流也没问题。怎么推送rtmp流&#xff0c;请参考我的文章&#x…

5.2.机器学习--岭回归+局部线性回归

目录 1.岭回归 1.1代码示例 2.局部线性回归 2.1代码示例 1.最小二乘法&#xff1a; 平面几何表达直线(两个系数): 重新命名变量: 强行加一个x01&#xff1a; 向量表达&#xff1a; 2.损失函数&#xff1a; 矩阵表达&#xff1a; 矩阵展开&#xff1a; 推导&#xff1a; …

nvidia-container-toolkit安装问题(OpenPGP)

1.正常情况下 apt-get install -y nvidia-container-toolkit2.使用nvidia源 nvidia-container-toolkit官网有安装教程 2.1 配置生产存储库 curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-containe…

电脑上的ip地址可以改吗?如何改变ip地址

在现代网络环境中&#xff0c;IP地址作为设备在网络中的唯一标识&#xff0c;扮演着至关重要的角色。无论是日常上网冲浪&#xff0c;还是进行专业的网络操作&#xff0c;IP地址都与我们息息相关。那么&#xff0c;电脑上的IP地址可以改吗&#xff1f;答案是肯定的。接下来&…

org.apache.log4j的日志记录级别和基础使用Demo

org.apache.log4j的日志记录级别和基础使用Demo&#xff0c;本次案例展示&#xff0c;使用是的maven项目&#xff0c;搭建的一个简单的爬虫案例。里面采用了大家熟悉的日志记录插件&#xff0c;log4j。来自apache公司的开源插件。 package com.qian.test;import org.apache.log…

PHP 生成分享海报

因为用户端有多个平台&#xff0c;如果做分享海报生成&#xff0c;需要三端都来做&#xff0c;工作量比较大。 所以这个艰巨的任务就光荣的交给后端了。经过一定时间的研究和调试&#xff0c;最终圆满完成了任务&#xff0c;生成分享海报图片实现笔记如下。 目录 准备字体文件…

ASP.NET Core 入门

使用 .NET CLI 创建并运行 ASP.NET Core Web 应用。 文章目录 一、先决条件二、创建Web应用项目三、运行应用四、编辑Razor页面 一、先决条件 .NET 8.0 SDK 二、创建Web应用项目 打开命令行界面&#xff0c;然后输入以下命令&#xff1a; dotnet new webapp --output aspne…

基于 Flask 和 Socket.IO 的 WebSocket 实时数据更新实现

简介 随着现代化应用的快速发展&#xff0c;实时数据交互已经成为许多 Web 应用的核心需求&#xff0c;比如实时消息推送、数据监控大屏等。本文将基于一个完整的 WebSocket 实现示例&#xff0c;带你一步步理解如何使用 Flask 和 Socket.IO 构建实时数据更新的 Web 应用。 将…

十、Spring Boot集成Spring Security之HTTP请求授权

文章目录 往期回顾&#xff1a;Spring Boot集成Spring Security专栏及各章节快捷入口前言一、HTTP请求授权工作原理二、HTTP请求授权配置1、添加用户权限2、配置ExceptionTranslationFilter自定义异常处理器3、HTTP请求授权配置 三、测试接口1、测试类2、测试 四、总结 往期回顾…

详细介绍HTTP与RPC:为什么有了HTTP,还需要RPC?

目录 一、HTTP 二、RPC 介绍 工作原理 核心功能 如何服务寻址 如何进行序列化和反序列化 如何网络传输 基于 TCP 协议的 RPC 调用 基于 HTTP 协议的 RPC 调用 实现方式 优点和缺点 使用场景 常见框架 示例 三、问题 问题一&#xff1a;是先有HTTP还是先有RPC&…

【Linux】 进程是什么

0. 什么是进程&#xff0c;为什么要有进程&#xff1f; 1.操作系统为了更好的管理我们的软硬件&#xff0c;抽象出了许多概念&#xff0c;其中比较有代表的就是进程了。通俗的来说操作系统为了更好的管理加载到内存的程序&#xff0c;故引入进程的概念。 2.在操作系统学科中用P…

[OpenHarmony5.0][Docker][环境]OpenHarmony5.0 Docker编译环境镜像下载以及使用方式

T. 已测试目录 主机类型主机版本Docker镜像版本结果WSL2Ubuntu22.04Ubuntu20.04PASSWSL2Ubuntu22.04Ubuntu18.04PASS R. 软硬件要求&#xff1a; 编译硬件需求&#xff1a;做多系统测试&#xff0c;磁盘500GB起步(固态)&#xff08;机械会卡死&#xff09;&#xff0c;内存3…

vue3-使用vite创建项目

vue-cli处于维护模式&#xff0c;也可以使用脚手架正常创建vue3项目&#xff0c;与vue2创建方式一致 官方推荐使用vite创建项目 vite 是新一代前端构建工具,官网地址轻量快速的热重载&#xff08;HMR&#xff09;&#xff0c;能实现极速的服务启动。对 TypeScript、JSX、CSS 等…

Java设计模式笔记(一)

Java设计模式笔记&#xff08;一&#xff09; &#xff08;23种设计模式由于篇幅较大分为两篇展示&#xff09; 一、设计模式介绍 1、设计模式的目的 让程序具有更好的&#xff1a; 代码重用性可读性可扩展性可靠性高内聚&#xff0c;低耦合 2、设计模式的七大原则 单一职…

Vue3+node.js实现登录

文章目录 前端代码实现后端代码实现跨域处理 前端代码实现 效果图 前端代码实现 <template><div class"login-container"><el-card class"login-card"><template #header><div class"card-header"><span>…