学习视频:天勤考研
语言:c++
string容器总结:c++中string容器的常用方法总结,加深学习巩固
1.串的基础
串分为顺序存储结构和链式存储结构
。
但是考研链式存储结构,不会出现,所有我只考虑顺序存储结构。
顺序存储结构分为:定长存储结构和变长存储结构
。
定长存储结构(存储的长度是不变的):
typedef struct
{
char str[maxSize+1];
int length;
}Str;
maxSize为已经定义的常量,表示串的最大长度;str数组的长度定义为maxSize+1,是因为char类会多出一个'\0'
作为结束标记。
关于可以用length来返回串的长度,为什么还要定义maxSize来占内存空间呢?
答:当需要立马读出串的长度,或结束标记时使用,定义maxSize 可以大大方便的代码实现。
变长存储结构(可以自行设置串的长度):
typedef struct
{
char *ch;
int length;
}Str;
变长存储结构申请内存:
Str s;
s.length=10; //设置串的长度
s.ch=new char[s.length+1]; //用new来申请内存,也可以使用malloc()来申请
s.ch[0]='1'; //赋值
cout<<s.ch[0]<<endl; //打印
free(s.ch); //释放内存
关于new和malloc申请函数的区别:
//malloc函数
Str s;
s.length=10;
s.ch=(char *)malloc((s.length+1)*sizeof(char)); 自己计算所需要开辟的内存大小
//new函数
Str s;
s.length=10;
s.ch=new char[s.length+1]; //此处只需要确定int数组的大小,而所需要的内存空间有系统自动计算
2.串的基本结构(这里以变长存储结构为例)
1.赋值操作
功能类似于string容器的assign操作。
string str4;str4.assign("hello c++");
#include <bits/stdc++.h>
using namespace std;
typedef struct
{
char *ch;
int length;
}Str;
int strAssign(Str& str,char ch[])
{
//当str.ch已经指向一个存储空间(已经存储数据)的时候,我们可以用这个操作将存储空间释放掉。
if(str.ch)
delete str.ch;
int len=0;
char *c=ch;
//判断ch中元素的长度
while(*c)
{
++len;
++c;
}
//传入的ch为空时
if(len==0) {
str.ch=NULL;
str.length=0;
return 1;
}
else{
str.ch=new char[len+1];
//当内存分配失败时
if(str.ch==NULL)
return 0;
else{
c=ch;
for(int i=0;i<=len;++i,++c){
str.ch[i]=*c;
}
str.length=len;
return 1;
}
}
}
int main(){
Str s;
s.length=10;
s.ch=new char[s.length+1];
char ch[20]={0};
string name="abcd";
strcpy(ch,name.c_str());
strAssign(s,ch);
cout<<s.length<<endl;
cout<<s.ch<<endl;
}
2.取串长度
int strLength(Str str)
{
return str.length;
}
3.串比较
这个功能和string容器的compare方法类似。
比较规则:
设两串C1和C2中待比较字符分别为a和b:
1.如果a的ASCII码小于
b的ASCII码,则返回C1小于
C2标记(一个负数);
2.如果a的ASCII码大于
b的ASCII码,则返回C1大于
C2标记(一个正数);
3.如果a的ASCII码等于
b的ASCII码,则按照之前的规则继续比较
两串中下一对
字符;
4.经过上述步骤没有比较出
C1和C2大小的情况下,先结束
的串为较小
串,两串同时结束
则返回两串相等
标记(0)。
比较代码:
int strCompare(Str s1,Str s2)
{
for(int i=0;i<s1.length&&i<s2.length;++i)
if(s1.ch[i]!=s2.ch[i])
return s1.ch[i]-s2.ch[i];
return s1.length-s2.length;
}
总共代码:
#include <bits/stdc++.h>
using namespace std;
typedef struct
{
char *ch;
int length;
}Str;
int strAssign(Str& str,char ch[])
{
if(str.ch)
delete str.ch;
int len=0;
char *c=ch;
while(*c)
{
++len;
++c;
}
if(len==0) {
str.ch=NULL;
str.length=0;
return 1;
}
else{
str.ch=new char[len+1];
if(str.ch==NULL)
return 0;
else{
c=ch;
for(int i=0;i<=len;++i,++c){
str.ch[i]=*c;
}
str.length=len;
return 1;
}
}
}
int strCompare(Str s1,Str s2)
{
for(int i=0;i<s1.length&&i<s2.length;++i)
if(s1.ch[i]!=s2.ch[i])
return s1.ch[i]-s2.ch[i];
return s1.length-s2.length;
}
int main(){
Str s1,s2;
char ch[20]={0};
string name="abcd";
strcpy(ch,name.c_str());
strAssign(s1,ch);
string name2="abcdf";
strcpy(ch,name2.c_str());
strAssign(s2,ch);
if(strCompare(s1,s2)>0){
cout<<"s1>s2"<<endl;
}else if(strCompare(s1,s2)<0){
cout<<"s1<s2"<<endl;
}else
cout<<"s1==s2"<<endl;
}
结果:
4.串连接
功能与string串的append方法类似。
#include <bits/stdc++.h>
using namespace std;
typedef struct
{
char *ch;
int length;
}Str;
int strAssign(Str& str,char ch[])
{
if(str.ch)
delete str.ch;
int len=0;
char *c=ch;
while(*c)
{
++len;
++c;
}
if(len==0) {
str.ch=NULL;
str.length=0;
return 1;
}
else{
str.ch=new char[len+1];
if(str.ch==NULL)
return 0;
else{
c=ch;
for(int i=0;i<=len;++i,++c){
str.ch[i]=*c;
}
str.length=len;
return 1;
}
}
}
//拼接操作
int append(Str& str,Str str1,Str str2){
if(str.ch){
free(str.ch);
str.ch=NULL;
}
str.ch=new char[str1.length+str2.length+1];
if(!str.ch)
return 0;
int i=0;
while(i<str1.length)
{
str.ch[i]=str1.ch[i];
++i;
}
int j=0;
while(j<=str2.length)
{
str.ch[i+j]=str2.ch[j];
++j;
}
str.length=str1.length+str2.length;
return 1;
}
int main(){
Str s,s1,s2;
char ch[20]={0};
string name="abcd";
strcpy(ch,name.c_str());
strAssign(s1,ch);
string name2="abcdf";
strcpy(ch,name2.c_str());
strAssign(s2,ch);
append(s,s1,s2);
cout<<s.ch<<endl;
}
结果:
5.子串的获取
功能与string容器的substr方法功能类似
#include <bits/stdc++.h>
using namespace std;
typedef struct
{
char *ch;
int length;
}Str;
int strAssign(Str& str,char ch[])
{
if(str.ch)
delete str.ch;
int len=0;
char *c=ch;
while(*c)
{
++len;
++c;
}
if(len==0) {
str.ch=NULL;
str.length=0;
return 1;
}
else{
str.ch=new char[len+1];
if(str.ch==NULL)
return 0;
else{
c=ch;
for(int i=0;i<=len;++i,++c){
str.ch[i]=*c;
}
str.length=len;
return 1;
}
}
}
//pos指子串开始位置,len表示子串长度
int subString(Str& substr,Str str,int pos,int len)
{
if(pos<0||pos>str.length||len<0||len>str.length-pos)
return 0;
if(substr.ch)
{
delete substr.ch;
substr.ch=NULL;
}
if(len==0){
substr.ch=NULL;
substr.length=0;
return 1;
}
else{
substr.ch=new char[len+1];
int i=pos;
int j=0;
while(i<pos+len)
{
substr.ch[j]=str.ch[i];
++i;
++j;
}
substr.ch[j]='\0';
substr.length=len;
return 1;
}
}
int main(){
Str s,s1,s2;
char ch[20]={0};
string name2="abcdf";
strcpy(ch,name2.c_str());
strAssign(s2,ch);
subString(s,s2,1,3);
cout<<s.ch<<endl;
}
结果:
6.清空串
与string的clear方法类似
int clearString(Str& str)
{
if(str.ch)
{
delete str.ch;
str.ch=NULL;
}
str.length=0;
return 1;
3.KMP算法
#include<bits/stdc++.h>
using namespace std;
/**
* KMP算法主要用来快速查找主串中是否有与模式串中相同的串。
* 使用KMP算法的优点:可以避免回调,缩短运行时间
* 模式串的第一个元素的下标为1,这样主要是方便于操作
* next[],next数组的意思就是 next[i] = len; 长度为i的数组的前缀和后缀相等的最大长度。
* nextval是改进的next,避免了aaaab这种情况,b前面都是相同的元素,使用nextval可以简化这种情况
* **/
typedef struct
{
char *ch;
int length;
}Str;
int strAssign(Str& str,char ch[])
{
if(str.ch)
delete str.ch;
int len=0;
char *c=ch;
while(*c)
{
++len;
++c;
}
if(len==0) {
str.ch=NULL;
str.length=0;
return 1;
}
else{
str.ch=new char[len+1];
if(str.ch==NULL)
return 0;
else{
c=ch;
for(int i=1;i<=len+1;++i,++c){
str.ch[i]=*c;
}
str.length=len;
return 1;
}
}
}
//next[],next数组的意思就是 next[i] = len; 长度为i的数组的前缀和后缀相等的最大长度。
void getNext(Str substr,int next[])
{
int j=1,t=0;
next[1]=0;
while(j<substr.length)
{
if(t==0||substr.ch[j]==substr.ch[t])
{
next[j+1]=t+1;
t++;
j++;
}else{
t=next[t];
}
}
}
//nextval是改进的next,避免了aaaab这种情况,b前面都是相同的元素,使用nextval可以简化这种情况
void getNextVal(Str substr,int nextval[],int next[])
{
int j=1,t=0;
next[1]=0;
nextval[1]=0;
while(j<substr.length)
{
if(t==0||substr.ch[j]==substr.ch[t])
{
next[j+1]=t+1;
if(substr.ch[j+1]!=substr.ch[next[j+1]])
nextval[j+1]=next[j+1];
else
nextval[j+1]=nextval[next[j+1]];
t++;
j++;
}else{
t=nextval[t];
}
}
}
//KMP算法,这里返回值为匹配串第一个元素地址
int KMP(Str str,Str substr,int next[])
{
int i=1,j=1;
while(i<=str.length&&j<=substr.length)
{
if(j==0||str.ch[i]==substr.ch[j])
{
++i;
++j;
}
else
{
j=next[j];
}
}
if(j>substr.length)
return i-substr.length;
else
return 0;
}
int main(){
Str s1,s2;
char ch[20]={0};
int next[100];
int nextval[100];
string name="abbaababa";
strcpy(ch,name.c_str());
strAssign(s1,ch);
string name2="aab";
strcpy(ch,name2.c_str());
strAssign(s2,ch);
getNext(s2,next);
cout<<KMP(s1,s2,next)<<endl;
getNextVal(s2,nextval,next);
cout<<KMP(s1,s2,nextval)<<endl;;
}