定义
串,即字符串(String)是由零个或者多个字符组成的有限序列。
一般记为:
如: S = ' HelloWorld!' *空格也算一个字符
术语:
子串:串中任意连续的字符组成的子序列
主串:包含子串的串
字符在主串中的位置:字符在串中的序列。
子串在主串中的位置:以子串第一个字符所在主串的位置作为子串的位置。
空串与空格串: M='' N=' '
*串也是一种特殊的线性表,数据元素之间呈线性结构
*串的基本操作,如增删改查等通常是以子串作为操作对象。
串的存储结构
顺序存储
//静态数组实现
#define Maxlen 255
typedef struct {
char ch[Maxlen];
int length; //串长
}SString;
//动态数组实现
typedef struct {
char* ch;
int length;
}HString;
/*
* //需要手动释放内存 free()
* HString S;
* S.ch = (char *)malloc(Maxlen * sizeof(char));
* S.length = 0;
*/
末尾是存放length
链式存储
//链式存储
typedef struct StringNode{
char ch;
struct StringNode* next;
}StringNode ,*Node;
*但这样的链式存储的问题在于,每个结点的指针域要占4B的空间,而char类型的数据只有1B,空间太浪费。
*但我们可以让多个字符存储在一个结点中,这样的存储密度就会提高。
//链式存储
typedef struct StringNode{
char ch[4];
struct StringNode* next;
}StringNode ,*Node;
如果最后一个结点的数据填不满可以采用一些特殊字符填充。如 /0 或者#。
基本操作
求串长
int StringLength(SString S) {
for (int i = 0; i < Maxlen - 1; i++) {
if (S.ch[i] == NULL) {
return i;
}
}
return Maxlen;
}
求子串(静态的顺序数组存储)
//求子串SubString(&Sub,S,pos,len)
bool SubString(SString& Sub, SString S, int pos, int len) { //将S串中,第pos个字符起长度为len的子串传入 Sub中
//子串范围越界
if (pos + len - 1 > S.length) {
return false;
}
else
{
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 = 0; i < S.length - 1; i++) {
if (S.ch[i] != T.ch[i]) {
return S.ch[i] - T.ch[i]; //Ascll码作对照
}
//扫描过的所有字符都相同,则长度大的串更大。
return S.length - T.length;
}
定位操作
//定位操作 Index(S,T):若主串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的位置:否则为零
int Index(SString S, SString T) {
int i = 1, n = StringLength(S), m = StringLength(T); //取S的长与T的长
SString Sub; //新建一个串,用来存放S中的片段
while (i<=n-m+1)
{
SubString(Sub, S, i, m); //将S 中第 i 位及之后的 m 位的字符存入Sub中
if (StrCompare(Sub, T) != 0) { //如过 Sub 与 T 不相同 则i++
++i;
}
else //如果相同则返回 位置 i
{
return i;
}
}
return 0; //遍历结束都无相同片段则返回 0
}