数据结构 -- 字符串

字符串

串的定义

串,即字符串(String)是由零个或多个字符组成的有限序列,一般记为S=‘a1a2a3a4’ (n≥0)

其中,S是串名,单引号括起来的是字符序列是串的值;ai可以是字母、数字或是其他字符;串中字符的个数n称为串的长度。n=0时的串称为空串(用 ∅ 表示)。

例:(不同语言可能使用的边界符不同,Java、c等使用双引号(“ ”)Python等使用单引号(’ ‘))

S = "HelloWorld!"

T = 'Hello World!' (空格也占一字符)

常用术语:

子串:串中任意个连续的字符组成的子序列(也可以是零个)

主串:包含子串的串

字符在主串中的位置:字符在串中的序号(一般来说讨论的是第一次出现的位置)

子串在主串中的位置:子串的第一个字符在主串中的位置

空串 V.S 空格串

空串:M = ''

空格串:N = ' '

N是由三个空格字符组成的空格串,每个空格字符占1B

串 V.S 线性表

串是一种特殊的线性表,数据元素之间呈线性关系

串的数据对象限定为字符集(如中文字符、英文字符、数字字符、标点字符等)

串的基本操作,如增删改查等通常以子串为操作对象

基本操作

假设有串T = ""S = "Hello World!"W = "llo "

StrAssign(&T,char) 赋值操作。把串T赋值为chars。

StrCopy(&T,S) 复制操作。由串S复制得到串T。

StrEmpty(S) 判空操作。若S为空串,则返回TRUE,否则返回FALSE。

StrLength(S) 求串长。返回串S的元素个数。

ClearString(&S) 清空操作。将S清空为空串。

DestroyString(&S) 销毁串。将串S销毁(回收存储空间)。

注:清空操作和销毁操作的区别:

清空串:将S清空为空串,后续还可以再存放数据

销毁串:将S原本分配的空间回收,后续想要再次存放数据需要重新分配内存空间

Concat(&T,S1,S2) 串联接。用T返回由S1和S2联接而成的新串,放入T中。

eg. 执行Concat(&T,S,W)后,T = "Hello World!llo "

//如果经常进行联接操作,需要考虑使用容易进行存储空间扩展的数据结构进行串的定义

SubString(&Sub,S,pos,len) 求子串。用Sub返回串S的第pos个字符起长度为len的子串。

eg. 执行SubString(&T,S,4,4)后,T = “lo w”

Index(S,T) 定位操作。若主串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的位置;否则函数值为0。

eg. 执行Index(S,W)后,返回值为3

StrCompare(S,T) 比较操作。若S > T,则返回值 > 0;若S = T,则返回值 = 0;若S < T,则返回值 < 0 。

字符集编码

任何数据存到计算机中一定是二进制数。需要确定一个字符和二进制数的对应规则 – ”编码“

”字符集“:

英文字符 – ASCII字符集

中英文字符 – Unicode字符集 (基于同一个字符集,可以有多种编码方案,如:UTF-16,UTF-8)

[!IMPORTANT]

采用不用的编码方式,每个字符所占的空间不同,考研中只需要默认每个字符占1B即可

[拓展] 乱码问题

产生原因:解码方式错误

在文件中,原本采用了一个编码方案进行映射并保存了映射结果,但是在使用另一个软件进行打开时,软件认为采用的是另一种编码规则并使用该规则进行解码,所以会显示乱码

存储结构

顺序存储

ElemType→char

//静态数组实现(定长顺序存储)
#define MAXLEN 255		//预定义最大串长255
typedef struct{
    char ch[MAXLEN];	//每个分量存储一个字符
    int length;			//串的实际长度
}SString;

//动态数组实现(堆分配存储)
typedef struct{
    char *ch;		//按串长分配存储区,ch指向串的基地址
    int lenth;		//串的长度
}HString;

bool InitHString(HString &S){
    S.ch = (char*)malloc(MAXLEN * sizeof(char));	//空间回收时需要进行free操作
    if(ch == NULL)	return false;
	S.length = 0;
    return true;
}

方案一:

使用变量length存放字符串长度

方案二:

使用 ch[0] 充当 length

优点:各字符的位序和数组下标相同,长度读取方便

缺点:ch 中每个元素只占 1B 大小,只能表示数字 0~255 ,因此使用这种方法要求字符串长度不超过255

方案三:

没有 length 变量,以字符 ’\0‘ 表示结尾(对应 ASCII 码的 0 )

缺点:长度读取不便(每次都需要遍历)

方案四:

(方案一和方案二的结合)

ch[0] 废弃不用,声明一个专门的 int 型变量 length 记录字符串长度

链式存储
typedef struct StringNode{
    char ch;					//每个结点存一个字符(占1B)
    struct StringNode * next;	//指向下一个字符(每个指针占4B)
}StringNode,* String;

缺点:存储密度低

优化:

typedef struct StringNode{
    char ch[4];					//每个结点存四个字符(占4B)(也可以更多)
    struct StringNode * next;	//指向下一组字符(每个指针占4B)
}StringNode,* String;

注意:如果最后一个结点存不满,可以使用一些特殊的字符进行填充

基于顺序存储实现的基本操作

StrAssign(&T,char) 赋值操作。把串T赋值为chars。

StrCopy(&T,S) 复制操作。由串S复制得到串T。

StrEmpty(S) 判空操作。若S为空串,则返回TRUE,否则返回FALSE。

StrLength(S) 求串长。返回串S的元素个数。

ClearString(&S) 清空操作。将S清空为空串。

DestroyString(&S) 销毁串。将串S销毁(回收存储空间)。

Concat(&T,S1,S2) 串联接。用T返回由S1和S2联接而成的新串,放入T中。

SubString(&Sub,S,pos,len) 求子串。用Sub返回串S的第pos个字符起长度为len的子串。

Index(S,T) 定位操作。若主串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的位置;否则函数值为0。

StrCompare(S,T) 比较操作。若S > T,则返回值 > 0;若S = T,则返回值 = 0;若S < T,则返回值 < 0 。

//使用顺序存储中的第四种方案进行存储:ch[0]不存放数据,并使用length进行长度存储
#define MAXLEN 255		//预定义最大串长255
typedef struct{
    char ch[MAXLEN];	//每个分量存储一个字符
    int length;			//串的实际长度
}SString;

bool SubString(SString &Sub,SString S,int pos,int len){
    //子串范围越界
    if(pos+len-1 > S.length)	return false;
    for(int i = pos;i < pos+len;i++){
        Sub.ch[i-pos+1] = S.ch[i];
    } 
    Sub.length = len;
    return true;
}

int StrCompare(SString S,SString T){
    for(int i = 1;i<=S.length&&i<=T.length;i++){
        if(S.ch[i]!=T.ch[i])	return S.ch[i] - T.ch[i];
    }
    //扫描过的字符都相同,则长度长的串更大
    return S.length - T.length;
}

//定位操作,每次从主串中取与长度与子串长度相同的子串
int Index(SString S,SString T){
    int i = 1;n = StrLength(S),m = StrLength(T);
    SString sub;	//用于暂存当前取出的子串
    while(i<=n-m+1){
        SubString(sub,S,i,m);
        if(StrCompare(sub,T)!=0)	++i;
        else return i;	//返回子串在主串中的位置
    }
    return 0;	//S中不存在与T相等的子串
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_安晓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值