数据结构(超详细讲解!!)第十八节 串(静态存储)

数据结构(超详细讲解!!)第十八节 串(静态存储)_第1张图片

数据结构(超详细讲解!!)第十八节 串(静态存储)_第2张图片

1.串的定义

串:由零个或多个字符组成的有限序列,一般记为:s=“a1a2...an” (n≥0)。

ai可以是字母、数字或其他字符。

 串中字符的个数n称为串的长度。

 空串:零个字符,即长度为零的串称为空串,用或””表示。

空格串:仅由空格组成的的串称为空格串,如:s=〃└┘〃。

若串中含有空格,在计算串长时,空格应计入串的长度中。

如:s=〃I’m a student〃的长度 为13。

空串≠空格串。

子串:串中任意个连续的字符组成的子序列。

主串:包含子串的串相应地称为主串。

位置:字符在序列中的序号。

子串在主串中的位置则以子串的第一个字符在主串中的位置来表示。

例:假设a、b、c、d为如下的四个串 a=“BEI” ,b=“JING”  ,c=“BEIJING”  ,d=“BEI JING” 子串b在串c中的位置为4,而在串d中的位置为5。

相等:两个串的长度相等,并且对应位置的字符都相同。 如,上述串c和串d就不相等。

串结构与线性表结构的比较:

逻辑结构:极为相似,区别仅在于串的数据对象约束为字符集。

基本操作:有很大差别,线性表大多以“单个元素”作为操作对象,串通常以“串的整体”作为操作对象。

2.串的抽象数据类型定义

抽象数据类型:
ADT String {
      数据对象:
         D={ ai |ai∈CharacterSet, i=1,2,...,n, n≥0 }
      数据关系:
         R1={ < ai-1, ai > | ai-1, ai ∈D,i=2,...,n }
      基本操作
} ADT String

StrAssign (&T, chars)      

初始条件:chars 是字符串常量。      

操作结果:把 chars 赋为 T 的值。

等价于C语言中的strset函数。

StrCopy (&T, S)      

初始条件:串 S 存在。    

操作结果:由串 S 复制得串 T。

等价于C语言中的strcpy函数。

DestroyString (&S)      

初始条件:串 S 存在。    

操作结果:串 S 被销毁。

StrEmpty (S)      

初始条件:串 S 已存在。    

操作结果:若 S 为空串,则返回TRUE,否则返回 FALSE。

“”表示空串,空串的长度为零。

StrCompare (S, T)      

初始条件:串 S 和 T 存在。    

操作结果:  若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0。      

等价于C语言中的strcmp函数(按ASCII码值进行大小比较)。

StrLength (S)      

初始条件:串 S 存在。    

操作结果:返回 S 的元素个数,称为串的长度。

等价于C语言中的strlen函数

Concat (&T, S1, S2)    

初始条件:串 S1 和 S2 存在。    

操作结果:用T返回由S1和S2联接而成的新串。

例如: Concate( T, “man”, “kind”)  求得  T = “mankind”    等价于C语言中的strcat函数

SubString (&Sub, S, pos, len)      

初始条件:串S存在,pos和len的取值 1≤pos≤StrLength(S) 且  0≤len≤StrLength(S)-pos+1。      

操作结果:用Sub返回串S的第pos个字符起长度 ,为len的子串。

Index (S, T, pos)

初始条件:串S和T存在,T是非空串,1≤pos≤StrLength(S)。

操作结果:若主串 S 中存在和串 T 值相同的子串, 则返回它在主串 S 中第pos个字符之后第一次出现的位置;否则函数值为0。

“子串在主串中的位置”指子串中的第一个字符在主串中的位序。

int Index (String S, String T, int pos)
 {
 // T为非空串。若主串S中第pos个字符之后存在与 T相等的子
 // 串,则返回第一个这样的子串在S中的位置,否则返回0
  if (pos > 0) {
    n = StrLength(S);  m = StrLength(T);  i = pos;
    while ( i <= n-m+1) {
        SubString (sub, S, i, m);
        if (StrCompare(sub,T) != 0)   ++i ;
        else return i ;
    } // while
  } // if
  return 0;     // S中不存在与T相等的子串
} // Index

