数据结构---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
没有这个子串
*/

 

posted @   张同光  阅读(239)  评论(0编辑  收藏  举报
编辑推荐:
· 基于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最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示