数据结构(字符串)

news2024/11/19 16:40:29

        字符串简称串,由零个或多个字符组成的有限序列,一般记为s=“a0 a1a2…an-1”,(n≥0)。其中s称作串名,用双引号括起来的字符序列是串的值。字符ai(0≤i≤n-1)可以是字母、数字或其它字符,n为串的长度。

如:a=“SHANGHAI”,a为串名,串值为SHANGHAI,串长度为8。

Ø如果把单个字符看作一个元素,整个串看作由多个元素组成的有序序列,和前面的线性表很相似。
Ø线性表强调的是单个元素,字符串除了单个元素外,更强调的是一组连续的元素,因此字符串基本操作有一定的特殊性。
Ø字符串中元素限定为简单的字符,而线性表中元素为任意类型,甚至可以是复杂的结构。

 

相关概念

  1. 空串:串的长度为零,但仍然为一个串。
  2. 空格串:由一个或一个以上的空格组成的串,串的长度为空格的个数。
  3. 单字符串:串中只有一个字符,串长度为1。
  4. 串相等:当且仅当两个串长度相同,且对应位置上的字符完全相同。
  5. 子串:一个串中任意个连续的字符组成的子序列称为该串的子串,子串在主串中的位置以子串的第一个字符在主串中的字符位置来表示。
  6. 主串:包含子串的串称为主串。

“”为空串;“ ”为长度为1的空格串;如果

a =“SHANDONG PROVINCE”b =“SHANDONG”,则b是子串、a为主串、ba中的位置为0

串的存储

顺序及链式两种存储方式

顺序方式:字符序列在连续的存储空间中依次连续地存放;

链式方式:串中每个字符作为一个结点独立地存放在不连续的存储空间中

链式存储

        方法一是:一个结点 中只放 单一 的字符,为了得到下一个字符结点,还必须有一个指向下一个字符结点的指针。通常一个字符占用一个字节,一个指针却要占用 4 个字节,显然从空间利用的角度,这种存储非常不合算。
        方法二是:将 字符序列分成若干等长的组,每个组占据一个结点,但由于串操作常常为对连续的字符子序列进行,故并不方便

考虑以上因素,在多数情况下,串的存储采用顺序存储最为常见

顺序存储一般分静态存储和动态存储两种方式

        静态存储,用一组地址连续的存储单元存储串中的字符序列,该存储空间的大小须预先定义,即使用静态数组,一些串操作结果会因预设空间不够而自动截断

        比如,当结果串存储空间大小为10时,若将“SHANGHAI CITY”赋值给结果串,则结果串串值为“SHANGHAI ”,串长度为9,最后1个空间留给串结束符’\0’

        动态存储,同样可以用一组地址连续的存储空间存放字符串,但空间大小可以在程序执行过程中由用户输入,空间在程序运行时动态分配得来,即使用动态数组。经过串操作之后得到的结果字符串全部可以得以保留

常见错误

        对于字符串”ok”的存储,两个字符加上一个结束标志字符’\0’,共占用了3个字节。常见错误是把该字符串长度计为3,应该是2,结束符不算入内。

串的基本操作 

串的长度: 求串中字符的个数,如 “SHANG HAI” 长度为 9
串相等操作: 判断两个字符串是否长度相等,且对应位置上的字符也相等。若二者均满足,返回 true ;若有一样不等,返回 false

               “SHANGHAI”“SHANGHAI”相等,

  “SHANGHAI” “SHANGHAAI ”不等。

赋值操作: 将一个字符串赋值给另一个串。如 t =“SHANGHAI”, s=“UNIVERSITY”, s 的值赋给 t ,则 t 的值变为 “UNIVERSITY”
连接操作: 将一个字符串中的字符序列,连接在另一个串字符序列之后,形成一个新的串

t =“SHANGHAI”, s=“JIAOTONG”。连接ts,即操作t+=s之后,得到字符串t =“SHANGHAIJIAOTONG”;而连接s t,即s+=t之后得到字符串t =“JIAOTONGSHANGHAI”

定位操作: 对于一个字符或字符串 ,求 其在另一个字符串中指定字符位置之后首次出现的位置

t =“SHANGHAI”, s = “HA”,则st的第3个字符及其之后首次出现的位置序号为5

      求子串操作:在一个主串中,从指定的位置序号开始,取得一定长度的字符序列

t =“SHANGHAI”, t取第2个字符开始的4个字符长度的子串为:“ANGH”

要求的子串长度过长,超出了主串在指定字符位置后的长度限制,以主串所能提供的最大长度为准。如t =“SHANGHAI”, t取第2个字符开始的10个字符长度的子串,实际变为取第2个字符开始的6个字符长度的子串,结果为:“ANGHAI”

