链式存储方式下字符串的replace(S,T1,T2)运算

news2024/11/25 20:21:51

链式存储方式下字符串的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;
}

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

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

相关文章

[Linux]线程池

[Linux]线程池 文章目录 [Linux]线程池线程池的概念线程池的优点线程池的应用场景线程池的实现 线程池的概念 线程池是一种线程使用模式。线程池是一种特殊的生产消费模型&#xff0c;用户作为生产者&#xff0c;线程池作为消费者和缓冲区。 线程过多会带来调度开销&#xff0c…

【计算机视觉】对极几何

文章目录 一、极线约束&#xff08;Epipolar Constraint&#xff09;二、相机标定过的情况三、相机没有标定过的情况四、八点算法&#xff08;eight-point algorithm&#xff09; 我的《计算机视觉》系列参考UC Berkeley的CS180课程&#xff0c;PPT可以在课程主页看到。 在上一…

进行商城的测试用例设计思路是什么?

进行商城的测试用例设计时&#xff0c;可以考虑以下思路&#xff1a; 1. 功能测试&#xff1a;测试商城的基本功能是否正常工作&#xff0c;包括用户注册、登录、浏览商品、搜索商品、添加商品到购物车、下单、支付等。 2. 数据验证测试&#xff1a;验证商城中的数据是否正确…

深入浅出认识Kubernetes

用来管理容器&#xff0c;容器编排工具 容器化有助于打包软件来实现这些目标&#xff0c;从而使应用程序可以轻松快速地发布和更新&#xff0c;而无需停机。Kubernetes可帮助您确保那些容器化的应用程序在所需的位置和时间运行&#xff0c;并帮助他们找到工作所需的资源和工具。…

10阶杨辉三角

【任务需求】 定义一个函数&#xff0c;根据杨辉三角的数学概念&#xff0c;使用循环嵌套进行编写实现杨辉三角的关&#xff0c;并用for循环实现10阶杨辉三角&#xff0c;最后输出时需使10阶杨辉三角每行数字左右对称&#xff0c;按要求编写程序。 def triangle(rows):triang…

将数据文件,控制文件,日志文件分别放在不同的目录下,且数据库正常启动

一、定位数据文件、控制文件、日志文件的位置 注意&#xff1a;后序需要用到这些文件的位置&#xff0c;可以在查询完毕之后先截图保存 1.以管理员身份登录数据库 sqlplus / as sysdba2.查找数据文件位置 SELECT name FROM v$datafile;3.查找控制文件位置 SELECT name FROM …

设计模式:享元模式(C#、JAVA、JavaScript、C++、Python、Go、PHP)

上一篇《原型模式》 下一篇《责任链模式》 简介&#xff1a; 享元模式&#xff0c;它是一种结构型设计模式&#xff0c;旨在有效地支持大量细粒度的对象共享&#xff0c;通过共享对象来减少内存消耗和…

【C++】缺省参数及函数重载

&#x1f4d9; 作者简介 &#xff1a;RO-BERRY &#x1f4d7; 学习方向&#xff1a;致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f4d2; 日后方向 : 偏向于CPP开发以及大数据方向&#xff0c;欢迎各位关注&#xff0c;谢谢各位的支持 目录 1. 缺省参数1.1 缺省…

常见持久层框架赏析,到底是什么让你选择 MyBatis?

在绝大多数在线应用场景中&#xff0c;数据是存储在关系型数据库中的&#xff0c;当然&#xff0c;有特殊要求的场景中&#xff0c;我们也会将其他持久化存储&#xff08;如 ElasticSearch、HBase、MongoDB 等&#xff09;作为辅助存储。但不可否认的是&#xff0c;关系型数据库…

Ubuntu20.04操作系统安装及重中之重:系统分区

最近因为学习原因&#xff0c;需要将电脑设置为双系统&#xff0c;在windows10的系统下去安装Ubuntu操作系统。本来看网上相关的安装教程蛮多的&#xff0c;以为比较简单&#xff0c;结果一路过五关斩六将&#xff0c;坑的七零八落的&#xff0c;折腾了好久&#xff0c;才算安装…

【Java】LinkedList 集合

LinkedList集合特点 LinkedList 底层基于双向链表实现增删 效率非常高&#xff0c;查询效率非常低。 LinkedList源码解读分析 LinkedList 是双向链表实现的 ListLinkedList 是非线程安全的&#xff08;线程是不安全的&#xff09;LinkedList 元素允许为null,允许重复元素Linked…

基于 ARM+FPGA+AD的高精度数据采集系统设计

随着图像处理 、 工业控制 、 无线通信等领域的飞速发 展 &#xff0c; 对数据采集系统的速度 、 精度等性能要求也越来越高 。 这些要求都对数据采集系统的设计和实现提出了新的挑 战 。 目前数据采集系统的设计方案通常分为以下几类 &#xff1a; &#xff11; &#xff0…

【持续交付】个人网站

今天给大家演示下如何基于Vuepress尝试持续交付博客网站。 也尝试过其他的方案&#xff0c;比如使用Typora导出html文件&#xff0c;并scp该文件到服务器上。 效果图 该持续交付主流程如下图 提交代码后会触发webHook生成version.txt,部署脚本每分钟轮询一次检测是否存在vers…

私有云:【14】桌面映射外网

私有云&#xff1a;【14】桌面映射外网 1、选择服务器设置2、选中以下项&#xff0c;填写自己的公网IP3、最后这个也修改掉 1、选择服务器设置 2、选中以下项&#xff0c;填写自己的公网IP 3、最后这个也修改掉 桌面映射外网设置完成&#xff0c;前提要有公网IP噶&#xff0c;…

Docker 笔记(上篇)

Docker 概述 Docker 概念 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中&#xff0c;然后发布到任何流行的 Linux或Windows操作系统的机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#xff0c;相互之…

【算法练习Day32】 斐波那契数爬楼梯使用最小花费爬楼梯

​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 斐波那契数爬楼梯使用最小花…

所有电商API接口,淘宝API接口分类,1688API、拼多多API、京东API

前往接入API 淘宝API item_get 获取商品详情 根据商品ID查询商品标题价格描述等详情数据 淘宝API item_search 按关键字搜索商品 搜索关键字&#xff0c;显示商品总数&#xff0c;标题&#xff0c;图片&#xff0c;优惠价等数据 淘宝API item_fee 获取商品快递费用 输入商品…

基于RK3568高性价比全国产EMS储能解决方案(一)概述

储能产业链框架 储能产业链可分为上游“原材料及生产设备”、中游“储能系统”、下游“储能场景应用及后市场服务”。 图1 储能产业链框架图 产业链中游的“储能电池系统”主要包括“能量管理系统(EMS)”、“电池管理系统(BMS)”、“储能逆变器(PCS)”、“电池组”四个部分。…

Java创建一个长度为10的数组,利用Arrays.sort(), 为数组元素排序

程序要求&#xff1a;1&#xff09;创建一个整型数组&#xff0c;数组的长度为10. 2&#xff09;给数组元素赋值&#xff0c;要求乱序。 3&#xff09;利用fori循环将数组元素依次输出。 4&#xff09;利用Arrays.sort(), 为数组元素排序 5&#xff09;采用增加for循环将排…

shell语法大全(超级详细!!!!),非常适合入门

本文旨在对y总的Linux基础课shell语法做学习记录&#xff0c;指令较多&#xff0c;方便日后查找。 参考视频&#xff1a;Linux基础课 参考教程&#xff1a;Linux教程 1 概论 Linux中常见的shell脚本有很多种&#xff0c;常见的有&#xff1a; Bourne Shell(/usr/bin/sh或/bi…