链式存储方式下字符串的replace(S,T1,T2)运算
链式存储方式下字符串的replace运算
- ⭐️题目
- ⭐️思路
- ⭐️代码
- ✨定义结点
- ✨打印字符串函数
- ✨计算字符串函数
- ✨初始化字符串函数
- ✨代码解读
- ✨字符串替换函数
- ✨字符串替换函数解读
- ✨ 主函数
- ✨完整代码
实现在链式存储下字符串的replace(S,T1,T2),来自课本习题的一道题目。这篇博客是我自己的思路,其中也还有很多不完善的地方,也还有很大的局限性。
希望对大家能有一点帮助。
⭐️题目
试编写一个函数,实现在链式存储方式下字符串的replace(S,T1,T2)运算。
⭐️思路
①首先,题目明确要求在链式存储方式下实现函数,所以,我们的字符串S以及我们的字符串T1,和要替换T1的字符串T2都必须是链式存储的。
明确了这一点,我们首先要初始化创建三个字符串,为了方便,写一个初始化字符串的函数。
②关于初始化一个字符串函数,采用前插或者尾插都可以。我自己写得是前插。
③关于替换掉S中T1,首先,应该是要找T1是否是在S中存在。其次应该计算T1的长度,改变有关两个结点的next值,举例即:

如上图,即改变b结点的next值,使之指向T2的头节点,并改变T2尾结点的next值,使之指向T1尾结点的后继结点。
我下面的代码并没有判断T1是否在S中是否存在,缺乏稳健性。计算T1的长度的原因是,这样以便我们能够很快找到f结点,并使T2的尾结点o指向f结点。
③关于替换,如上面所说,我们要找到关键结点。
即b结点、m结点和o结点。
b结点的找法是,当我们设置一个当前结点开始遍历循环S字符串时,也要找一个指针pre来跟踪cur指针,当cur指针指向T1的第一个字符时,这时q就指向了在了我们的目标结点。
f结点的查找方法是,我们计算T2结点的长度length,然后cur指针从当前c位置移动length-1个单位,这时cur就指向了f结点。
o结点即我们对T2字符串用指针tmp进行遍历,当以循环条件whiile(tmp->next)进行循环遍历,当不满足条件是,tmp恰好指在了尾结点即o结点。
④最后,我们改变相关结点的next值即可。
即pre->next=head2;,tmp->next=cur;
⑤释放T1.free(head1)
⭐️代码
✨定义结点
typedef struct node
{char data;struct node* next;
}linkstrnode;
✨打印字符串函数
void printstr(linkstrnode* head)
{linkstrnode* cur = head;while (cur){printf("%c", cur->data);cur = cur->next;}
}
✨计算字符串函数
int length(linkstrnode* head)
{int i = 0;linkstrnode* cur = head;while (cur){i++;cur = cur->next;}return i;
}
✨初始化字符串函数
linkstrnode* Initstr()
{int n,i;printf("请输入字符串的长度:\n");scanf("%d", &n);printf("请依次输入各节点:\n");getchar();//吸收回车linkstrnode* q = NULL;for (i = 1; i <= n; i++) {char s;scanf("%c",&s);//前插linkstrnode* newnode = (linkstrnode*)malloc(sizeof(linkstrnode));//产生新的结点newnode->data = s;newnode->next =q;q = newnode;}return q;
}
在这里插入一个在我自己写代码时的一个报错!0x00007FFC8C5325E7 (ucrtbased.dll)处(位于 DataStructure.exe 中)引发的异常: 0xC0000005: 读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突。 原因就是 使用了malloc函数 ,但没有包含<stdlib.h>头文件。
✨代码解读
①
首先,对于getchar()这一行
在下面的for循环中,用scanf来接收从键盘输入的字符。在上面,我们知道此时还有一个回车留在了缓冲区,如果不将缓冲区中的回车清除,那么scanf函数读取到的第一个字符就是回车了而不是从键盘输入的第一个字符。
②
在for循环中,scanf先从缓冲区读取到一个字符,然后我们用malloc函数在堆上开辟内存,开辟空间的大小即sizeof(linkstrnode),然后让栈上面的局部变量newnode来管理这块内存。
当我们开辟好空间,即开辟好一个结点的空间,我们就需要通过指针newnode来对这个结点进行赋值。newnode->data=s;即将scanf读取到的字符s赋值给newnode的data域。
那关键就在于next域,它就关键在可以将我们所输入的字符“连接起来”。
在这里我采用前插的方法。即我使一个字符所在的结点指向空。

