数据结构---05---堆串---20205106009---郭睿玥

/*郭睿玥第五次算法实验作业*/

/*实验原理
     串的堆存储结构,与定长顺序串的存储结构类似,都是用一维数组地址连续的存储单元存储串
 的字符序列,不同的是堆串的存储空间是在程序执行过程中动态分配的。
     在系统中存在一个称为“堆”的自由存储区,每当建立一个新串时,可以通过动态分配函数从
 这个空间中分配一块实际串所需的存储空间,来存储新的串值。只要空间能分配成功,则在操作的
 过程中就不会发生“截断”的情况。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 @ 2021-12-25 21:19  张同光  阅读(214)  评论(0编辑  收藏  举报