数据结构学习笔记——串的基本知识以及顺序存储结构实现串

简介: 数据结构学习笔记——串的基本知识以及顺序存储结构实现串

一、串的基本知识


串由零个或多个字符组成的有限序列,其数据元素就是字符,它是一种特殊的线性表,串的数据元素必须是单个字符。由任意多个连续的字符组成的子序列称为串的子串,包含子串的串称为主串,线性表是以单个元素进行相关操作,而串是以子串进行相关操作的,在c语言中,通过以字符'\0'来表示串值的结束。


(一)空串和空格串


1、空串

串的长度等于0时的串称为空串,空串是任意串的子串,任意串是自身的子串。

2、空格串

由一个或多个空格的特殊字符组成的串称为空格串,其长度并不为0,而是串中空格字符的个数。


(二)最大子串个数


首先要知道空串是任意串的子串,任意串是自身的子串,例如有一个字符串S=“ABCDEFGH”,其串的最大子串个数应该是8+7+6+5+4+3+2+1=36,另外再加上空串,即36+1=37,所以一个串的最大子串个数为n(n+1)/2+1,即8×9/2+1=37。

若串中含有重复数据元素,即最大子串个数=总子串个数-重复子串个数。


二、串的定义


字符串按存储可以分为:顺序存储、链接存储和堆分配存储(索引存储),另外存储方式也分为紧凑存储和非紧凑存储,紧凑存储的优点是空间利用率高但对串中字符处理的效率低,而非紧凑存储的优点是运算处理简单但空间利用率低。


(一)定长顺序存储


通过静态数组实现定长顺序存储,一组地址连续的存储单元存储串值的字符序列,其中每个串都被分配一个固定长度的ch[MAXLEN]数组。


#include<stdio.h>
#define MAXLEN 255
typedef struct{
  char ch[MAXLEN];  //为每个串分配一个固定长度的数组 
  int length;  //串的实际长度 
}SString;


例如,顺序存储,例如串S=”sjjg”,其中从S.ch[0]开始存放串,最后以字符’\0’来表示串值的结束,如下图:

1667279783404.jpg


(二)动态存储


1、链式存储

对不确定长度的串进行存储时,就要用到动态存储方式,这里可以采用链式存储,链式存储串中,每个结点有两个域,分为数据域(data)和指针域(next),数据域由于存放串的各字符,指针域用于存放后继结点的地址。


使用链式存储的优点是插入、删除运算方便,但缺点是存储、检索效率低,其空间利用率低。

2、堆分配存储

与定长顺序存储一样,也是采用一组地址连续的存储单元来存放串值的字符序列,但堆分配存储的存储空间是动态分配的,通过malloc()和free()函数来完成动态存储的分配和释放。


分配成功时,返回一个指向起始地址的指针*ch作为串的基地址,它指向动态分配存储区首地址的字符指针,若分配失败则返回NULL。

//堆分配存储的定义 
#include<stdio.h>
#include<stdlib.h>
typedef struct{
  char *ch; //指向串的基地址 ,即指向动态分配存储区首地址的字符指针 
  int length;  //串的实际长度 
}HString;
HString S;
S.ch=(char *)malloc(MAXLEN*sizeof(char)); //malloc动态分配 
S.length=0;  //初始化length串长度


注:以下操作均由定长顺序存储方式实现。


三、串的初始化


/*初始化串S*/
void InitString(SString &S) {
  S.length = 0;  
}


四、判断串是否为空


/*判断串S是否为空*/
bool EmptyString(SString &S) {
  if (S.length == 0)
  return false;
  else
  return true;
}


五、串的建立


串的建立中,通过从键盘读入一个字符串并赋给S,如下代码:

/*串的建立*/
void CreateString(SString &S) {
  printf("请输入一个字符串:\n");
  scanf("%s",&S.ch);
}


六、串的遍历输出


/*串的遍历输出*/
void PrintString(SString S) {
  for(int i=0; i<S.length; i++)
  printf("%c ", S.ch[i]);
}


七、求串的长度


通过while()循环,每次读取一个字符然后S.length++,最后得到串的长度,如下代码:

/*求串的长度*/
bool LengthString(SString &S) {
  if(S.ch[0]=='\0')
  return false; //空串报错
  while(S.ch[S.length]!='\0')
  S.length++;
  printf("该串的长度为:%d\n",S.length);
  return true;
}