然后此时,我存下来现在结点的值
q=newnode;
然后第二个结点如是,

然后最后一次的q即为这个链表的头节点。
✨字符串替换函数
//创建字符串替换函数
void strreplace(linkstrnode* head, linkstrnode *head1, linkstrnode* head2)
{linkstrnode* pre = NULL;linkstrnode* cur = head;linkstrnode* q;//q结点作为指向cur结点指针的前驱结点指针int i = 0;while (cur){if (cur->data == head1->data){while (i < length(head1) && cur){i++;cur = cur->next;}break;}else {pre = cur;cur = cur->next; }}//将T2替换原来T1的位置,插入到字符串S中//先找到T2的尾结点linkstrnode* tmp = head2;while (tmp->next){tmp = tmp->next;}pre->next = head2;tmp->next = cur;
}
✨字符串替换函数解读
head指向字符串S的头节点,head1是指向字符串T1的头节点,T2是指向字符串T2的头节点。
①
指针cur用来循环遍历S字符串。
❌❌我这里在S中查找T1字符串不严谨!只是判断了cur所指向的当前结点的值是否和T1头结点的值是否相等,就直接进行了替换。
当cur所指向结点的值和T1头节点的值不相等时,进入else条件体。

直到cur所指向结点的值和T1头节点的值相等。
若相等,则pre就指向了–>如图(假设d结点即是T1字串第一个结点的值)

这时,我们进入if条件体。我们需要的是,移动指针cur,使之指向T1尾结点值的后一个结点。(举例,若T1尾结点值为f,则我们需要将cur指向g)
这时,我们就需要直到T1的长度,使循环cur移动length-1次即可。
此时cur指向了–>如图
此时我们在循环中达到了目的,break退出循环即可。
②
下面,我们仍然是利用长度找到T2的尾结点。
③连接