插入操作: 在字符串指定的位置上插入另外一个字符串

t =“SHANGHAI”,在第5个位置上插入字符串“123”后得字符串“SHANG123HAI”

删除操作: 对于一个字符串,从指定的字符位置开始,删除一定长度的字符子序列

“SHANG123HAI”,从第5个字符开始,删除3个字符后为“SHANGHAI”

 C++中关于串的库

Ø C++ 有两个字符串处理的库 cstring.h ( 面向过程 ) string( 面向对象 ) ,它们已经提供了许多实现串操作的函数,其功能和上面提供的基本操作基本相同
Ø 这里 用面向对象的方法给出字符串结构的定义、基本操作和其实现,是为了让大家进一步体会串数据结构的处理本质,相当于自定义的一个 string 库。

 

字符串类定义sstring.h:

#ifndef SSTRING_H_INCLUDED
#define SSTRING_H_INCLUDED
#include <iostream>
using namespace std;
 
class illegalSize{};
class outOfBound{};
class noSpace{};
class sstring
{    friend int* nextValue(const sstring &t); //外部函数,计算失配函数
      private:
        	char *str; //动态数组,存储字符串
            int  maxSize; //数组的尺寸
     public:
        sstring(int size); //创建动态空间,数组长度size,字符串长度为0。
        sstring(const char *t); //用字符串t初始化。
        sstring(const sstring &t); //用同类对象t初始化。
        int length() const; //实际存储的字符串长度
        void disp() const {cout<<str<<endl;}; //显示字符串
 
        //判断两个字符串是否内容一样。是返回true,否返回false。
        bool equal(const sstring &t) const;
        void assign(const sstring &t); //赋值操作,将t中字符串赋值给调用函数的对象
        sstring &subString(int pos, int len) const; //求从pos开始,长度为len的子串。
        //从串的第start个字符起,向后查找字符串t第一次在
        //串中出现的位置找到返回位置序号,未找到返回-1。
        int BF_find(const sstring &t, int start )const;//BF算法
        int KMP_find(const sstring &t, int start )const;//KMP算法
 
        // 在串的第pos个字符位置位置上,插入串t的字符串。
        // 插入成功返回true,否则返回false。
        bool insert(int pos, const sstring &t);
         // 从串的字符串的第pos个字符位置起,删除长度为n的子串。
        // 如果长度不够length,以实际长度为准。删除成功返回true,否则返回false。
        bool Remove(int pos, int n);
 
        ~sstring(){delete []str;};//释放动态空间
};
#endif // SSTRING_H_INCLUDED

 插入操作分析:

bool insert(int pos, const sstring &t)

t插入到当前串的第pos个位置中

Shanghai ”插入到“Hello SJTU”中,其中pos=5。操作时,先为插入串腾出空间,之后将插入串中字符逐个抄入腾出的空间,插入操作结束

 

字符串类部分基本操作的实现 sstring.cpp

 

#include <iostream>
#include "sstring.h"
using namespace std;

sstring::sstring(int size)//创建动态空间,数组长度size,字符串长度为0。
{
    if (size <= 0) throw illegalSize();
    str = new char[size];//动态申请数组空间
    if (!str)throw noSpace();
    maxSize = size;
    str[0]='\0';
}
//求串中从pos开始,长度为len的子串。
sstring & sstring::subString(int pos, int len)const
{   int i;
    if (pos<0) throw outOfBound();
 
    sstring *tmp = new sstring(len+1);
    for (i=0; i<len; i++)
        if (str[pos+i]=='\0') break;
        else tmp->str[i]=str[pos+i];
    tmp->str[i]='\0';
    
    return *tmp;  }
//判断两个对象中存储的字符串是否内容一样。是返回true,否返回false。
bool sstring::equal(const sstring &t)const
{
    int i=0;
    if (length() !=t.length()) return false;
    while (str[i]!='\0')
        if (str[i]!=t.str[i]) return false;
        else i++;
    return true;
}

字符串类的调试main.cpp

#include <iostream>
#include "sstring.h"
using namespace std;
int main()
{  sstring s1(50), s2("abd"), s3(s2), s4("sjtu");
    s1.disp();  s2.disp();  s3.disp();
    cout<<"length of s2 is: "<<s2.length()<<endl;
 
    if (s2.equal(s3))  cout<<"s2 is equal to s3"<<endl;
    if (s1.equal(s3))  cout<<"s1 is equal to s3"<<endl;
 	s1.assign(s2);    cout<<"after assign s1: "; s1.disp();
 	s1.insert(1,s4);  cout<<"after insert s1: "; s1.disp();
 
 	s3.Remove(1,2); cout<<"after remove s3: "; s3.disp();
 	sstring &s6 = s1.subString(2,4);
 	s6.disp();
 	return 0;
}

 常见错误