Replace (&S, T, V)      

初始条件:串S, T和V均已存在,且T是非空串。    

操作结果:用 V 替换主串 S 中出现的所有与(模式串)T 相等的不重叠的子串。

StrInsert (&S, pos, T)    

初始条件:串S和T存在,pos取值1≤pos≤StrLength(S)+1                        

操作结果:在串S的第pos个字符之前插入串T。

StrDelete (&S, pos, len)

初始条件:串S存在 pos取值1≤pos≤StrLength(S)-len+1。

操作结果:从串S中删除第pos个字符起长度为len的子串。

ClearString (&S)

初始条件:串S存在。

操作结果:将S清为空串。

串赋值StrAssign、串复制Strcopy、串比较StrCompare、求串长StrLength、串联接Concat以及求子串SubString等六种操作构成串类型的最小操作子集。

3.串的标准库函数

#include

strcpy: 将字符串src复制到dest

Strcat:将字符串src添加到dest末尾

Strchr:检索并返回字符c在字符串s中第一次出现的位置

Strcmp:字符串s1与s2的大小,并返回s1-s2

strcpy :将字符串src复制到dest

Strcspn:扫描s1,返回在s1中有,在s2中也有的字符个数

Strdup:将字符串s复制到最近建立的单元

Strerror: 本函数返回最近一次的错误信息

Stricmp:比较字符串s1和s2,并返回s1-s2 strlen: 返回字符串s的长度

strlwr :字符串s中的大写字母全部转换成小写字母,并返回转换后的字符串

strncat:将字符串src中最多maxlen个字符复制到字符串dest中

strncmp:比较字符串s1与s2中的前maxlen个字符

strncpy:复制src中的前maxlen个字符到dest中

strnicmp:比较字符串s1与s2中的前maxlen个字符

Strnset: 将字符串s的前n个字符置于ch中

strpbrk :扫描字符串s1,并返回在s1和s2中均有的字符个数

Strrchr: 扫描最后出现一个给定字符c的一个字符串s

Strrev: 将字符串s中的字符全部颠倒顺序重新排列,并返回排列后的字符串

Strset: 将一个字符串s中的所有字符置于一个给定的字符ch

 strspn: 扫描字符串s1,并返回在s1和s2中均有的字符个数  

strstr: 扫描字符串s2,并返回第一次出现s1的位置  

strtod: 将字符串str转换成双精度数,并返回这个数

strtok: 检索字符串s1,该字符串s1是由字符串s2中定义的定界符所分隔  

strtol:将字符串str转换成长整型数,并返回这个数

 strupr: 将字符串s中的小写字母全部转换成大写字母,并返回转换后的字符串

4.抽象数据类型串的实现

在C语言中可以有两种方式:

串的静态存储结构:将串定义为字符型数组,数组名就是串名,串的存储空间分配在编译时完成,程序运行时不能更改。

串的动态存储结构:定义字符指针变量,存储串值的首地址,通过字符指针变量名访问串值,串的存储空间分配是在程序运行时动态分配的。

静态存储采用顺序存储结构; 动态存储采用的是堆存储结构和链式存储。

5.串的静态实现

0.存储结构

#define MAXLEN 20
 typedef struct {    /* 串结构定义 */
    char ch[MAXLEN]; 
    int len; 
} SStrin;

1.初始化

//初始化
SStrin * Init_SStrin( )
{	SStrin *s;	
	s = (SStrin *) malloc ( sizeof( SStrin ) );
 	s->len=0;
 	printf("初始化成功。\n");
	return s;	
}

2.录入