即pre->next=head2;
tmp->next=cur;
✨ 主函数
int main()
{printf("*****创建字符串S*****\n");linkstrnode* head=Initstr();//创建指向字符串S头节点的指针printf("字符串S为:");printstr(head);printf("\n");printf("*****创建字符串T1*****\n");linkstrnode* head1 = Initstr();//创建指向字符串T1头节点的指针printf("字符串T1为:");printstr(head1);printf("\n");printf("*****创建字符串T2*****\n");linkstrnode* head2 = Initstr();//创建指向字符串T2头节点的指针printf("字符串T2为:");printstr(head2);printf("\n");strreplace(head, head1, head2);printf("被替换后的字符串S:");printstr(head);free(head1);//释放T1字符串所占的空间return 0;
}
✨完整代码
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include<stdlib.h>//定义结点
typedef struct node
{char data;struct node* next;
}linkstrnode;//初始化链式字符串 (使用前插)
linkstrnode* Initstr()
{int n,i;printf("请输入字符串的长度:\n");scanf("%d", &n);printf("请依次输入各节点:\n");getchar();//吸收回车linkstrnode* q = NULL;for (i = 1; i <= n; i++) {char s;scanf("%c",&s);//前插linkstrnode* newnode = (linkstrnode*)malloc(sizeof(linkstrnode));//产生新的结点newnode->data = s;newnode->next =q;q = newnode;}return q;
}//打印字符串
void printstr(linkstrnode* head)
{linkstrnode* cur = head;while (cur){printf("%c", cur->data);cur = cur->next;}
}//计算字符串的长度
int length(linkstrnode* head)
{int i = 0;linkstrnode* cur = head;while (cur){i++;cur = cur->next;}return i;
}//创建字符串替换函数
void strreplace(linkstrnode* head, linkstrnode *head1, linkstrnode* head2)
{linkstrnode* pre = NULL;linkstrnode* cur = head;linkstrnode* q;//q结点作为指向cur结点指针的前驱结点指针int i = 0;while (cur){if (cur->data == head1->data){while (i < length(head1) && cur){i++;cur = cur->next;}break;}else {pre = cur;cur = cur->next; }}//将T2替换原来T1的位置,插入到字符串S中//先找到T2的尾结点linkstrnode* tmp = head2;while (tmp->next){tmp = tmp->next;}pre->next = head2;tmp->next = cur;}//主函数
int main()
{printf("*****创建字符串S*****\n");linkstrnode* head=Initstr();//创建指向字符串S头节点的指针printf("字符串S为:");printstr(head);printf("\n");printf("*****创建字符串T1*****\n");linkstrnode* head1 = Initstr();//创建指向字符串T1头节点的指针printf("字符串T1为:");printstr(head1);printf("\n");printf("*****创建字符串T2*****\n");linkstrnode* head2 = Initstr();//创建指向字符串T2头节点的指针printf("字符串T2为:");printstr(head2);printf("\n");strreplace(head, head1, head2);printf("被替换后的字符串S:");printstr(head);free(head1);return 0;
}相关文章:
链式存储方式下字符串的replace(S,T1,T2)运算
链式存储方式下字符串的replace运算 ⭐️题目⭐️思路⭐️代码✨定义结点✨打印字符串函数✨计算字符串函数✨初始化字符串函数✨代码解读✨字符串替换函数✨字符串替换函数解读✨ 主函数✨完整代码 实现在链式存储下字符串的replace(S,T1,T2),来自课本习题的一道题…...
unity脚本_Mathf和Math c#
首先创建一个脚本 当我们要做一个值趋近于一个值变化时 可以用Mathf.Lerp(start,end,time);方法实现 比如物体跟随...
轻量级仿 Spring Boot=嵌入式 Tomcat+Spring MVC
啥?Spring Boot 不用?——对。就只是使用 Spring MVC Embedded Tomcat,而不用 Boot。为啥?——因为 Boot 太重了:) 那是反智吗?Spring Boot 好好的就只是因为太重就不用?——稍安勿…...
笔记Kubernetes核心技术-之Controller
2、Controller 2.1、概述 在集群上管理和运行容器的对象,控制器(也称为:工作负载),Controller实际存在的,Pod是抽象的; 2.2、Pod和Controller关系 Pod是通过Controller实现应用运维,比如:弹…...
Azure云工作站上做Machine Learning模型开发 - 全流程演示
目录 本文内容先决条件从“笔记本”开始设置用于原型制作的新环境(可选)创建笔记本开发训练脚本迭代检查结果 关注TechLead,分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验,同济本复旦硕࿰…...
前端 : 用html ,css,js写一个你画我猜的游戏
1.HTML: <body><div id "content"><div id "box1">计时器</div><div id"box"><div id "top"><div id "box-top-left">第几题:</div><div id "box…...
Illustrator 2024(AI v28.0)
Illustrator 2024是一款功能强大的矢量图形编辑软件,由Adobe公司开发。它是设计师、艺术家和创意专业人士的首选工具,用于创建和编辑各种矢量图形、插图、图标、标志和艺术作品。 以下是Adobe Illustrator的主要功能和特点: 矢量图形编辑&…...
【Git企业开发】第二节.Git 的分支管理
作者简介:大家好,我是未央; 博客首页:未央.303 系列专栏:Git企业级开发 每日一句:人的一生,可以有所作为的时机只有一次,那就是现在!!!࿰…...
第三章认识Node.js模块化开发
目录 认识Node.js 概述 作用 基本使用 Node.js的运行 Node.js的组成 Node.js的语法 Node.js全局对象 认识模块化开发 概述 场景 特点 模块成员的导入和导出 Node.js 模块化语法 导入模块 导出模块 ES6 模块化语法 导入模块 导出模块 项目 认识Node.js 概述…...
扩展Nginx的无限可能:掌握常见扩展模块和第三方插件的使用方法
Nginx是一款高性能的开源Web服务器和反向代理服务器。它具有模块化的架构,可以通过扩展模块和插件来增强其功能。在本文中,我将围绕Nginx的扩展模块和插件进行讲解,并提供一些常见的扩展模块和第三方插件的示例。 一、Nginx扩展模块 Nginx的…...
centos遇到的问题
lsof -i :8091 > 查看这个端口的线程 lsof : list open files 列出打开文件 -i : internet linux检测系统进程和服务: top : 实时监视系统的进程和资源的利用情况htop : top的增强版 问题: -bash: …...
本机spark 通idea连接Oracle的坑
1. 报错:Exception in thread "main" java.lang.NoSuchMethodError: scala.Product.$init$(Lscala/Product;)V 查询网上资料,是idea引入的scala运行环境版本与idea默认的scala版本不一样 也就是写的项目中的pom的spark版本与idea默认的版本不…...
网络协议--DNS:域名系统
14.1 引言 域名系统(DNS)是一种用于TCP/IP应用程序的分布式数据库,它提供主机名字和IP地址之间的转换及有关电子邮件的选路信息。这里提到的分布式是指在Internet上的单个站点不能拥有所有的信息。每个站点(如大学中的系、校园、…...
计算机视觉注意力机制小盘一波 (学习笔记)
将注意力的阶段大改分成了4个阶段 1.将深度神经网络与注意力机制相结合,代表性方法为RAM ⒉.明确预测判别性输入特征,代表性方法为STN 3.隐性且自适应地预测潜在的关键特征,代表方法为SENet 4.自注意力机制 通道注意力 在深度神经网络中…...
LVS+keepalive高可用集群
keepalive简介 keepalive为LVS应用延伸的高可用服务。lvs的调度器无法做高可用。但keepalive不是为lvs专门集群服务的,也可以为其他的的代理服务器做高可用。 keepalive在lvs的高可用集群,主调度器和备调度器(可以有多个) 一主两备或一主一备。 VRRP: k…...
Thread 和 Runnable 的区别
Thread 和 Runnable 接口的区别有四个: Thread 是一个类,Runnable 是接口,因为在 Java 语言里面的继承特性,接口可以支持多继承,而类只能单一继承。所以如果在已经存在继承关系的类里面要实现线程的话,只能…...
图神经网络和分子表征:5. Completeness
大家都知道 “两点确定一线,三点确定一平面”,那么多少个变量可以确定一个分子呢?这是最近顶刊们热烈讨论的话题。 (据笔者不完全统计)最早在 SphereNet (2022 ICLR)论文里,摘要上就…...
css-渐变色矩形
效果图: 代码: html: <!DOCTYPE html> <html><head><meta charset"utf-8"><meta name"viewport" content"initial-scale1.0, user-scalableno" /><title></title><link …...
使用easypoi-spring-boot-starter 4.1.1导入excel报错NoSuchMethodError和NoSuchMethodError
前言 使用easypoi进行excel的导入遇到的错误以及解决办法 easypoi项目地址:https://gitee.com/lemur/easypoi easypoi的Maven依赖: <dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-spring-boot-starter<…...
matlab中类的分别之handle类和value类——matlab无法修改类属性值的可能原因
写在之前(吐槽) 最近由于变化了一些工作方向,开始需要使用matlab进行开发,哎哟喂,matlab使用的我想吐,那个matlab编辑器又没代码提示,又没彩色,我只好用vscode进行代码编辑…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...