Ø 对于字符串 s t 的相互赋值,可能会使用 s.str = t.str ,但是数组不能直接赋值,正确做法应是:用循环将 t.str 指向的数组中所有元素抄写到 s.str 指向的数组中,即 s.str [ i ]= t.str [ i ]
Ø 各种操作都要特别关注结果串中是否保证了“关门字符 ’\0’ ”的存在,这点常常会忽略,但系统并不会报错,输出结果是一个无终止的长长的错误串。

 

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

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

相关文章

开发第三天(Day 03)

首先对ipl.nas进行修改&#xff1a; ; haribote-ipl ; TAB4ORG 0x7c00 ; 这个程序被读入哪里; 以下是标准FAT12格式软盘的描述JMP entryDB 0x90DB "HARIBOTE" ; 可以自由地写引导扇区的名字 (8字节)DW 512 ; 1扇区…

【动态内存管理】-关于动态内存你只知道四个函数是不够的,这里还有题目教你怎么正确使用函数,还不进来看看??

&#x1f387;作者&#xff1a;小树苗渴望变成参天大树 &#x1f4a6;作者宣言&#xff1a;认真写好每一篇博客 &#x1f4a2; 作者gitee&#xff1a;link 如 果 你 喜 欢 作 者 的 文 章 &#xff0c;就 给 作 者 点 点 关 注 吧&#xff01; &#x1f38a;动态内存管理&…

adrp 命令为何能获取符号的地址

疑问所在 在linux 启动时&#xff0c;在如下位置会将bootloader 传入的x0 - x3 参数保存到boot_args[] 变量中。代码如下&#xff1a; /* …

神经网络基础部件-损失函数详解

一&#xff0c;损失函数概述 大多数深度学习算法都会涉及某种形式的优化&#xff0c;所谓优化指的是改变 xxx 以最小化或最大化某个函数 f(x)f(x)f(x) 的任务&#xff0c;我们通常以最小化 f(x)f(x)f(x) 指代大多数最优化问题。 在机器学习中&#xff0c;损失函数是代价函数的…

Spring Security 多过滤链的使用

一、背景 在我们实际的开发过程中&#xff0c;有些时候可能存在这么一些情况&#xff0c;某些api 比如&#xff1a; /api/** 这些是给App端使用的&#xff0c;数据的返回都是以JSON的格式返回&#xff0c;且这些API的认证方式都是使用的TOKEN进行认证。而除了 /api/** 这些API…

Qt扫盲-QTextEdit理论总结

QTextEdit理论总结一、概述二、用途一&#xff1a;富文本阅读器1. 用法2. 快捷键绑定三、用途二&#xff1a;编辑器1. 用法2. 拖拽3. 快捷键绑定四、常用功能五、信号一、概述 QTextEdit是一个先进的所见即所得的 富文本 查看器/编辑器&#xff0c;支持使用 html 风格的标签或…

【QT】.pro 文件

&#x1f33f;作者&#xff1a;阿润菜菜 &#x1f4d6;专栏&#xff1a;QT开发 .pro 文件是什么 .pro就是工程文件(project)&#xff0c;它是qmake自动生成的用于生产makefile的配置文件。类似于VS中的.sln 和vsproj文件 默认情况下&#xff0c;每个 Qt 项目都包含一个后缀名为…

Huffman编码实现文件的压缩和解压缩

一个项目&#xff0c;不过处理起来也比较麻烦&#xff0c;配套可以和文件传输放一起 前提知识&#xff1a; 哈夫曼树和哈夫曼编码的概念和构建 1&#xff1a;n个数构成的哈夫曼树一共有2*n-1个结点>8 -> 15 2&#xff1a;数字越大的数离根节点越近&#xff0c;越小的数离…

无线耳机跑步会不会掉、最适合跑步用的耳机排名

现在&#xff0c;喜欢运动的人越来越多了。大家都有体会&#xff0c;多数运动是相对枯燥的&#xff0c;在运动时听听音乐&#xff0c;那是多么惬意的事情啊。为此&#xff0c;体验过多款耳机&#xff0c;但令我很满意的甚少。相信不少喜欢运动的朋友都有着跟我一样的烦恼吧&…

【Java基础知识3】Java注释:单行、多行、文档注释(如何通过 javadoc 命令生成代码文档、如何在IEDA配置自动为所有的类都添加创建者和创建日期)

