数据结构---05---堆串---20205106009---郭睿玥
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 | /*郭睿玥第五次算法实验作业*/ /*实验原理 串的堆存储结构,与定长顺序串的存储结构类似,都是用一维数组地址连续的存储单元存储串 的字符序列,不同的是堆串的存储空间是在程序执行过程中动态分配的。 在系统中存在一个称为“堆”的自由存储区,每当建立一个新串时,可以通过动态分配函数从 这个空间中分配一块实际串所需的存储空间,来存储新的串值。只要空间能分配成功,则在操作的 过程中就不会发生“截断”的情况。C语言采用malloc()、free()等函数完成动态存储管理。 */ /*实验环境 CodeBlocks*/ /*实验目的 1. 了解顺序串的结构特点及有关概念; 2. 理解顺序串的存储结构; 3. 掌握顺序串的基本操作算法。 */ /*实验内容 建立顺序串,完成顺序串的基本操作:初始化、求串长、串赋值、串连接、求子串、串比较、字串定位、串插入、子串删除、串替换、串清空、串输出等。 */ #include<stdio.h> #include<string.h> #include<stdlib.h> #define MAXSIZE 100 typedef int Status; // 定义函数返回值类型 typedef char ElemType; // 定义每条数据的结构体类型 typedef struct { //定义串 char *stri; //若不是空串则按照串长度分配空间,否则为NULL int length; //串长 }string; //别名 Status insitstring(string * SS){ //初始化 SS->stri =NULL; //空串不分配空间 SS->length = 0; //空串串长为0 return 1; } Status lengthstring(string * SS) //求串长 { return SS->length; //返回SS的元素个数,串长度包含在数据结构中因此直接返回即可 } void StrAssign(string *SS, char str1[]) //串赋值 { int i,j; if (SS->length) //如果不是空串则清空需要赋值的串 free (SS); //清空操作 for (i=0;str1[i]!=NULL;i++) //循环查找所要赋值的字符数组,直到字符数组的某个元素为空,循环次数就是串长度 { ; } SS->length=i; //串长度赋值 if (i){ SS->stri=( char *) malloc (SS->length* sizeof ( char *)); //根据串长度申请空间 if (!SS->stri) //如果分配失败则结束 exit (-1); //退出 for (j=0;j<SS->length;j++) //通过循环逐个元素赋值,j表示循环次数,也表示被赋值的元素下标 { SS->stri[j]=str1[j]; //赋值操作 } } else { //如果输入的字符数组不合理则重新输入 printf ( "请重新输入\n" ); //提示 char ch1[MAXSIZE]; //新建数组 gets (ch1); //输入 StrAssign(SS,ch1); //递归调用赋值函数 } return 0; //程序结束返回 } void printstring(string T) //串输出 { int i; for (i=0;i<T.length;i++) //通过循环逐个元素输出,i表示循环次数,也表示被赋值的元素下标 printf ( "%c" ,T.stri[i]); //输出元素的值 printf ( "\n" ); //换行 } Status constring(string *SS,string *S) //串连接 { int i,j; SS->stri=( char *) realloc (SS->stri,(SS->length+S->length )* sizeof ( char )); //根据需要连接的两个穿分配空间 if (!SS->stri) //如果分配失败则结束 { printf ( "分配空间失败" ); //提示 exit (-1); //退出 } else { //如果成功,则通过循环,按照顺序一个个把S的元素增加到SS内,i表示S下标,j表示SS下标 for (i=0,j=SS->length;i<S->length;i++,j++) //循环,一共执行S->length次 SS->stri[j]=S->stri[i]; //赋值 SS->length+=S->length; //改变串长 } return 1; //返回 } Status comparestring(string * SS,string *S) //串比较 { int i,j; if (SS->length!=S->length) //首先比较串长,如果两个串的串长不一致比较无意义,故不进行比较 { printf ( "两个串的长度不一致无法比较\n" ); //提示 return 5; //返回 } for (i=0;i<SS->length;i++) //通过循环,按照顺序逐个比较知道找到第一个两个串不一样的元素 { if (SS->stri[i]>S->stri[i]) //如果SS的第i个元素大,则返回1 return 1; if (SS->stri[i]<S->stri[i]) //如果S的第i个元素大,则返回 return -1; //如果两个一样大则循环继续 } return 0; } void clearstring(string * SS) //串清空 { if (SS->stri) //如果不是空串则清空需要赋值的串 free (SS); //清空操作 insitstring(SS); //调用初始化函数 printf ( "清空成功" ); //提示 return 0; //返回 } Status emptystring(string * SS) //串判空 { if (SS->length = 0) //空串的串长为0可以直接判断 return 0; //空串返回0 return 1; //非空串返回1 } Status insertstring(string * SS,string * S, int pos) //串插入 { if (pos < 0||pos-1>SS->length) //判断插入位置是否合法 { printf ( "插入位置不正确\n" ); //提示 return 0; //由于插入的位置不合法故函数无法进行 } int i=SS->length-1,j=i+S->length,k; SS->stri=( char *) realloc (SS->stri,(SS->length+S->length )* sizeof ( char )); //根据需要连接的两个穿分配空间 if (!SS->stri) //如果分配失败则结束 { printf ( "内存分配失败" ); //提示 exit (-1); //退出 } for (k=0;k<SS->length-pos+1;i--,j--,k++) //通过循环,从后往前一直到要插入的位置的串元素依次后移 SS->stri[j]=SS->stri[i]; //后移操作 for (i=0,j=pos-1;i<S->length;i++,j++) //通过循环,从要插入串的位置开始,依次赋值 SS->stri[j]=S->stri[i]; //赋值 SS->length=SS->length+S->length; //改变串长 printf ( "插入后的串为" ); //提示 printstring(*SS); //调用输出函数输出插入后的串 return 0; } Status findstring(string * substr,string SS, int pos, int len) //截取子串 { int i; if (!substr->stri) //如果不是空串则清空串 free (substr->stri); //清空操作 else { substr->stri=( char *) malloc (len* sizeof ( char )); //为子串分配空间 if (!substr->stri) //如果分配失败则结束 { printf ( "存储分配失败" ); //提示 exit (-1); //退出 } for (i=0;i<len;i++) //通过循环,从需要截取子串的位置开始,按照参数中的len截取子串 substr->stri[i]=SS.stri[i+pos-1]; //逐个元素截取 substr->length=len; //子串长度就是参数中的len return 1; //返回 } } Status searchsub(string * SS,string substr) //子串定位 { int i=1,j=0,k; do { if (substr.stri[0]==SS->stri[j]) //如果SS中存在子串则substr的第一个元素一定和ss的某个元素相等,如果相等往下比较,不相等ss后移 { k=j+1; while (i<substr.length) //通过循环判断串的第i+1到第i+1+substr.length个元素的值是不是都和substr串一致 { if (substr.stri[i]!=SS->stri[k]) //如果当前元素和子串的元素不一致则跳出循环 { i=1; //返回初始状态方便下一次判断 j++; //j后移 break ; //跳出循环 } else { //如果一直接着判断下一个元素 i++; k++; } } if (i==substr.length) //判断是否进行完毕 break ; //循环结束 } else j++; //如果SS中的第j个元素和子串中第0个元素不等则j后移 } while (j<SS->length); //循环条件 if (j==SS->length) //如果j能等于SS的串长则没有这个子串 { printf ( "没有这个子串" ); //提示 return -1; //返回 } printf ( "字串位于第%d\n" ,j+1); //输出子串位置 return j+1; //返回子串位置 } void deletesub(string* SS,string substr, int pos) //子串删除 { int i,len; char *p; //定义一个指针 len=substr.length; if (pos<0||len<0||pos+len-1>SS->length) //判断删除位置是否合法 { printf ( "删除位置不正确\n" ); //提示 return 0; //由于删除的位置不合法故函数无法进行 } p=( char *) malloc (SS->length-len); //根据需要删除的子串分配空间 if (!p) //如果分配失败则结束 exit (-1); //退出 for (i=0;i<pos-1;i++) //将串第pos位置之前的字符复制到p中 p[i]=SS->stri[i]; for (i = pos-1;i < SS->length-len;i++) //将串第pos+len位置以后的字符复制到p中 p[i] = SS->stri[i+len]; //逐个元素复制 SS->length=SS->length-len; //修改串的长度 free (SS->stri); //释放原来的串S的内存空间 SS->stri=p; //将串的str指向p字符串 return 1; //返回 } void repalcesub(string * SS,string substr,string*S) //串替换,用S替换串SS中的所有子串substr { int i=0,j; if (substr.length==0) //判断要替换的串是否是空串 return 0; //返回 do { //通过循环替换所有子串 i=searchsub(SS,substr); //通过调用定位函数找到子串位置 if (i==-1) //如果没有这个子串结束 return 0; //返回 insertstring(SS,S,i); //在找到的位置里插入要替换的子串 j=i+S->length; //j表示要被替换子串当前的位置 deletesub(SS,substr,j); //根据位置删除要被替换的子串 printf ( "现在s1为" ); //提示 printstring(*SS); //输出替换后的SS } while (i!=-1); } int main() { char ch[MAXSIZE]; string S1,S2,sub; //建立两个串 int postion,length; //位置和长度 printf ( "请输入S1\n" ); //提示 gets (ch); //输入S1的串数据 insitstring(&S1); //初始化S1 StrAssign(&S1,ch); //用输入的字符数组为S1赋值 printf ( "请输入S2\n" ); //提示 gets (ch); //输入S2的串数据 insitstring(&S2); //初始化S2 StrAssign(&S2,ch); //用输入的字符数组为S1赋值 printf ( "s1为" ); //提示 printstring(S1); //输出S1 printf ( ",长度为%d\n" ,lengthstring(&S1)); //输出S1长度 printf ( "s2为" ); //提示 printstring(S2); //输出S2 printf ( ",长度为%d\n" ,lengthstring(&S2)); //输出S2长度 if (comparestring(&S1,&S2)==0) //通过比较函数的返回值比较S1,S2是否相等 printf ( "两者相等\n" ); //提示 if (comparestring(&S1,&S2)==1) //通过比较函数的返回值比较S1,S2是否相等 printf ( "s1大\n" ); //提示 if (comparestring(&S1,&S2)==-1) //通过比较函数的返回值比较S1,S2是否相等 printf ( "s2大\n" ); //提示 //有关插入的一系列操作 printf ( "请输入你想插入的位置\n" ); //提示 scanf ( "%d" ,&postion); //输入位置 insertstring(&S1,&S2,postion); //调用插入函数 //有关连接的一系列操作 constring(&S1,&S2); //调用连接函数 printf ( "连接后的子串为" ); //提示 printstring(S1); //输出S1 printf ( ",长度为%d\n" ,lengthstring(&S1)); //输出S1现在长度 //有关截取子串的一系列操作 printf ( "截取子串\n" ); //提示 printf ( "请输入截取子串的位置\n" ); //提示 scanf ( "%d" ,&postion); //输入要截取的起始位置 printf ( "请输出字串长度\n" ); //提示 scanf ( "%d" ,&length); //输入要截取的长度 while (postion<0||length<0||postion+length-1>S1.length) //判断截取的子串是否合法 { printf ( "无法插入请重新输入\n" ); //提示 printf ( "请输入截取子串的位置\n" ); //提示 scanf ( "%d" ,postion); //重新输入位置 printf ( "请输出字串长度\n" ); //提示 scanf ( "%d" ,length); //重新输入长度 } findstring(&S2,S1,postion,length); //调用截取子串函数 printf ( "该字串为" ); //提示 printstring(S2); //有关子串删除的一系列操作 printf ( "字串删除\n" ); //提示 printf ( "首先,字串定位\n" ); //提示 postion=searchsub(&S1,S2); //调用函数寻找第一个子串位置 deletesub(&S1,S2,postion); //根据刚才的位置删除子串 printf ( "现在s1为" ); //提示 printstring(S1); //输出现在的S1 //有关子串替换的一系列操作 printf ( "把S1的子串替换为\n" ); //提示 gets (ch); //输入要替换的数据 insitstring(&sub); //初始化sub StrAssign(&sub,ch); //赋值 printf ( "替换为\n" ); //提示 printstring(sub); //打印子串 repalcesub(&S1,S2,&sub); //调用替换子串函数 return 0; } /*实验结果 请输入S1 ILIKECHINA 请输入S2 CHINA s1为ILIKECHINA ,长度为10 s2为CHINA ,长度为5 两个串的长度不一致无法比较 两个串的长度不一致无法比较 两个串的长度不一致无法比较 请输入你想插入的位置 4 插入后的串为ILICHINAKECHINA 连接后的子串为ILICHINAKECHINACHINA ,长度为20 截取子串 请输入截取子串的位置 4 请输出字串长度 4 该字串为CHIN 字串删除 首先,字串定位 字串位于第4 现在s1为ILIAKECHINACHINA 把S1的子串替换为 请重新输入 abc 替换为 abc 字串位于第7 插入后的串为ILIAKEabcCHINACHINA 现在s1为ILIAKEabcACHINA 字串位于第11 插入后的串为ILIAKEabcAabcCHINA 现在s1为ILIAKEabcAabcA 没有这个子串 */ |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通