串是一种数据元素受限的线性表,它的每个数据元素限定为仅由一个字符组成。因此,串是n个字符的有限序列。串的一些相关概念如下:
1.将串中所含字符的个数n称为串的长度。2.将不包含任何字符的串称为空串。3.将由一个或多个空格组成的串称为空格串,这点空串和空格串是有区别的。4.将串中任意哥连续字符组成的子序列称为该串的子串,将包含这个子串的串叫做主串。5.字符在串中的位置是指字符在字符序列中的位序,子串在主串中的位置是子串在主串中第一次出现时,其首字母在主串中的位置。6.当且仅当两个串的串值相等时,才称这两个串相等。如果两个串的串值相等,那么意味着这两个串的长度相等,且他们对应位置上的元素(
即字符)相等。
串的基本操作:
typedef struct //串结构定义
{
char ch[20];//编译时产生的静态数组,其空间长度不可变
int len;//字符串长度,字符串最后一个字符下标为len-1
}sstring;
int 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<=20)//插入后串长小于最大长度
{
for(i=s->len-1;i>=pos;i--) //先将原本pos之后的字符串后移,空出t.len长度的位置
{
s->ch[i+t.len]=s->ch[i];
}
for(i=0;i<t.len;i++) //将t字符串插入
{
s->ch[pos+i]=t.ch[i];
s->len=s->len+t.len;//现在的字符串长度等于原来的字符串加上t.len
}
}
else if(pos+t.len<=20)
{
//插入后总串长大于最大长度,但t可以全部插入,串s有部分溢出
for(i=20-t.len-1;i>=pos;i--)
{
s->ch[i+t.len]=s->ch[i];
}
for(i=0;i<t.len;i++)
{
s->ch[pos+i]=t.ch[i];//插入t
s->len=20;//字符串的长度为最大长度
}
}
return 1;//插入成功
}
//字符串删除函数
int strdelete(sstring *s,int pos,int len) // 在串s中删除从下标pos起len个字符
{
int i;
if(pos<0||len<1||pos>(s->len-len)) return 0;
for(i=pos+len;i<s->len;i--)
{
s->ch[i-len]=s->ch[i];
}
s->len=s->len-len;
return 1;
}
//串复制函数,将串t中的字符复制到s中
void strcopy(sstring *s,sstring t)
{
for(int i=0;i<t.len;i++)
{
s->ch[i]=t.ch[i];
s->len=t.len;
}
}
//判空函数
int strempty(sstring s)
{
if(s.len==0) return 1;
else return 0;
}
//串比较函数
int strcompare(sstring s,sstring t)
{
for(int 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);
}
//串连接函数,将串t连接在串s的后面
int strconnect(sstring *s,sstring t)
{
int flag;
if(s->len+t.len<=20)
{
for(int i=0;i<t.len;i++)
{
s->ch[i+s->len]=t.ch[i];
}
s->len=s->len+t.len;
flag=1;
}
else if(s->len<20)
{
for(int i=0;i<20-s->len;i++)
{
s->ch[i+s->len]=t.ch[i];
}
s->len=20;
flag=0;
}
else flag=0;
return flag;
}
//求子串函数
int strstring(sstring *sub,sstring s,int pos,int len)
{
//将串s 中下标pos起len个字符复制到sub中
if(pos<0||pos<s.len-1||len<1||len>s.len-pos)
{
sub->len=0;
return 0;
}
else
{
for(int i=0;i<len;i++)
{
sub->ch[i]=s.ch[i+pos];
sub->len=len;
return 1;
}
}
}
串的顺序存储表示:串的顺序存储结构类似于线性表的顺序存储表示方法,即用一组地址连续的存储单元依次存放串值的字符序列。采用顺序存储方式的串叫顺序串。
串的堆分配存储结构表示:串的堆分配存储结构仍然以一组地址连续的存储单元来存放串值字符序列。但它具有两个不同于顺序串的特点:串变量的存储空间是在程序执行过程中动态分配的,程序中出现的所有串变量的可用存储空间就是一个称为堆的共享空间。
//采用堆存储结构的串的类型定义
#define max 200
char store[max];//定义堆空间
int free;//指向堆中自由空间的起始位置
typedef struct
{
int length;//串的长度
int addrstart;//串在堆中的存储首地址
}hstring;
串的块链存储表示:由于串中每个数据元素是一个字符,因此在具体实现时,允许每个节点内存放一个或多个字符,每个节点可容纳的字符个数称为块大小,由此得到的链式存储结构称为串的块链结构。如果串长不是块大小的整数倍,那么最后一个节点需要用一个特殊的字符填满,我们选用的特殊字符为“#”。同时为了便于实现串的连接操作,设置了尾指针,使它始终指向尾元节点。但要注意的是,在进行两个串的连接操作的时候,需要处理尾的特殊字符“#”。
#define size 4//块大小
typedef struct chnode //块链中的节点结构
{
char ch[size];
struct chnode *next;
}chnode;
typedef struct //块链结构
{
chnode *head,*tail;
int length; //为了一些操作的方便实现,增加一个记录串长的成员length
}linkstring;
串的模式匹配算法:
int patternmatching(sstring s,sstring t)
{
int i=0,j=0;
while(i<=s.len-t.len)
{
while(j<t.len&&s.ch[i]==t.ch[j])
{
i++;j++;
}
if(j<t.len)
{
i=i-j+1;j=0;
}
else
{
return i-j;
}
}
return -1;
}