八、求串的子串


求子串的操作是从串S的第某位起,length为相关长度的子串S1,也就是截取串S的部分,首先要判断求的子串的相关参数是否正确合法,然后通过循环依次将串S的相应内容赋值给新串(子串)中 ,代码如下:

/*求子串*/
//求串S的第pos位置开始,长度为length的子串,并将其存入到串Sub中
int SubString(SString &S,SString &Sub,int pos,int length) {
  if(pos<1||pos>S.length||length<1||length>S.length-pos+1) {
  return false; //以上情况报错 
  } else {
  for(int i=0; i<length; i++)
    Sub.ch[i]=S.ch[pos+i-1];  //依次将串S的相应内容赋值给新串(子串)中 
  Sub.length=length;  //新串(子串)的长度 
  return true;
  }
}


例已知串S“ABCDEFGH”,求串S从第2位起,长度为4的子串子串,并将其存入到串S1中,最后输出串S1。


代码如下:

#include<stdio.h>
#define MAXLEN 255
typedef struct {
  char ch[MAXLEN];  //为每个串分配一个固定长度的数组
  int length;  //串的实际长度
} SString;
/*初始化*/
void InitString(SString &S) {
  S.length = 0;
}
/*求串的长度*/
bool LengthString(SString &S) {
  if(S.ch[0]=='\0')
  return false; //空串报错
  while(S.ch[S.length]!='\0')
  S.length++;
  printf("该串的长度为:%d\n",S.length);
  return true;
}
/*串的建立*/
void CreateString(SString &S) {
  printf("请输入一个字符串:\n");
  scanf("%s",&S.ch);
}
/*串的遍历输出*/
void PrintString(SString S) {
  for(int i=0; i<S.length; i++)
  printf("%c ", S.ch[i]);
}
/*求子串*/
//求串S的第pos位置开始,长度为length的子串,并将其存入到串Sub中
int SubString(SString &S,SString &Sub,int pos,int length) {
  if(pos<1||pos>S.length||length<1||length>S.length-pos+1) {
  return false; //以上情况报错 
  } else {
  for(int i=0; i<length; i++)
    Sub.ch[i]=S.ch[pos+i-1];  //依次将串S的相应内容赋值给新串(子串)中 
  Sub.length=length;  //新串(子串)的长度 
  return true;
  }
}
/*主函数*/
int main() {
  int pos,length;
  SString S,S1;
  InitString(S);  //初始化
  CreateString(S);  //串的创建
  LengthString(S);  //求串的长度
  PrintString(S); //遍历串 
  printf("\n"); 
  printf("请输入从串的第几个字符开始求子串pos以及要取出的子串长度length:\n");
  scanf("%d %d",&pos,&length);
  SubString(S,S1,pos,length);
  LengthString(S1); 
  PrintString(S1);  
}

运行结果如下:

1667279956135.jpg


九、插入子串


插入子串的操作是在串S的第i个位置进行插入,插入子串S1,首先也是要判断插入的位置是否合法(要注意插入后两个串的长度相加之和是否超过存储空间长度),将从第i位开始的字符都向后移动S1串长度,然后通过循环依次将子串S1插入到串S的第i位开始的依次位置处,最后再修改串S的长度,并在新串S的末尾加上字符串结束标志“\0”,代码如下:

/*插入子串*/
bool InsertString(SString &S,SString &S1,int i) {
  int n;
  if(i>S.length+1||S.length+S1.length>MAXLEN)  //报错 
  return false;
  else {
  for(n=S.length-1; n>=i-1; n--)  //从第i位开始的字符都向后移动S1串长度
    S.ch[S1.length+n]=S.ch[n];
  for(n=0; n<S1.length; n++)  //将子串S1依次插入到串S的第i位开始的依次位置处
    S.ch[i+n-1]=S1.ch[n];
  S.length=S.length+S1.length;  //修改串S的长度
  S.ch[S.length]='\0';  //加上字符串结束标志\0 
  return true;
  }
}


例已知串S“aaaaaa”和串S1“bbb”,将串S1插入至串S的第二位,最后输出串S。


代码如下:

#include<stdio.h>
#define MAXLEN 255
typedef struct {
  char ch[MAXLEN];  //为每个串分配一个固定长度的数组
  int length;  //串的实际长度
} SString;
/*初始化*/
void InitString(SString &S) {
  S.length = 0;
}
/*求串的长度*/
bool LengthString(SString &S) {
  if(S.ch[0]=='\0')
  return false; //空串
  while(S.ch[S.length]!='\0')
  S.length++;
  printf("该串的长度为:%d\n",S.length);
  return true;
}
/*串的建立*/
void CreateString(SString &S) {
  printf("请输入一个字符串:\n");
  scanf("%s",&S.ch);
}
/*串的遍历输出*/
void PrintString(SString S) {
  for(int i=0; i<S.length; i++)
  printf("%c ", S.ch[i]);
}
/*插入子串*/
bool InsertString(SString &S,SString &S1,int i) {
  int n;
  if(i>S.length+1||S.length+S1.length>MAXLEN)  //报错 
  return false;
  else {
  for(n=S.length-1; n>=i-1; n--)  //从第i位开始的字符都向后移动S1串长度
    S.ch[S1.length+n]=S.ch[n];
  for(n=0; n<S1.length; n++)  //将子串S1依次插入到串S的第i位开始的依次位置处
    S.ch[i+n-1]=S1.ch[n];
  S.length=S.length+S1.length;  //修改串S的长度
  S.ch[S.length]='\0';  //加上字符串结束标志\0 
  return true;
  }
}
/*主函数*/
int main() {
  int i;
  SString S,S1;
  printf("请输入串S!");
  InitString(S);  //初始化
  CreateString(S);  //串S的创建
  printf("请输入要插入的子串S1!");
  InitString(S1); //初始化
  CreateString(S1); //串S1的创建
  LengthString(S);
  PrintString(S);
  printf("\n"); 
  LengthString(S1);
  PrintString(S1);
  printf("\n"); 
  printf("请输入从串的第几个字符插入子串i:");
  scanf("%d",&i);
  InsertString(S,S1,i); //插入子串 
  printf("插入子串后的串S的长度,");
  LengthString(S);
  PrintString(S);
}


运行结果如下:

1667280044301.jpg


十、删除子串


删除子串的操作也就是删除从串S的某一位置起连续的字符,首先要判断删除的位置以及删除的串长度是否正确合法,否则报错,将第i+j-1位的字符向前移动到第i位依次移动字符,最后再修改串S的长度,并在新串S的末尾加上字符串结束标志“\0”,例如删除第2位长度为4的字符,串S总长度为8,删除后原先第5位的字符向前移动到第2位上,原先第6位的字符向前移动到第3位上,……,代码如下:

/*删除子串*/
bool DeleteString(SString &S,int i,int j) {
  if(i+j-1>S.length)  //所删除的子串超过串S长度,则报错
  return false;
  else {
  for(int n=i+j-1; n<S.length; n++,i++)
    S.ch[i-1]=S.ch[n];  //从串的第i位删除长度为j多个字符
  S.length=S.length-j;  //修改串S的长度
  S.ch[S.length]='\0';  //加上字符串结束标志\0 
  return true;
  }
}


例已知串S“ABCDEFGHIJK”,删除串S中从第2位起,长度为6的子串,最后输出串S。


代码如下:

#include<stdio.h>
#define MAXLEN 255
typedef struct {
  char ch[MAXLEN];  //为每个串分配一个固定长度的数组
  int length;  //串的实际长度
} SString;
/*初始化*/
void InitString(SString &S) {
  S.length = 0;
}
/*求串的长度*/
bool LengthString(SString &S) {
  if(S.ch[0]=='\0')
  return false; //空串
  while(S.ch[S.length]!='\0')
  S.length++;
  printf("该串的长度为:%d\n",S.length);
  return true;
}
/*串的建立*/
void CreateString(SString &S) {
  printf("请输入一个字符串:\n");
  scanf("%s",&S.ch);
}
/*串的遍历输出*/
void PrintString(SString S) {
  for(int i=0; i<S.length; i++)
  printf("%c ", S.ch[i]);
}
/*删除子串*/
bool DeleteString(SString &S,int i,int j) {
  if(i+j-1>S.length)  //所删除的子串
  return false;
  else {
  for(int n=i+j-1; n<S.length; n++,i++)
    S.ch[i-1]=S.ch[n];  //从串的第i位删除长度为j多个字符
  S.length=S.length-j;  //修改串S的长度
  S.ch[S.length]='\0';  //加上字符串结束标志\0 
  return true;
  }
}
/*主函数*/
int main() {
  int i,j;
  SString S;
  InitString(S);  //初始化
  CreateString(S);  //串的创建
  LengthString(S);  //求串的长度
  PrintString(S); //遍历串
  printf("\n");
  printf("请输入从串的第几个字符开始删除位置i以及要删除的子串长度j:\n");
  scanf("%d %d",&i,&j);
  DeleteString(S,i,j);  //删除子串 
  LengthString(S);
  PrintString(S);
}


