数据结构 5.串

1.串的定义和基本操作

        字符串(String)是由零个或多个字符组成的有限序列。

        S=“a1a2a3.....an”(n≥0)

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

        主串:包含字串的串。

        字符在主串中的位置:字符在串中的序号。

        字串在主串中的位置:字串的第一个字符在主串中的位置。

        空串:M=“”      空格串:“        ”

        串是一种特殊的线性表,数据元素之间呈线性关系。

串的基本操作:如增删改查等通常以字串为操作对象

假设有串T="",S="iPhone 11 Pro Max?”,W="Pro”
        StrAssign(&T,chars):赋值操作。把串T赋值为chars。
        StrCopy(&T,S);复制操作。由串S复制得到串T。
        StrEmpty(S):判空操作。若S为空串,则返回TRUE,否则返回FALSE。
        StrLength(S):求串长。返回串S的元素个数。
        ClearString(&S):清空操作。将S清为空串。
        DestroyString(&S):销毁串。将串S销毁(回收存储空间)。
        Concat(&T,S1,S2):串联接。用T返回由S1和S2联接而成的新串
        SubString(&Sub,S,pos,len):求子串。用Sub返回串S的第pos个字符起长度为len的子串。
        Index(S,T):定位操作。若主串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的
位置;否则函数值为0。
        StrCompare(S,T):比较操作。若S>T, 则返回值>0;若S=T, 则返回值=0;若S<T, 则返回值<0。
Eg:执行基本操作Concat(&T, S, W)后,T="iPhone 11 Pro Max?Pro"
        执行基本操作SubString(&T ,S, 4, 6)后,T="one 11”
        执行基本操作Index(S, W)后,返回值为11

2.串的存储结构

串的顺序存储:

//串的顺序存储
#define MAXLEN 255
typedef struct{
	char ch[MAXLEN]; //每个分量存储一个字符
	int length; 
}SString; 


typedef struct{
	char *ch; //按串长分配存储区,ch指向串的基地址 
	int length; 
}SString; 
SString S;
S.ch=(char*)malloc(MAXLEN * sizeof(char));
S.length=0;

 串的链式存储:

//串的链式存储
#define MAXLEN 255
typedef struct StringNode{
	char ch; //每个结点存储一个字符
	struct StringNode *next; 
}StringNode,*String; 
//存储密度低,每个字符1B,每个指针4B 


typedef struct StringNode{
	char ch[4]; //每个结点存储多个字符
	struct StringNode *next; 
}StringNode,*String;
//存储密度高 

串的顺序存储案例:

//串的顺序存储
#include<stdio.h>
#include<stdlib.h>
#define MAXLEN 100
typedef struct{
	char ch[MAXLEN]; //每个分量存储一个字符,0号不存储 
	int length; //串的长度 
}SString; 
//初始化 
bool StringAssign(SString &S,char ch[]){
	int i=0;
	while(ch[i]!='\0'){
		S.ch[i+1]=ch[i];
		++i;
	}
	S.length=i;
	return 0;
}
//求串的长度
int StrLength(SString S){
	return S.length;
} 
//求字串  (sub返回串S的第pos个字符起长度为len)
bool SubString(SString &Sub,SString S,int pos,int len){
	if(pos+len-1>S.length)
		return false;
	for(int i=pos;i<pos+len;i++){
		Sub.ch[i-pos+1] = S.ch[i];  //0下标不存数据 
	}
	Sub.length=len;
	return true;
}
//比较操作
int StrCompare(SString S,SString T){
	for(int i=1;i<=S.length && i<=T.length;i++){
		if(S.ch[i]!=T.ch[i]){
			return S.ch[i]-T.ch[i]; 
		}
	}
	return S.length-T.length; 
} 
//定位操作
//若主串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的位置 
int Index(SString S,SString T){
	int i=1;
	int n=StrLength(S);
	int m=StrLength(T);
	SString sub; //暂存字串 
	while(i<=n-m+1){
		SubString(sub,S,i,m);
		if(StrCompare(sub,T)!=0){
			++i;
		}else{
			return i;
		}
	}
	return 0;
}
//打印 
int ShowString(SString &S){
	if(S.length==0){
		printf("当前串为空");
		return 0; 
	}
	for(int i=1;i<=S.length;i++){
		printf("%c",S.ch[i]);
	}
	printf("\n");
	return 0;
}

