数据结构<c语言>——串
一、顺序串的基本操作:
假定下面所有的串均为顺序串,参数ch、ch1和ch2均是字符型,编写算法依次实现下列操作。
① 将串r中所有值为ch1的字符换成ch2的字符。
② 将串r中所有字符按照相反的次序仍存放在r中。
③ 从串r中删除其值等于ch的所有字符。
④ 从串r1中第index个字符起求出首次与串r2相同的子串的起始位置。
输入格式:第一行:r
第二行:r1
第三行:r2
第四行:ch ch1 ch2
第五行:index
输出格式:
第一行:操作①结果
第二行:操作②结果
第三行:操作③结果
第四行:操作④结果(不存在输出-1)
1.操作1:替换字符
// 1. 字符替换:将S中所有ch1替换为ch2
void StrReplaceCh(SString *S, char ch1, char ch2) {for (int i = 0; i < S->len; i++) {if (S->ch[i] == ch1) {S->ch[i] = ch2;}}
}
2.操作2(双指针):逆置字符串
// 2. 串逆置:将S中字符按相反次序存放
void StrRreverse(SString *S) {int left = 0; // 左指针(起始位置)int right = S->len - 1;// 右指针(末尾位置)while (left < right) {// 交换左右指针指向的字符char temp = S->ch[left];S->ch[left] = S->ch[right];S->ch[right] = temp;// 指针移动left++;right--;}
}
3.操作3:删除字符
// 3. 字符删除:删除S中所有值为ch的字符
void StrDeleteCh(SString *S, char ch) {int k = 0; // 记录有效字符的位置for (int i = 0; i < S->len; i++) {if (S->ch[i] != ch) {S->ch[k++] = S->ch[i]; // 有效字符存到k位置,k自增}}S->len = k; // 更新串的长度为有效字符数
}
4.操作4:定位子串(查找主串中与子串进行匹配的起始位置)
// 4. 子串定位:从S的pos位置起,查找首次匹配T的起始位置(失败返回-1)
int StrIndex(SString *S, int pos, SString T) {// 边界检查:T为空、pos超出范围、S长度不足if (T.len == 0 || pos < 0 || pos >= S->len || S->len < T.len) {return -1;}// i:S中当前比较的位置,从pos开始;j:T中当前比较的位置int i = pos, j = 0;// 遍历S中可能的起始位置(最多到S->len - T->len)while (i <= S->len - T.len && j < T.len) {if (S->ch[i] == T.ch[j]) {// 字符匹配,继续比较下一个i++;j++;} else {// 字符不匹配,回溯:S回到上一轮起始位置+1,T回到0i = i - j + 1;j = 0;}}// 若j遍历完T,说明匹配成功,返回起始位置(i - T.len)return (j == T.len) ? (i - T.len) : -1;
}
5.代码汇总:
#include<stdio.h>
#include <stdlib.h>
#include <string.h>#define MAXLEN 50 // 字符串的最大长度
typedef struct{char ch[MAXLEN];int len;
}SString;// 函数声明
void StrReplaceCh(SString *S, char ch1, char ch2); /*字符替换函数*/
void StrRreverse(SString *S); /*串逆置函数*/
void StrDeleteCh(SString *S, char ch); /*在串S中删除值为ch的字符*/
int StrIndex(SString *S, int pos, SString T); /*求串T在串S中的位置*/// 串初始化(裁判代码已提供,此处仅作参考)
void StrInit(SString *s){s->len=0;
}// 串赋值(裁判代码已提供,此处仅作参考)
void StrAssign(SString *s, char *r){ int i=0;while (r[i]!='\0'){s->ch[i]=r[i];i++;}s->len=i;
}// 1. 字符替换:将S中所有ch1替换为ch2
void StrReplaceCh(SString *S, char ch1, char ch2) {for (int i = 0; i < S->len; i++) {if (S->ch[i] == ch1) {S->ch[i] = ch2;}}
}// 2. 串逆置:将S中字符按相反次序存放
void StrRreverse(SString *S) {int left = 0; // 左指针(起始位置)int right = S->len - 1;// 右指针(末尾位置)while (left < right) {// 交换左右指针指向的字符char temp = S->ch[left];S->ch[left] = S->ch[right];S->ch[right] = temp;// 指针移动left++;right--;}
}// 3. 字符删除:删除S中所有值为ch的字符
void StrDeleteCh(SString *S, char ch) {int k = 0; // 记录有效字符的位置for (int i = 0; i < S->len; i++) {if (S->ch[i] != ch) {S->ch[k++] = S->ch[i]; // 有效字符存到k位置,k自增}}S->len = k; // 更新串的长度为有效字符数
}// 4. 子串定位:从S的pos位置起,查找首次匹配T的起始位置(失败返回-1)
int StrIndex(SString *S, int pos, SString T) {// 边界检查:T为空、pos超出范围、S长度不足if (T.len == 0 || pos < 0 || pos >= S->len || S->len < T.len) {return -1;}// i:S中当前比较的位置,从pos开始;j:T中当前比较的位置int i = pos, j = 0;// 遍历S中可能的起始位置(最多到S->len - T->len)while (i <= S->len - T.len && j < T.len) {if (S->ch[i] == T.ch[j]) {// 字符匹配,继续比较下一个i++;j++;} else {// 字符不匹配,回溯:S回到上一轮起始位置+1,T回到0i = i - j + 1;j = 0;}}// 若j遍历完T,说明匹配成功,返回起始位置(i - T.len)return (j == T.len) ? (i - T.len) : -1;
}// 裁判测试程序(已提供,此处仅作参考)
void main()
{SString s, s1, s2;char r[50], r1[50], r2[50];char ch, ch1, ch2;int i, loc, index;gets(r); gets(r1); gets(r2);scanf("%c %c %c", &ch, &ch1, &ch2); StrAssign(&s, r);/*操作1:字符替换*/StrReplaceCh(&s, ch1, ch2);for(i=0;i<s.len;i++)printf("%c", s.ch[i]);printf("\n");/*操作2:串逆置*/StrRreverse(&s);for(i=0;i<s.len;i++)printf("%c", s.ch[i]);printf("\n");/*操作3:串删除*/StrDeleteCh(&s, ch);for(i=0;i<s.len;i++)printf("%c", s.ch[i]);printf("\n");/*操作4:串定位匹配*/StrAssign(&s1, r1); StrAssign(&s2, r2);scanf("%d", &index); loc=StrIndex(&s1, index, s2);printf("%d\n",loc);
}
二、堆串的基本操作:
编写算法,实现堆串的基本操作StrReplace(S, T, V)。
初始条件: 串S, T和 V 均已存在,且 V 是非空串。
操作结果: 用V替换主串S中出现的所有与(模式串)T相等的不重叠的子串。
输入格式:第一行:S
第二行:T
第三行:V
输出格式:
S = 被替换后的结果
1.替代操作:
// 核心:串替换函数
void StrReplace(HString *S, HString T, HString V) {// 边界条件:T为空或T长度大于S长度,无匹配可替换if (T.len == 0 || T.len > S->len) {return;}int pos = 0; // 每次定位的起始位置int start; // 匹配到的子串起始位置while (1) {// 从pos位置开始查找T的匹配start = StrIndex(S, pos, T);if (start == -1) {break; // 无更多匹配,退出循环}// 1. 删除S中从start开始的T子串StrDelete(S, start, T.len);// 2. 在start位置插入V子串StrInsert(S, start, V);// 3. 更新下一轮定位起点(避免重叠,跳过已替换的V)pos = start + V.len;// 若起点超出S长度,退出循环if (pos >= S->len) {break;}}
}
2.代码汇总:
#include<stdio.h>
#include <stdlib.h>
#include <string.h>typedef struct{char *ch;int len;
}HString;// 函数声明(裁判已提供部分,此处补充)
void StrReplace(HString *S, HString T, HString V);
void StrInit(HString *s);
int StrAssign(HString *s, char *tval);
int StrInsert(HString *s, int pos, HString t);
int StrDelete(HString *s, int pos, int len);
int StrIndex(HString *s, int pos, HString t);//初始化
void StrInit(HString *s) {s->ch=NULL;s->len=0;
}
//赋值字符串
int StrAssign(HString *s, char *tval) { int len,i=0;if (s->ch!=NULL) free(s->ch);while (tval[i]!='\0') i++;len=i;if (len){s->ch=(char *)malloc(len);if (s->ch==NULL) return(0); for (i=0;i<len;i++)s->ch[i]=tval[i];}else s->ch=NULL;s->len=len;return(1);
}
//插入串
int StrInsert(HString *s, int pos, HString t){int i; char *temp;if (pos<0 || pos>s->len)return(0);temp=(char *)malloc(s->len + t.len);if (temp==NULL) return(0);for (i=0;i<pos;i++)temp[i]=s->ch[i];for (i=0;i<t.len;i++)temp[i+pos]=t.ch[i];for (i=pos;i<s->len;i++)temp[i + t.len]=s->ch[i];s->len+=t.len;free(s->ch);s->ch=temp;return(1);
}
//删除串
int StrDelete(HString *s, int pos, int len) {int i; char *temp;if (pos<0 || pos>(s->len - len))return(0);temp=(char *)malloc(s->len - len);if (temp==NULL) return(0);for (i=0;i<pos;i++)temp[i]=s->ch[i];for (i=pos;i<s->len - len;i++)temp[i]=s->ch[i+len];s->len=s->len-len;free(s->ch);s->ch=temp;return(1);
}
//求索引
int StrIndex(HString *s, int pos, HString t){int i,j,start;if (t.len==0 || pos < 0 || pos >= s->len) return(-1);start=pos; i=start; j=0;while (i<s->len && j<t.len){if (s->ch[i]==t.ch[j]) {i++;j++;}else {start++; i=start; j=0;}}if (j>=t.len) return(start);else return(-1);
} // 核心:串替换函数
void StrReplace(HString *S, HString T, HString V) {// 边界条件:T为空或T长度大于S长度,无匹配可替换if (T.len == 0 || T.len > S->len) {return;}int pos = 0; // 每次定位的起始位置int start; // 匹配到的子串起始位置while (1) {// 从pos位置开始查找T的匹配start = StrIndex(S, pos, T);if (start == -1) {break; // 无更多匹配,退出循环}// 1. 删除S中从start开始的T子串StrDelete(S, start, T.len);// 2. 在start位置插入V子串StrInsert(S, start, V);// 3. 更新下一轮定位起点(避免重叠,跳过已替换的V)pos = start + V.len;// 若起点超出S长度,退出循环if (pos >= S->len) {break;}}
}// 裁判测试程序
void main()
{HString s, t, v;char str1[100],str2[100],str3[100];int i;gets(str1); StrInit(&s); StrAssign(&s, str1);gets(str2); StrInit(&t); StrAssign(&t, str2);gets(str3); StrInit(&v); StrAssign(&v, str3);StrReplace(&s, t, v);printf("S = '");for(i=0;i<s.len;i++)printf("%c", s.ch[i]);printf("'\n");
}