本节为串内容,回到总目录:点击此处
字符串
·子串、主串、子串在主串中的位置、串相等
抽象数据类型定义
ADT String
{
数据对象:
结构关系:
基本操作:
{
StrAssign(S,chars)
生成一个值等于chars的串S
StrInsert(S,pos,T)
在串S的第pos个字符之前插入串T,1<=pos<=len+1
StrDelete(S,pos,len)
从串S中删除第pos个字符起长度为len的子串
StrCopy(S,T)
由串T复制得到串S
StrEmpty(S
判断是否为空串
StrCompare(S,T)
判断S与T的大小
StrLength(S)
返回串的长度
StrClear(S)
将串清空为空串
StrCat(S,T)
将串T的值连接在串S的后面
SubString(Sub,S,pos,len)
用Sub返回串S的第pos个字符起长度为len的子串
StrIndex(S,pos,T)
若串S中存在和串T相同的子串,则返回它在串S中第pos个字符之后第一次出现的位置,否则返回0
StrReplace(S,T,V)
用V替换串S中出现的所有与T相等的不重叠的子串
StrDestroy(S)
销毁串S
}
}
串的存储实现
定长顺序串
#define Maxlen 40
typedef struct
{
char ch[Maxlen];
int len;
}SString;
定长顺序串的操作
·顺序串插入函数
分析:在进行顺序串的插入时,插入位置pos将原来的串分成了两个部分A,B长度为LA,LB;以及待插入的部分C,长度为LC。
需要分三种情况讨论
LA+LB+LC <= Maxlen;
LB需要删除一部分
LC需要删除一部分
StrInsert(SString *s, int pos, SString t)
{
//在串s中下标为pos的字符之前插入串t
int i;
if (pos < 0 || pos > s -> len) return 0;//检查插入位置是否合法
if (s -> len+t.len <= Maxlen) //情况1
{
for(i = s -> len + t.len - 1;i >= t.len+pos;i --)
{
s -> ch[i] = s -> ch[i - t.len];
}
for (i = 0; i < i.len; i ++)
{
s -> ch[i+pos] = t.ch[i];
s -> len = s -> len + t.len;
}
}
else if(pos+t.len <= Maxlen) //情况2,
{
for(i = Maxlen - 1;i > t.len + pos - 1;i --)
{
s -> ch[i] = s -> ch[i - t.len];
}
for (i = 0; i < t.len; i ++)
{
s -> ch[i + pos] = t.ch[i];
s -> len = Maxlen;
}
}
else //情况3
{
for (i = 0; i < Maxlen - pos;i ++)
{
s -> ch[i+pos] = t.ch[i];
s -> len = Maxlen;
}
}
return 1;
}
·顺序串删除函数
StrDelete(SString *s, int pos, int len)
{
int i;
if(pos < 0 || pos > (s -> len - len)) return 0;
for (i = pos + len; i < s -> len; i ++)
{
s -> ch[i - len] = s -> ch[i];
}//从pos+len开始至串尾依次向前移动,实现删除len个字符
s -> len = s -> len - len;
return 1;
}
·串比较函数
StrCompare(SString s,SString t)
{
//如果s、t相等则返回0;若s>t则返回正数,如果s<t则返回负数
int i;
for (i = 0; i < s.len && i < t.len; i ++)
{
if(s.ch[i] != t.ch[i]) return (s.ch[i] - t.ch[i]);
}
return (s.len - t.len);
}
·定位函数【重点】
1、串的简单模式匹配(布鲁特-福斯)算法
简单模式匹配算法是一种带回溯的匹配算法
从主串S的第pos个字符开始,和模式串T的第一个字符开始比较,如果相等则继续比较后续字符,如果不等,则从(回溯到)主串S的第pos+1个字符开始重新和模式串T比较,直到模式T中的每一个字符都和主串S中的一个连续字符序列全部相等
----插入图片
StrIndex(SString s, int pos, SString t)
{
//从主串S的第pos个字符开始,串t第一次出现的位置
int i,j,start;
if(t.len == 0 ) return 0;
start = pos; //主串从pos开始
i = start;
j = 0; //模式串从头0开始
while(i < s.len && j < t.len)
{
if(s.ch[i] == t.ch[i]) {i++;j++} //字符相等时推进
else //字符不等时回溯
{
start ++;
i = start; //主串从START+1开始
j = 0; //子串从0开始
}
}
if(j >= t.len) return start;
else return -1;
}
//另外的写法:使用C语言的库函数
int index(SString s,SString t, int pos)
{
if(pos > 0)
{
n = strlen(s);
m = strlen(m);
i = pos;
}
while(i < n - m + 1)
{
substr(sub , s, i, m);
if(strcmp(sub,t) != 0) ++i;
else return i;
}
return 0;
}
无回溯的定位匹配算法KMP算法!效率更高
堆串
-字符串包括串名和串值两个部分。串值采用堆串的存储方式存储,串名用符号表存储-
·堆串存储方法:存储空间时在程序执行过程中动态分配的
·串名符号表:所有串名的存储映像构成一个符号表。借助此结构可以在串名与串值之间建立一个对应关系,称为串名的存储映像。
·堆的存储表示:C语言中已有一个称为“堆”的自由存储空间,并可用malloc和free完成动态存储管理
typedef Data_Structure
{
char *ch;
int len;
}HString;
堆串与定长顺序串的区别在于:一个长度固定,一个是动态申请的。
·堆串的插入函数
StrInsert(HString *s, int pos, HString *t)
{
int i; char *temp;
if (Pos) //判断插入位置
temp = (char *) malloc(sizeof(s -> len + t -> len)); //动态产生足够空间
if(temp == NULL) return false;
for(i = 0 ;i < pos; i ++) temp[i] = s -> ch[i];
for(i = 0 ;i < t -> len ; i ++) temp[i+pos] = t -> ch[i];
for(i = pos; i < s -> len; i ++) temp[i + t -> len] = s -> ch[i];
s -> len += t -> len;
free(s -> ch);
s -> ch = temp;
return 1;
}
·堆串赋值函数
StrAssign(HString *s, char * tval)
{
int len, i = 0;
if(s -> ch != NULL) free(s -> ch);
while(tval [i] != '\0') i ++;
len = i;
if(len)
{
s -> ch = (char*) malloc(len);
if(s -> ch == NULL) return false;
for(i = 0; i < len; i++) s -> ch[i] = tval[i];
}
else
{
s -> ch = NULL;
}
s -> len = len;
return 1;
}
块链串
利用链表来存放字符串,一个结点既可以一个字符也可以多个字符。
定义:
#define BLOCK_SIZE 4
typedef struct Block
{
char ch[BLOCK_SIZE];
struct Block * next;
}Block;
typedef struct
{
Block *head;
Block *tail;
int len;
}BLString;