int main(){
	SString S; //主串 
	char ch[]={"hello world!"};
	StringAssign(S,ch);
	printf("主串S-ch:"); 
	ShowString(S);
	SString T; //子串 
	char cl[]={"world"};
	StringAssign(T,cl);
	printf("字串S-cl:");
	ShowString(T);
	
	//求字串  (sub返回串S的第pos个字符起长度为len)
	SString Sub;
	SubString(Sub,S,3,7);
	printf("S的字串:");
	ShowString(Sub);

	//比较操作
	int com= StrCompare(S,T);
	printf("Compare :%d\n",com);
	
	//若主串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的位置 
	int de= Index(S,T);
	printf("字串在主串中的位置:%d",de); 
}

结果:

主串S-ch:hello world!
字串S-cl:world
S的字串:llo wor
Compare :-15
字串在主串中的位置:7

3.字符串的模式匹配

 

4.KMP算法

 5.求next数组

6.KMP算法的优化

KMP综合案例:

#include<stdio.h>
#include<stdlib.h>
#define MAXLEN 100
typedef struct{
	char ch[MAXLEN]; //每个分量存储一个字符,0号不存储 
	int length; //串的长度 
}SString; 
bool StringAssign(SString &S,char ch[]){
	int i=0;
	while(ch[i]!='\0'){
		S.ch[i+1]=ch[i];
		i++;
	}
	S.length=i;
	printf("len=%d\n",i); 
	return 0;
}

int ShowString(SString &S){
	if(S.length==0){
		printf("当前串为空");
		return 0; 
	}
	for(int i=1;i<=S.length;i++){
		printf("%c",S.ch[i]);
	}
	printf("\n");
	return 0;
}

//模式串T的next数组
void get_next(SString T,int next[]){
	int i=1,j=0;
	next[1]=0;
	while(i<T.length){
		if(j==0 || T.ch[i] == T.ch[j]){
			++i;
			++j;
			next[i]=j;//若pi=pj,则next[j+1]=next[j]+1 
		}else{
			j=next[j];//否则j=next[j],循环继续 
		}
	}	
}

//KMP算法
int Index_KMP(SString S,SString T){
	int i=1,j=1;
	int next[T.length+1];
	get_next(T,next);
	printf("next:");
	for(int k=1;k<=T.length;k++){
		printf("%d ",next[k]);
	}
	printf("\n");

	int nextval[T.length+1];
	nextval[1]=0; 
	for(int j=2;j<=T.length;j++){
		if(T.ch[next[j]] == T.ch[j]){
			nextval[j]=nextval[next[j]];
		}else{
			nextval[j]=next[j];
		}
	}
	printf("nextval:");
	for(int k=1;k<=T.length;k++){
		printf("%d ",nextval[k]);
	}
	printf("\n");
	
	while(i<=S.length && j<=T.length){
		if(j==0 || S.ch[i]==T.ch[j]){
			++i;
			++j;
		}else{
			j=next[j];
		}
	}
	if(j>T.length){
		return i-T.length;
	}else{
		return 0;
	}
	
}

int main(){
	SString S; //主串 
	char ch[]={"aaaaaaabaa"};
	StringAssign(S,ch);
	printf("主串:"); 
	ShowString(S);
	SString T; //子串 
	char cl[]={"aaaab"};
	StringAssign(T,cl);
	printf("字串:");
	ShowString(T);
	int i=Index_KMP(S,T);
	printf("index is:%d",i);	
}

结果:

len=10
主串:aaaaaaabaa
len=5
字串:aaaab
next:0 1 2 3 4
nextval:0 0 0 0 4
index is:4

  • 40
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值