//录入
int Enter_SStrin(SStrin *s)
{char x;
printf("请输入元素:");
scanf(" %c",&x); 
while(x!='#')
{
	if (s->len==MAXLEN)		
	{	printf("串已满,录入失败。\n");
              return 0; 	
	}	
	s->ch[s->len] = x;	
	s->len=s->len+1;  
	scanf(" %c",&x);
}
printf("录入完成。\n");
	return 1;			/*入队成功,函数返回1*/
}

3.插入

//串插入函数
int StrInsert(SStrin *s,SStrin *t)       /*在串s中序号为pos的字符之前插入串t */
{int i,pos;
printf("请输入插入位置:");
scanf("%d",&pos); 

if ( pos<0||pos>s->len) //pos从0开始。 
	{printf("插入位置不合法。\n");
	return 0;     /* 插入位置不合法 */
	}
if (s->len + t->len<=MAXLEN)    /* 插入后串长≤MAXLEN */ 
{      
    for (i=s->len + t->len-1;i>=t->len + pos;i--) 
           s->ch[i]=s->ch[i-t->len] ;                                              
    for (i=0;ilen;i++)     
	s->ch[i+pos]=t->ch[i];                                        
    s->len=s->len+t->len;
    printf("插入完成。\n");
    } 
else if (pos+t->len<=MAXLEN) /* 插入后串长>MAXLEN, 但串t的字符序列可以全部插入 */ 
{
    for (i=MAXLEN-1;i >= t->len+pos;i--) 
		s->ch[i]=s->ch[i-t->len]; 
    for (i=0;ilen;i++) 
	s->ch[i+pos]=t->ch[i];
    s->len=MAXLEN; 
    printf("s中元素溢出,但t完整插入。\n");
    }
else {              /* 串t的部分字符序列要舍弃 */ 
    for (i=0;ich[i+pos]=t->ch[i];
    s->len=MAXLEN;
    printf("s和t都溢出,插入部分t。\n");
    }
return(1);
} 

4.遍历

 
 //遍历 
int Printf(SStrin *s)
{int i;
if(s->len==0)
{printf("串为空。\n");
return 0;
}
printf("查看表中元素:");
for(i=0;ilen;i++)
{printf("%c",s->ch[i]);
}
printf("\n");
return 1;
}

5.删除

//串删除函数。
int StrDelete(SStrin *s) /* 在串s中删除从序号pos起len个字符 */
{
int i,pos,len;
printf("请输入插入位置,和删除字符个数:");
scanf("%d %d",&pos,&len); 
if (pos<0 || pos>(s->len-len)) 
{printf("删除位置不合理。\n");
	return(0);}
for (i=pos+len;ilen;i++) 
     s->ch[i-len]=s->ch[i];
	s->len=s->len - len;
	printf("删除成功。\n");
return(1);
} 

6.复制

//串复制函数
void StrCopy(SStrin *s,SStrin *t) /* 将串t的值复制到串s中 */
{
int i;
for (i=0;ilen;i++)  
s->ch[i]=t->ch[i];
s->len=t->len;
printf("复制完成。\n");
} 

7.判空

//判空函数
int StrEmpty(SStrin *s) /* 若串s为空(即串长为0), 则返回1, 否则返回0 */
{
if (s->len==0) 
{printf("串为空。\n");
	return(1);}
else 
{printf("串不为空。\n");
	return(0);}
} 

8.比较

//串比较函数
int StrCompare(SStrin *s,SStrin *t) /* 若串s和t相等, 则返回0;若s>t,则返回>0;若slen&&ilen;i++) 
    if (s->ch[i]!=t->ch[i]) 
    {if(s->ch[i]- t->ch[i]==0)
	printf("串s和t相等。\n");
	if(s->ch[i]- t->ch[i]>0)
	printf("串s大于t。\n");
	if(s->ch[i]- t->ch[i]<0)
	printf("串s小于t。\n");
	  	return(s->ch[i]- t->ch[i]);}
	  	
if(s->len - t->len==0)
printf("串s和t相等。\n");
if(s->len - t->len>0)
printf("串s大于t。\n");
if(s->len - t->len<0)
printf("串s小于t。\n");	  	

return(s->len - t->len);

} 

9.串长

//求串长函数
int StrLength(SStrin *s)/* 返回串s的长度 */
{printf("串s长度为:%d",s->len);
printf("\n");
return(s->len);
} 

10.清空串

//清空函数
int StrClear(SStrin *s) /* 将串s置为空串 */
{
    s->len=0;
    printf("清空完成。\n");
    return(1);
} 

11.连接

//连接函数 
int StrCat(SStrin *s,SStrin *t) /* 将串t连接在串s的后面 */
{
int i, flag;
if (s->len + t->len<=MAXLEN) {        /* 连接后串长小于MAXLEN */ 
   for (i=s->len; ilen + t->len; i++)
    s->ch[i]=t->ch[i-s->len];
   s->len+=t->len;
   flag=1;
   printf("连接成功。\n");
   } 
else if (s->lenlen;ich[i]=t->ch[i-s->len];
 s->len=MAXLEN;
 flag=0;    
 printf("溢出,已连接部分t串。\n");
 }
 else 
 {flag=0;          /* 串s的长度等于MAXLEN, 串t不被连接 */
 printf("s串已满无法连接。\n");}
 return(flag);
} 

12.求子串

//求子串函数
SStrin *SubString(SStrin *s) /* 将串s中序号pos起len个字符复制到sub中 */
{
int i,pos,len;
	SStrin *sub;	
	sub = (SStrin *) malloc ( sizeof( SStrin ) );
 	sub->len=0;
printf("请输入子串起始位置,和子串长度:");
scanf("%d %d",&pos,&len); 
if (pos<0 || pos>s->len || len<1 || len>s->len-pos)
     { sub->len=0;
     printf("子串不合法。\n");
	 return(sub);}
else { 
   for (i=0;ich[i]=s->ch[i+pos]; 
   sub->len=len;
   printf("截取子串成功。\n");
   return(sub); 
   }
} 

13.定位

//定位函数 
int StrIndex(SStrin *s,SStrin *t) /* 求串t在串s中的位置 */
 {
int i, j=0,pos;
printf("请输入在第几个元素之后进行查找:");
scanf("%d",&pos);
i=pos;
if (t->len==0) 
{printf("t不存在。\n");
	return(0);}
while (ilen && jlen) 
    if (s->ch[i]==t->ch[j]) 
	{i++;
	j++;}
    else 
	{i=i-j+1;
	j=0;}
if (j>=t->len) 
{printf("串t首在s中的位置为:%d",i-j);
		return(i-j);}
else 
	{printf("未在s中找到t。\n"); 
	return(0);}
} 

6.串的静态存储总代码

#include
#include

#define MAXLEN 20
 typedef struct {    /* 串结构定义 */
    char ch[MAXLEN]; 
    int len; 
} SStrin;


//初始化
SStrin * Init_SStrin( )
{	SStrin *s;	
	s = (SStrin *) malloc ( sizeof( SStrin ) );
 	s->len=0;
 	printf("初始化成功。\n");
	return s;	
}

//录入
int Enter_SStrin(SStrin *s)
{char x;
printf("请输入元素:");
scanf(" %c",&x); 
while(x!='#')
{
	if (s->len==MAXLEN)		
	{	printf("串已满,录入失败。\n");
              return 0; 	
	}	
	s->ch[s->len] = x;	
	s->len=s->len+1;  
	scanf(" %c",&x);
}
printf("录入完成。\n");
	return 1;			/*入队成功,函数返回1*/
}
 
 //遍历 
int Printf(SStrin *s)
{int i;
if(s->len==0)
{printf("串为空。\n");
return 0;
}
printf("查看表中元素:");
for(i=0;ilen;i++)
{printf("%c",s->ch[i]);
}
printf("\n");
return 1;
}


//串插入函数
int StrInsert(SStrin *s,SStrin *t)       /*在串s中序号为pos的字符之前插入串t */
{int i,pos;
printf("请输入插入位置:");
scanf("%d",&pos); 

if ( pos<0||pos>s->len) //pos从0开始。 
	{printf("插入位置不合法。\n");
	return 0;     /* 插入位置不合法 */
	}
if (s->len + t->len<=MAXLEN)    /* 插入后串长≤MAXLEN */ 
{      
    for (i=s->len + t->len-1;i>=t->len + pos;i--) 
           s->ch[i]=s->ch[i-t->len] ;                                              
    for (i=0;ilen;i++)     
	s->ch[i+pos]=t->ch[i];                                        
    s->len=s->len+t->len;
    printf("插入完成。\n");
    } 
else if (pos+t->len<=MAXLEN) /* 插入后串长>MAXLEN, 但串t的字符序列可以全部插入 */ 
{
    for (i=MAXLEN-1;i >= t->len+pos;i--) 
		s->ch[i]=s->ch[i-t->len]; 
    for (i=0;ilen;i++) 
	s->ch[i+pos]=t->ch[i];
    s->len=MAXLEN; 
    printf("s中元素溢出,但t完整插入。\n");
    }
else {              /* 串t的部分字符序列要舍弃 */ 
    for (i=0;ich[i+pos]=t->ch[i];
    s->len=MAXLEN;
    printf("s和t都溢出,插入部分t。\n");
    }
return(1);
} 


//串删除函数。
int StrDelete(SStrin *s) /* 在串s中删除从序号pos起len个字符 */
{
int i,pos,len;
printf("请输入插入位置,和删除字符个数:");
scanf("%d %d",&pos,&len); 
if (pos<0 || pos>(s->len-len)) 
{printf("删除位置不合理。\n");
	return(0);}
for (i=pos+len;ilen;i++) 
     s->ch[i-len]=s->ch[i];
	s->len=s->len - len;
	printf("删除成功。\n");
return(1);
} 

//串复制函数
void StrCopy(SStrin *s,SStrin *t) /* 将串t的值复制到串s中 */
{
int i;
for (i=0;ilen;i++)  
s->ch[i]=t->ch[i];
s->len=t->len;
printf("复制完成。\n");
} 

//判空函数
int StrEmpty(SStrin *s) /* 若串s为空(即串长为0), 则返回1, 否则返回0 */
{
if (s->len==0) 
{printf("串为空。\n");
	return(1);}
else 
{printf("串不为空。\n");
	return(0);}
} 

//串比较函数
int StrCompare(SStrin *s,SStrin *t) /* 若串s和t相等, 则返回0;若s>t,则返回>0;若slen&&ilen;i++) 
    if (s->ch[i]!=t->ch[i]) 
    {if(s->ch[i]- t->ch[i]==0)
	printf("串s和t相等。\n");
	if(s->ch[i]- t->ch[i]>0)
	printf("串s大于t。\n");
	if(s->ch[i]- t->ch[i]<0)
	printf("串s小于t。\n");
	  	return(s->ch[i]- t->ch[i]);}
	  	
if(s->len - t->len==0)
printf("串s和t相等。\n");
if(s->len - t->len>0)
printf("串s大于t。\n");
if(s->len - t->len<0)
printf("串s小于t。\n");	  	

return(s->len - t->len);

} 

//求串长函数
int StrLength(SStrin *s)/* 返回串s的长度 */
{printf("串s长度为:%d",s->len);
printf("\n");
return(s->len);
} 

//清空函数
int StrClear(SStrin *s) /* 将串s置为空串 */
{
    s->len=0;
    printf("清空完成。\n");
    return(1);
} 

//连接函数 
int StrCat(SStrin *s,SStrin *t) /* 将串t连接在串s的后面 */
{
int i, flag;
if (s->len + t->len<=MAXLEN) {        /* 连接后串长小于MAXLEN */ 
   for (i=s->len; ilen + t->len; i++)
    s->ch[i]=t->ch[i-s->len];
   s->len+=t->len;
   flag=1;
   printf("连接成功。\n");
   } 
else if (s->lenlen;ich[i]=t->ch[i-s->len];
 s->len=MAXLEN;
 flag=0;    
 printf("溢出,已连接部分t串。\n");
 }
 else 
 {flag=0;          /* 串s的长度等于MAXLEN, 串t不被连接 */
 printf("s串已满无法连接。\n");}
 return(flag);
} 

//求子串函数
SStrin *SubString(SStrin *s) /* 将串s中序号pos起len个字符复制到sub中 */
{
int i,pos,len;
	SStrin *sub;	
	sub = (SStrin *) malloc ( sizeof( SStrin ) );
 	sub->len=0;
printf("请输入子串起始位置,和子串长度:");
scanf("%d %d",&pos,&len); 
if (pos<0 || pos>s->len || len<1 || len>s->len-pos)
     { sub->len=0;
     printf("子串不合法。\n");
	 return(sub);}
else { 
   for (i=0;ich[i]=s->ch[i+pos]; 
   sub->len=len;
   printf("截取子串成功。\n");
   return(sub); 
   }
} 

//定位函数 
int StrIndex(SStrin *s,SStrin *t) /* 求串t在串s中的位置 */
 {
int i, j=0,pos;
printf("请输入在第几个元素之后进行查找:");
scanf("%d",&pos);
i=pos;
if (t->len==0) 
{printf("t不存在。\n");
	return(0);}
while (ilen && jlen) 
    if (s->ch[i]==t->ch[j]) 
	{i++;
	j++;}
    else 
	{i=i-j+1;
	j=0;}
if (j>=t->len) 
{printf("串t首在s中的位置为:%d",i-j);
		return(i-j);}
else 
	{printf("未在s中找到t。\n"); 
	return(0);}
} 

 void menu()
{
printf("--------1.初始化s------\n"); 
printf("--------2.初始化t------\n"); 
printf("--------3.录入s--------\n"); 
printf("--------4.录入t--------\n"); 
printf("--------5.插入---------\n"); 
printf("--------6.删除---------\n"); 
printf("--------7.判空---------\n"); 
printf("--------8.复制---------\n"); 
printf("--------9.比较---------\n"); 
printf("--------10.求长度------\n"); 
printf("--------11.清空--------\n"); 
printf("--------12.连接--------\n"); 
printf("--------13.求子串sub---\n"); 
printf("--------14.定位-------\n");
printf("--------15.遍历s-------\n"); 
printf("--------16.遍历t-------\n"); 
printf("--------17.遍历sub-----\n"); 
printf("--------18.退出程序----\n");
}

int main()
{SStrin *s,*t,*sub;
int n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,a,quit=0;
menu();
while(1)
{
scanf("%d",&a);
switch(a)
{
case 1:s=Init_SStrin( );break;
case 2:t=Init_SStrin( );break;
case 3:n1=Enter_SStrin(s);break;
case 4:n2=Enter_SStrin(t);break;
case 5:n3=StrInsert(s,t) ;break;
case 6:n4=StrDelete(s) ;break;
case 7:n5=StrEmpty(s);break;
case 8:StrCopy(s,t);break;
case 9:n6=StrCompare(s,t) ;break;
case 10:n7=StrLength(s);break;
case 11:n8=StrClear(s) ;break;
case 12:n9=StrCat(s,t);break;
case 13:sub=SubString(s);break;
case 14:n10=StrIndex(s,t);break;
case 15:n11=Printf(s);break;
case 16:n11=Printf(t);break;
case 17:n11=Printf(sub);break;
case 18:quit=1;break;
default:printf("输入1~18之间的数字\n");break;
}
if(quit==1)
{break;
}
}
return 0;
 } 

你可能感兴趣的:(数据结构(超详细讲解!!),数据结构)