本文已收录专栏 &#x1f332;《Java进阶之路》&#x1f332; 目录 本文已收录专栏 &#x1f332;《Java进阶之路》&#x1f332; &#x1f350;01、单行注释 &#x1f350;02、多行注释 &#x1f350;03、文档注释 &#x1f350;04、文档注释的注意事项 &#x1f350;05、注释…

ceres学习笔记(二)

继续关于ceres官方doc里教程的学习&#xff0c;对于powells function的学习。 一、powells function 鲍威尔法&#xff0c;严格来说是鲍威尔共轭方向法&#xff0c;是迈克尔J.D.鲍威尔提出的一种求解函数局部最小值的算法。该函数不能是可微分的&#xff0c;并且不会导出衍生函…

spring用注解读取与获取对象

前言 上一篇博客简单的介绍了spring的功能与使用&#xff0c;可以看到我们创建一个对象&#xff0c;就需要在xml中存储一个bean对象&#xff0c;这种操作非常的繁琐&#xff0c;因此spring发明了使用注解来快捷存储bean对象 配置工作 我们在xml文件中写下面的代码片段 <…

基于风光储能和需求响应的微电网日前经济调度(Python代码实现)【0】

目录 0 引言 1 计及风光储能和需求响应的微电网日前经济调度模型 1.1风光储能需求响应都不参与的模型 1.2风光参与的模型 1.3风光和储能参与模型 1.4 风光和需求响应参与模型 1.5 风光储能和需求响应都参与模型 2 需求侧响应评价 2.1 负载率 2.2 可再生能源消纳率 …

Win10PE_V2.0Nvme网络版.iso 支持Nvme硬盘免费下载无需积分

Win10PE_V2.0Nvme网络版.iso 支持Nvme硬盘免费下载无需积分 V1.0版本发布 2022年1月19日 内置常用PE工具&#xff0c;7-Zip、EasyImageX_x64、XorBoot Uefi修复、NT6修复、Ghost、CGI、Google浏览器、PENetwork、RegWorkshop、迅雷迷你版、、BOOTICEx64、windows安装器、XP安…

路径计数2

路径计数2 题目描述 一个NNN \times NNN的网格&#xff0c;你一开始在(1,1)(1,1)(1,1)&#xff0c;即左上角。每次只能移动到下方相邻的格子或者右方相邻的格子&#xff0c;问到达(N,N)(N,N)(N,N)&#xff0c;即右下角有多少种方法。 但是这个问题太简单了&#xff0c;所以现…

MySQL 数据同步 Elasticsearch 的技术方案选型

文章目录1.同步双写2.异步双写3.定时任务4.数据订阅1.同步双写 优点&#xff1a;实现简单缺点&#xff1a; 业务耦合&#xff0c;商品的管理中耦合大量数据同步代码 影响性能&#xff0c;写入两个存储&#xff0c;响应时间变长 不便扩展&#xff1a;搜索可能有一些个性化需求&…

jvm学习的核心(三)---运行时数据区详解(1)

图片等相关信息来源于&#xff1a;尚硅谷宋红康JVM全套教程 1.程序计数器 程序计数器又叫pc寄存器&#xff0c;中文有两个名字 我们可以反编译字节码文件查看方法中操作指令对应的指令地址 javap -v "对应的class文件"为什么要用pc寄存器&#xff0c;pc寄存器有什…

13、Javaweb_Filter登陆验证动态代理过滤敏感词Listener

Filter&#xff1a;过滤器 1. 概念&#xff1a; * 生活中的过滤器&#xff1a;净水器,空气净化器&#xff0c;土匪、 * web中的过滤器&#xff1a;当访问服务器的资源时&#xff0c;过滤器可以将请求拦截下来&#xff0c;完成一些特殊的功能。 * 过滤器的作用&…

深入理解计算机系统_可执行目标文件和可重定位目标文件的3个区别

这篇笔记对比一下可执行目标文件和可执行目标的3个区别。下图分别是可重定位目标文件和可执行目标文件各段结构。 1.1 可执行目标文件和可重定位目标文件的3个区别 区别1&#xff1a;可执行目标文件的rel.text和.rel.data消失了 链接器将.o中.text和.data节整合到一起时&a…

【ROS2入门】理解 ROS 2 Topics 话题

大家好&#xff0c;我是虎哥&#xff0c;从今天开始&#xff0c;我将花一段时间&#xff0c;开始将自己从ROS1切换到ROS2&#xff0c;在上一篇中&#xff0c;我们一起了解ROS 2中节点的功能以及与之交互的工具&#xff0c; 这一篇&#xff0c;我们主要会围绕ROS中另外一个重要的…