运行结果如下:

1667280102665.jpg


十一、连接子串


连接子串,也就是将第二个串S2连接到第一个串S1的后,最后形成一个新串S,首先要判断连接成功后的总长度是否预定的存储空间长度,若成功则形成串S,修改串S1的长度并设字符串结束标志;若连接后的串S大于预定的存储空间长度,则多余的部分字符序列将会被舍弃,代码如下:

/*连接子串*/
bool ConnectString(SString &S,SString &S1) {
  int i;
  if(S.length==MAXLEN)  //当串S的长度等于预先设定的存储空间长度MAXLEN则报错 
  return false;
  if(S.length+S1.length<=MAXLEN) {  //连接后,串S的长度小于定的存储空间长度MAXLEN 
  for(i=S.length; i<S.length+S1.length; i++)
    S.ch[i]=S1.ch[i-S.length];
  S.ch[i]='\0'; //加上字符串结束标志\0
  S.length=S.length+S1.length;
  } else if(S.length<MAXLEN) {  //连接后,串S的长度大于MAXLEN,但串S1的长度小于MAXLEN,部分字符将被舍弃 
  for(i=S.length; i<MAXLEN; i++)
    S.ch[i]=S1.ch[i-S.length];
  S.length=MAXLEN;
  }
  return true;
}


例已知串S“aaaa”和串S1“bbbbb”,将串S和串S1连接,最后输出串S。


代码如下:

#include<stdio.h>
#define MAXLEN 255
typedef struct {
  char ch[MAXLEN];  //为每个串分配一个固定长度的数组
  int length;  //串的实际长度
} SString;
/*初始化*/
void InitString(SString &S) {
  S.length = 0;
}
/*求串的长度*/
bool LengthString(SString &S) {
  if(S.ch[0]=='\0')
  return false; //空串
  while(S.ch[S.length]!='\0')
  S.length++;
  printf("该串的长度为:%d\n",S.length);
  return true;
}
/*串的建立*/
void CreateString(SString &S) {
  printf("请输入一个字符串:\n");
  scanf("%s",&S.ch);
}
/*串的遍历输出*/
void PrintString(SString S) {
  for(int i=0; i<S.length; i++)
  printf("%c ", S.ch[i]);
}
/*连接子串*/
bool ConnectString(SString &S,SString &S1) {
  int i;
  if(S.length==MAXLEN)  //当串S的长度等于预先设定的存储空间长度MAXLEN则报错 
  return false;
  if(S.length+S1.length<=MAXLEN) {  //连接后,串S的长度小于定的存储空间长度MAXLEN 
  for(i=S.length; i<S.length+S1.length; i++)
    S.ch[i]=S1.ch[i-S.length];
  S.ch[i]='\0'; //加上字符串结束标志\0
  S.length=S.length+S1.length;
  } else if(S.length<MAXLEN) {  //连接后,串S的长度大于MAXLEN,但串S1的长度小于MAXLEN,部分字符将被舍弃 
  for(i=S.length; i<MAXLEN; i++)
    S.ch[i]=S1.ch[i-S.length];
  S.length=MAXLEN;
  }
  return true;
}
/*主函数*/
int main() {
  SString S,S1;
  printf("请输入串S!");
  InitString(S);  //初始化
  CreateString(S);  //串S的创建
  printf("请输入串S1!");
  InitString(S1); //初始化
  CreateString(S1); //串S1的创建
  LengthString(S);
  PrintString(S);
  printf("\n");
  LengthString(S1);
  PrintString(S1);
  printf("\n");
  ConnectString(S,S1);
  printf("连接后的串S的长度,");
  LengthString(S);
  PrintString(S);
}

运行结果如下:

1667280132288.jpg


十二、比较子串


比较两个串S1和串S2是否相等,两个串相等的条件是两个串的长度相等且对应位置的字符也都相同,比较子串的代码如下:

/*比较子串*/
bool CompareString(SString &S,SString &S1) {
  int i=0,flag=0;
  while(S.ch[i]!='\0'&&S1.ch[i]!='\0') {  //当串没到尾部时循环一直执行下去 
  if(S.ch[i]!=S1.ch[i]) { //比较两个串对应位置的字符是否相同 
    flag=1;  //如果不相同,则将flag置为1 
    break;
  } else  //否则i++ 
    i++;
  }
  if(S.length==S1.length&&flag==0) {
  printf("两个串相等!");
  return true;  //相等
  } else {
  printf("两个串不相等!");
  return false; //不相等
  }
}



例已知串S“aaaa”和串S1“aaba”,比较这两个串。


代码如下:

#include<stdio.h>
#define MAXLEN 255
typedef struct {
  char ch[MAXLEN];  //为每个串分配一个固定长度的数组
  int length;  //串的实际长度
} SString;
/*初始化*/
void InitString(SString &S) {
  S.length = 0;
}
/*求串的长度*/
bool LengthString(SString &S) {
  if(S.ch[0]=='\0')
  return false; //空串
  while(S.ch[S.length]!='\0')
  S.length++;
  printf("该串的长度为:%d\n",S.length);
  return true;
}
/*串的建立*/
void CreateString(SString &S) {
  printf("请输入一个字符串:\n");
  scanf("%s",&S.ch);
}
/*串的遍历输出*/
void PrintString(SString S) {
  for(int i=0; i<S.length; i++)
  printf("%c ", S.ch[i]);
}
/*比较子串*/
bool CompareString(SString &S,SString &S1) {
  int i=0,flag=0;
  while(S.ch[i]!='\0'&&S1.ch[i]!='\0') {  //当串没到尾部时循环一直执行下去 
  if(S.ch[i]!=S1.ch[i]) { //比较两个串对应位置的字符是否相同 
    flag=1;  //如果不相同,则将flag置为1 
    break;
  } else  //否则i++ 
    i++;
  }
  if(S.length==S1.length&&flag==0) {
  printf("两个串相等!");
  return true;  //相等
  } else {
  printf("两个串不相等!");
  return false; //不相等
  }
}
/*主函数*/
int main() {
  SString S,S1;
  printf("请输入串S!");
  InitString(S);  //初始化
  CreateString(S);  //串S的创建
  printf("请输入串S1!");
  InitString(S1); //初始化
  CreateString(S1); //串S1的创建
  LengthString(S);
  PrintString(S);
  printf("\n");
  LengthString(S1);
  PrintString(S1);
  printf("\n");
  CompareString(S,S1);
}


运行结果如下:

1667280204479.jpg


十三、串的模式匹配算法


串的模式匹配也称为串的定位,搜索串中的子串,若存在则返回子串在串S中第一次出现的位置,否则直到i、j指向两个串尾时结束循环,对应位置的相应字符相同则继续比较,若不相同则进行下一次字符进行比较(若第一个字符不相同,即i=i-j+1=1,j=0,开始将串S的第二个字符与串S1的第一个字符进行比较),代码如下:

/*搜索子串,在串S中查找子串S1*/
bool IndexString(SString &S,SString &S1) {
  int i=0,j=0;
  while(i<S.length&&j<S1.length) {  //直到两个串的串尾时结束while循环
  if(S.ch[i]==S1.ch[j]) { //若对应字符相同则继续比较下一个字符,i++、j++
    i++;
    j++;
  } else {  //否则进行下一次的字符串首字符比较
    i=i-j+1;
    j=0;
  }
  }
  if(j>=S1.length) {  //当串S中有串S1时,返回其首次出现的起始位置i,由于是数组下标i的值要减一
  printf("查找成功,该子串在主串中第一次出现的位置为%d",i-1);
  return true;
  } else {
  printf("查找失败,主串中没有该子串!");
  return false;
  }
}


例已知串S“ABCDEF”和子串S1“CDE”,查找子串S1是否在串S中。


代码如下:

