您的位置:首页 > 其它

串(四)

2016-06-24 22:58 369 查看

4_1串的定义

串,是由零个或多个字符组成的有限序列

当且仅当俩个串的长度相等并且各个对应位置上的字符都相同时,这俩个串才是相等的

空串是任何串的子串

4_2_1 串的顺序存储结构

在顺序串中,串中的字符被依次存放在一组连续的存储单元里

一般来会所,一个字节(8位)可以表示一个字符(即该字符的ASCII码).因此,一个内存单元可以存储多个字符。

(例如:一个32位的内存单元可以存储4个字符)

从上一点可以得出,串的顺序存储有俩种方法:一种是每个单元只存一个字符,称为非紧缩格式(存储密度小);另一种是每个单元存放多个字符,称为紧缩格式(存储密度大).

对于非紧缩格式的顺序串,定义如下:

typedef struct
{
char data[MaxSize];
int length;
}SqString;


顺序串上实现串基本运算的算法

将一个字符串常量赋给串s,即生成一个值等于cstr的串s:StrAssign(SqString &s,char cstr[])

void StrAssign(SqString &s,char cstr[])
{
int i;
for(i=0;cstr[i]!='\0';i++)
s.data[i] = cstr[i];
s.length = i;
}


将串t复制给串s:StrCopy(s,t)

void StrCoopy(SqString &s,SqString t)
{
int i;
//for(i=0;t.data[i]!='\0';i++)
for(i=0;i>t.length;i++)
s.data[i] = t.data[i];
s.length = t.length;
}


判断串相等:若俩个串s与t相等返回真(1);否则返回假(0):StrEqual(s,t)

bool StrEqual(s,t)
{
bool same = true;
int i;
if(s.length != t.length)
same  = false;
else
for(i=0;i<s.length;i++)
if(s.data[i]!=t.data[i])
{
same = false;
break;
}
return same;
}


求串长:返回串s中字符个数:StrLength(s)

int StrLength(s)
{
return s.length;
}


串连接:返回由俩个串s和t连接在一起形成的新串:Concat(s,t)

SqString Concat(SqString s,SqString t)
{
SqString str;
int i;
str.length = s.length + t.length;
for(i=0;i<s.length;i++)
str[i] = s.data[i];
for(i=0;i<t.length;i++)
str[s.length+i] = t.data[i];
return str;
}


求子串:返回串s中第i(1≤i≤StrLength(s)1\le i \le StrLength(s))个字符开始的,由连续j个字符组成的子串。参数不正确时返回一个空串:SubStr(s,i,j)

SqString SubStr(SqString s,int i,int j)
{
SqString str;
int k;
str.length = 0;
if(j<0 || i+j-1>s.length)
return str;
//i和j的值并不能被改变,只能使用临时变量k
for(k=i-1;k<i-1+j;k++)
str[k] = s.data[k];
str.length = j;
return str;
}


将串s2插入到串s1的第i(1≤i≤StrLength(s)1\le i \le StrLength(s))个字符中,即将s2的第一个字符作为s1的第i个字符,并返回产生的新串。参数不正确时返回一个空串:InsStr(s1,i,s2)

SqString InsStr(SqString s1,int i,SqString s2)
{
SqString str;
int j;
str.length = 0;
if(i<=0 || i>s1.length+1)
return str;
for(j=0;j<i-1;j++)
str[j] = s1.data[j];
for(j=0;j<s2.length;j++)
str[i-1+j] = s2.data[j];
for(j=i-1;j<s1.length;j++)
str[i-1+s2.length] = s1.data[j];
str.length = s1.length + s2.length;
return str;
}


从串s删去第i(1≤i≤StrLength(s)1\le i \le StrLength(s))个字符开始的长度为j的子串,并返回产生的新串。参数不正确时返回一个空串:DelStr(s,i,j)

SqString DelStr(SqString s,int i,int j)
{
SqString str;
int k;
str.length = 0;
if(略)
return str;
for(k=0;k<i-1;k++)
str[k] = s.data[k];
for(k=i-1+j;k<j.length;j++)
str[k-j] = s.data[k];
str.length = s.length - j;
return str;
}


在串s中,将第i(1≤i≤StrLength(s)1\le i \le StrLength(s))个字符开始的长度为j的子串用串t替换,并返回产生的新串。参数不正确时返回一个空串:RepStr(s,i,j,t)

SqString RepStr(SqString s,int i,intj,SqString t)
{
SqString str;
str.length = 0;
int k;
if(略)
return str;
for(k=0;k<i-1;j++)
str[j] = s.data[j];
for(k=0;k<t.length;j++)
str[i+k-1] = t.data[k];
for(k=i-1+j;j<s.length;j++)
str[i-1+t.length] = s.data[k];
str.length = s.length-j+t.length
return str;
}


输出串s的所有元素值:DispStr(s)

void DispStr(SqString s)
{
int i;
if(s.length>0)
{
for(i=0;i<s.length;i++)
printf("%c",s.data[i]);
printf("\n");
}
}


例题 4_1 设计顺序串上实现串比较运算StrCmp(s,t)的算法

int Strcmp(SqString s,SqString t)
{
略
}


例题 4_2 以顺序串作为串的存储结构,设计一个算法求串s中出现的第一个最长的连续相同字符构成的平台

思路

用index保存最长的平台在s中的开始位置,max保存其长度,先将它们初始化为0.扫描串s,计算局部重复子串的长度length,若max较大,则更新max,并用index记下其开始位置。

void LongestString(SqString s,int &index,int &max)
{
int i=0,length=1,max=0,start=0;
while(i<s.length-1)
{
if(s.data[i] == s.data[i+1])
i++;
length++;
else
if(max<length)
{
max = length;
index = start;
}
i++;
start = i;
length = 1;
}
}


4_2_2 串的链式存储结构-链串

链串的组织形式与一般的链表相似,主要的区别在于链串中的一个节点可以存储多个字符。

通常将链串中每个节点所存储的字符个数称为节点大小

链串节点大小的选择与顺序串的格式类似。节点越大,则存储密度越大。但存储密度越大,一些操作越是不便,且可能引起大量字符移动。

这里规定链串节点大小均为1

typedef struct snode
{
char data;
struct snode *next;
}LiSting;


链串上实现串基本运算的算法

将一个字符串常量cstr赋给串s,即生成一个其值等于cstr的串s。采用尾插法简历串s:StrAssign(s,cstr);

StrAssign(LiString * &s,char cstr[])
{
int i;
LiString *r,*p;
s = (LiString *)malloc(sizeof(LiString));
r = s;
for(i=0;cstr[i] != '\0';i++)
{
p = (LiString *)malloc(sizeof(LiString));
p->data = cstr[i];
r->next = p;
r = p;
}
r->next = NULL;
}


将串t赋值给串s。采用尾插法建立复制后的链串s:StrCopy(s,t);

void StrCopy(LiString * &s,LiString * t)
{
LiString *p = t->next,*r,*q;
s = (LiString *)malloc(sizeof(LiString));
r = s;
while(p!=null)
{
q = (LiString *)malloc(sizeof(LiString));
q->data = p->data;
r->next = q;
r = q;
p = p->next;
}
r->next = NULL;
}


判断串相等,若俩个串s与t相等则返回真,否则返回假:StrEqual(s,t)

bool StrEqual(LiString *s,LiString *t)
{
LiString *p = s,*q = t;
while(p!=NULL && q!=NULL && p->data = q->data)
{
p = p->next;
q = q->next;
}
if(p==NULL && q==NULL)
{
return true;
}
else
return false;
}


求串长:返回串s中字符个数;StrLength(s)

int StrLength(LiString *s)
{
int i=0;
LiString *r;
r = s->next;
while(r!=null)
{
i++;
r= r->next;
}
return i;
}


串连接:返回由俩个串s和t连接在一起形成的新串。采用尾插法建立链串str并返回其地址;Concat(s,t)

LiString Concat(LiString *s,LiString *t)
{
LiString *str,*r,*p,*q;
str = (LiString *)malloc(sizeof(LiString));
r = str;
p = s->next;
while(p!=null)
{
q = (LiString *)malloc(sizeof(LiString))
q->data = p->data;
r-next = q;
r = q;
p = p->next;
}
p = t->next;
while(p!=NULL)
{
q = (LiString *)malloc(sizeof(LiString))
q->data = p->data;
r-next = q;
r = q;
p = p->next;
}
r->next = NULL;
return str;
}


求子串:返回串s中从第i个字符开始的,由连续j个字符组成的子串,参数不正确时返回一个空串。以下采用尾插法简历链串str并返回其地址;SubStr(s,i,j)