#include<stdio.h>
#define MAXLEN 255
typedef struct {
  char ch[MAXLEN];  //为每个串分配一个固定长度的数组
  int length;  //串的实际长度
} SString;
/*初始化*/
void InitString(SString &S) {
  S.length = 0;
}
/*求串的长度*/
bool LengthString(SString &S) {
  if(S.ch[0]=='\0')
  return false; //空串
  while(S.ch[S.length]!='\0')
  S.length++;
  printf("该串的长度为:%d\n",S.length);
  return true;
}
/*串的建立*/
void CreateString(SString &S) {
  printf("请输入一个字符串:\n");
  scanf("%s",&S.ch);
}
/*串的遍历输出*/
void PrintString(SString S) {
  for(int i=0; i<S.length; i++)
  printf("%c ", S.ch[i]);
}
/*搜索子串,在串S中查找子串S1*/
bool IndexString(SString &S,SString &S1) {
  int i=0,j=0;
  while(i<S.length&&j<S1.length) {  //直到两个串的串尾时结束while循环
  if(S.ch[i]==S1.ch[j]) { //若对应字符相同则继续比较下一个字符,i++、j++
    i++;
    j++;
  } else {  //否则进行下一次的字符串首字符比较
    i=i-j+1;
    j=0;
  }
  }
  if(j>=S1.length) {  //当串S中有串S1时,返回其首次出现的起始位置i,由于是数组下标i的值要减一
  printf("查找成功,该子串在主串中第一次出现的位置为%d",i-1);
  return true;
  } else {
  printf("查找失败,主串中没有该子串!");
  return false;
  }
}
/*主函数*/
int main() {
  int i;
  SString S,S1;
  printf("请输入串S!");
  InitString(S);  //初始化
  CreateString(S);  //串S的创建
  printf("请输入串S1!");
  InitString(S1); //初始化
  CreateString(S1); //串S1的创建
  LengthString(S);
  PrintString(S);
  printf("\n");
  LengthString(S1);
  PrintString(S1);
  printf("\n");
  IndexString(S,S1);
}


运行结果如下:

1667280262319.jpg


例已知串S“ABCDEFGHJI”和子串S1“GI”,查找子串S1是否在串S中。


代码如下:


#include<stdio.h>
#define MAXLEN 255
typedef struct {
  char ch[MAXLEN];  //为每个串分配一个固定长度的数组
  int length;  //串的实际长度
} SString;
/*初始化*/
void InitString(SString &S) {
  S.length = 0;
}
/*求串的长度*/
bool LengthString(SString &S) {
  if(S.ch[0]=='\0')
  return false; //空串
  while(S.ch[S.length]!='\0')
  S.length++;
  printf("该串的长度为:%d\n",S.length);
  return true;
}
/*串的建立*/
void CreateString(SString &S) {
  printf("请输入一个字符串:\n");
  scanf("%s",&S.ch);
}
/*串的遍历输出*/
void PrintString(SString S) {
  for(int i=0; i<S.length; i++)
  printf("%c ", S.ch[i]);
}
/*搜索子串,在串S中查找子串S1*/
bool IndexString(SString &S,SString &S1) {
  int i=0,j=0;
  while(i<S.length&&j<S1.length) {  //直到两个串的串尾时结束while循环
  if(S.ch[i]==S1.ch[j]) { //若对应字符相同则继续比较下一个字符,i++、j++
    i++;
    j++;
  } else {  //否则进行下一次的字符串首字符比较
    i=i-j+1;
    j=0;
  }
  }
  if(j>=S1.length) {  //当串S中有串S1时,返回其首次出现的起始位置i,由于是数组下标i的值要减一
  printf("查找成功,该子串在主串中第一次出现的位置为%d",i-1);
  return true;
  } else {
  printf("查找失败,主串中没有该子串!");
  return false;
  }
}
/*主函数*/
int main() {
  int i;
  SString S,S1;
  printf("请输入串S!");
  InitString(S);  //初始化
  CreateString(S);  //串S的创建
  printf("请输入串S1!");
  InitString(S1); //初始化
  CreateString(S1); //串S1的创建
  LengthString(S);
  PrintString(S);
  printf("\n");
  LengthString(S1);
  PrintString(S1);
  printf("\n");
  IndexString(S,S1);  //串的搜索
}


运行结果如下:

1667280299361.jpg


顺序存储结构实现串的完整代码

#include<stdio.h>
#define MAXLEN 255
typedef struct {
  char ch[MAXLEN];  //为每个串分配一个固定长度的数组
  int length;  //串的实际长度
} SString;
/*初始化*/
void InitString(SString &S) {
  S.length = 0;
}
/*判断串S是否为空*/
bool EmptyString(SString &S) {
  if (S.length == 0)
  return false;
  else
  return true;
}
/*求串的长度*/
bool LengthString(SString &S) {
  if(S.ch[0]=='\0')
  return false; //空串
  while(S.ch[S.length]!='\0')
  S.length++;
  printf("该串的长度为:%d\n",S.length);
  return true;
}
/*串的建立*/
void CreateString(SString &S) {
  printf("请输入一个字符串:\n");
  scanf("%s",&S.ch);
}
/*串的遍历输出*/
void PrintString(SString S) {
  for(int i=0; i<S.length; i++)
  printf("%c ", S.ch[i]);
}
/*求子串*/
//求串S的第pos位置开始,长度为length的子串,并将其存入到串Sub中
int SubString(SString &S,SString &Sub,int pos,int length) {
  if(pos<1||pos>S.length||length<1||length>S.length-pos+1) {
  return false; //以上情况报错
  } else {
  for(int i=0; i<length; i++)
    Sub.ch[i]=S.ch[pos+i-1];  //依次将串S的相应内容赋值给新串(子串)中
  Sub.length=length;  //新串(子串)的长度
  return true;
  }
}
/*插入子串,在串S中指定位置插入串S1*/
bool InsertString(SString &S,SString &S1,int i) {
  int n;
  if(i>S.length+1||S.length+S1.length>MAXLEN)  //报错
  return false;
  else {
  for(n=S.length-1; n>=i-1; n--)  //从第i位开始的字符都向后移动S1串长度
    S.ch[S1.length+n]=S.ch[n];
  for(n=0; n<S1.length; n++)  //将子串S1依次插入到串S的第i位开始的依次位置处
    S.ch[i+n-1]=S1.ch[n];
  S.length=S.length+S1.length;  //修改串S的长度
  S.ch[S.length]='\0';  //加上字符串结束标志\0
  return true;
  }
}
/*删除子串,删除串S中指定位置开始的字符*/
bool DeleteString(SString &S,int i,int j) {
  if(i+j-1>S.length)
  return false;
  else {
  for(int n=i+j-1; n<S.length; n++,i++)
    S.ch[i-1]=S.ch[n];  //从串的第i位删除长度为j多个字符
  S.length=S.length-j;  //修改串S的长度
  S.ch[S.length]='\0';  //加上字符串结束标志\0
  return true;
  }
}
/*连接子串,连接串S和串S1*/
bool ConnectString(SString &S,SString &S1) {
  int i;
  if(S.length==MAXLEN)  //当串S的长度等于预先设定的存储空间长度MAXLEN则报错
  return false;
  if(S.length+S1.length<=MAXLEN) {  //连接后,串S的长度小于定的存储空间长度MAXLEN
  for(i=S.length; i<S.length+S1.length; i++)
    S.ch[i]=S1.ch[i-S.length];
  S.ch[i]='\0'; //加上字符串结束标志\0
  S.length=S.length+S1.length;
  } else if(S.length<MAXLEN) {  //连接后,串S的长度大于MAXLEN,但串S1的长度小于MAXLEN,部分字符将被舍弃
  for(i=S.length; i<MAXLEN; i++)
    S.ch[i]=S1.ch[i-S.length];
  S.length=MAXLEN;
  }
  return true;
}
/*比较子串,比较串S和串S1是否相等*/
bool CompareString(SString &S,SString &S1) {
  int i=0,flag=0;
  while(S.ch[i]!='\0'&&S1.ch[i]!='\0') {  //当串没到尾部时循环一直执行下去
  if(S.ch[i]!=S1.ch[i]) { //比较两个串对应位置的字符是否相同
    flag=1;  //如果不相同,则将flag置为1
    break;
  } else  //否则i++
    i++;
  }
  if(S.length==S1.length&&flag==0) {
  printf("两个串相等!");
  return true;  //相等
  } else {
  printf("两个串不相等!");
  return false; //不相等
  }
}
/*搜索子串,在串S中查找子串S1*/
bool IndexString(SString &S,SString &S1) {
  int i=0,j=0;
  while(i<S.length&&j<S1.length) {  //直到两个串的串尾时结束while循环
  if(S.ch[i]==S1.ch[j]) { //若对应字符相同则继续比较下一个字符,i++、j++
    i++;
    j++;
  } else {  //否则进行下一次的字符串首字符比较
    i=i-j+1;
    j=0;
  }
  }
  if(j>=S1.length) {  //当串S中有串S1时,返回其首次出现的起始位置i,由于是数组下标i的值要减一
  printf("查找成功,该子串在主串中第一次出现的位置为%d",i-1);
  return true;
  } else {
  printf("查找失败,主串中没有该子串!");
  return false;
  }
}
相关文章
|
14天前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
57 16
|
1月前
|
存储 安全 数据库
除了 HashMap,还有哪些数据结构可以实现键值对存储?
【10月更文挑战第11天】 除了`HashMap`,其他常见支持键值对存储的数据结构包括:`TreeMap`(基于红黑树,键有序)、`LinkedHashMap`(保留插入顺序)、`HashTable`(线程安全)、`B-Tree`和`B+Tree`(高效存储大量数据)、`SkipList`(通过跳跃指针提高查找效率)及`UnorderedMap`(类似`HashMap`)。选择合适的数据结构需根据排序、并发、存储和查找性能等需求。
|
2月前
|
存储 Java
java数据结构,线性表链式存储(单链表)的实现
文章讲解了单链表的基本概念和Java实现,包括头指针、尾节点和节点结构。提供了实现代码,包括数据结构、接口定义和具体实现类。通过测试代码演示了单链表的基本操作,如添加、删除、更新和查找元素,并总结了操作的时间复杂度。
java数据结构,线性表链式存储(单链表)的实现
|
1月前
|
存储 编译器 C++
【初阶数据结构】掌握二叉树遍历技巧与信息求解:深入解析四种遍历方法及树的结构与统计分析
【初阶数据结构】掌握二叉树遍历技巧与信息求解:深入解析四种遍历方法及树的结构与统计分析
|
2月前
|
存储 JSON NoSQL
redis基本数据结构(String,Hash,Set,List,SortedSet)【学习笔记】
这篇文章是关于Redis基本数据结构的学习笔记,包括了String、Hash、Set、List和SortedSet的介绍和常用命令。文章解释了每种数据结构的特点和使用场景,并通过命令示例演示了如何在Redis中操作这些数据结构。此外,还提供了一些练习示例,帮助读者更好地理解和应用这些数据结构。
redis基本数据结构(String,Hash,Set,List,SortedSet)【学习笔记】
|
1月前
探索顺序结构:栈的实现方式
探索顺序结构:栈的实现方式
|
1月前
|
存储 算法
【数据结构】二叉树——顺序结构——堆及其实现
【数据结构】二叉树——顺序结构——堆及其实现
|
2月前
|
存储 人工智能 C语言
数据结构基础详解(C语言): 栈的括号匹配(实战)与栈的表达式求值&&特殊矩阵的压缩存储
本文首先介绍了栈的应用之一——括号匹配,利用栈的特性实现左右括号的匹配检测。接着详细描述了南京理工大学的一道编程题,要求判断输入字符串中的括号是否正确匹配,并给出了完整的代码示例。此外,还探讨了栈在表达式求值中的应用,包括中缀、后缀和前缀表达式的转换与计算方法。最后,文章介绍了矩阵的压缩存储技术,涵盖对称矩阵、三角矩阵及稀疏矩阵的不同压缩存储策略,提高存储效率。
384 8
|
2月前
|
存储 算法 C语言
数据结构基础详解(C语言): 二叉树的遍历_线索二叉树_树的存储结构_树与森林详解
本文从二叉树遍历入手,详细介绍了先序、中序和后序遍历方法,并探讨了如何构建二叉树及线索二叉树的概念。接着,文章讲解了树和森林的存储结构,特别是如何将树与森林转换为二叉树形式,以便利用二叉树的遍历方法。最后,讨论了树和森林的遍历算法,包括先根、后根和层次遍历。通过这些内容,读者可以全面了解二叉树及其相关概念。
|
2月前
|
存储 机器学习/深度学习 C语言
数据结构基础详解(C语言): 树与二叉树的基本类型与存储结构详解
本文介绍了树和二叉树的基本概念及性质。树是由节点组成的层次结构,其中节点的度为其分支数量,树的度为树中最大节点度数。二叉树是一种特殊的树,其节点最多有两个子节点,具有多种性质,如叶子节点数与度为2的节点数之间的关系。此外,还介绍了二叉树的不同形态,包括满二叉树、完全二叉树、二叉排序树和平衡二叉树,并探讨了二叉树的顺序存储和链式存储结构。

热门文章

最新文章