//正确的做法应该是利用链表,取到i-1的节点,这其实是一个公式
LiString * SubStr(LiString * s,int i,int j)
{
int k = 0;
LiString *str,*p,*q,*r;
p = s->next;
str = (LiString *)malloc(sizeof(LiString));
r = str;
if(i<=0 || i>StrLength(s) || j<0 || i+j-1>StrLength(s))
{
return str;
}
for(k=0;k<i-1;k++)
p = p->next;
//经过上面,已经把p指向第i个节点
for(k=0;k<j;k++)
{
q = (LiString *)malloc(sizeof(LiString));
q->data = p->data;
r->next = q;
r = q;
p = p->next;
}
r->next = NULL;
return str;


将串s2插入到串s1的第i个字符位置,即将s2的第1个字符作为s1的第i个字符,s2的第2个字符作为s1的第i+1个字符,等等,并返回产生的新串,参数不正确时返回一个空串。以下采用尾插法:InsStr(s1,i,s2)

//先插进去s1的前i个,然后插s2,再插s1剩下的,so easy
LiString * InsStr(LiString *s,int i,LiString *t)
{
int k;
LiString *str,*p,*r,*q,*m;
str = (LiString *)malloc(sizeof(LiString));
r = str;
p = s->next;
m = t->next;
if(i<=0 || i>StrLength(s)+1)
{
return str;
}
for(k=0;k<i-1;k++)
{
q = (LiString *)malloc(sizeof(LiString));
q->data = p->data;
r->next = q;
r = q;
p = p->next;
}
while(m!=NULL)
{
q = (LiString *)malloc(sizeof(LiString));
q->data = m->data;
r->next = q;
r = q;
m = m->next;
}
while(p!=null)
{
q = (LiString *)malloc(sizeof(LiString));
q->data = p->data;
r->next = q;
r = q;
p = p->next;
}
r->next = NULL;
return str;
}


从串s中删去从第i个字符开始的长度为j的子串,并返回产生的新串,参数不正确时返回一个空串。以下采用尾插法建立链串str并返回其地址;

LiStrng * DelStr(LiString *s,int i,int j)
{
int k;
LiString * str,*r,*p,*q;
str = (LiString *)malloc(sizeof(LiString));
r = str;
p = s->next;
if(略)
return str;
for(k=0;k<i-1;k++)
{
q = (LiString *)malloc(sizeof(LiString));
q->data = p->data;
r->next = q;
r = q;
p = p->next;
}
for(k=0;k<j;k++)
p = p->next;
while(p!=null)
{
q = (LiString *)malloc(sizeof(LiString));
q->data = p->data;
r->next = q;
r = q;
p = p->next;
}
r->next = NULL;
return str;

}


在串s中,将第i个字符开始的j个字符构成的子串用串t替换,并返回产生的新串,参数不正确时返回一个空串。以下采用尾插法建立链串str并返回其地址;RepStr(s,i,j,t)

LiString * RepStr(LiString *s,int i,int j,LiString *t)
{
int k;
LiString *str,*p,*q,*r,*p1;
str = (LiString *)malloc(sizeof(LiString));
r = str;
p = s->next;
p1 = t->next;
if(略)
return str;
for(k=0;k<i-1;k++)
{
q = (LiString *)malloc(sizeof(LiString));
q->data = p->data;
r->next = q;
r = q;
p = p->next;
}
for(k=0;k<j;k++)
p = p->next;
while(p1!=null)
{
q = (LiString *)malloc(sizeof(LiString));
q->data = p1->data;
r->next = q;
r = q;
p1 = p1->next;
}
while(p!=null)
{
q = (LiString *)malloc(sizeof(LiString));
q->data = p->data;
r->next = q;
r = q;
p = p->next;
}
r->next = NULL;
return str;
}


输出串s的所有元素值;DispStr(s)

void DispStr(LiString * s)
{
LiString *p = s->next;
while(p!=NULL)
{
printf("%c",p->data);
p = p->next;
}
printf("\n");
}


例题 4_3 以链串为存储结构,设计一个算法把最先出现的子串ab改为xyz。

void Repl(LiString * &s)
{
LiString *p,*q;
p = s->next;
int find = 0;
while(p->next!=NULL && find==0)
{
if(p->data=='a' && p->next-data == 'b')
{

p->data = 'x';
p->next-data == 'z'
q = (LiString *)malloc(sizeof(LiString));
q->data = 'y';
q->next = p->next;
p->next = q;
find = 1;
}
else
p = p->next;

}

}


-
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: