堆串的C语言实现(数据结构)

和上一篇定长度顺序实现差不多,都是用一块连续的内存地址来存储字节数据,唯一不同的在于堆串的内存是动态申请的,利用了C语言中的malloc、free、realloc函数。此类函数管理了内存中一块儿叫做自由存储区——”堆“的地方。因此该种形式的串实现被称作堆串。

实现思路和定长的静态串差不多。

在实现中遇到的问题:

1.静态串中第一个元素存储的是该串的总长度,后续的内存用来存内容。因此,真正的字符串顺序和其在数组中的下标一致。而在堆串之中,用一个结构体来表示堆串类型,结构体中有描述堆串长度的量,故在堆串中数组下标和字符序数会相差1。在实现时应当注意这一点。

2.由于堆串中Concat的实现特点,不能直接进行Concat(&S,S,T)的操作。 需要一个临时变量tmp,首先进行Concat(&tmp,S,T),然后StrCopy(&S,tmp)来完成和静态串中Concat(&S,S,T)相同的效果。具体请看实现。

HeapString.h头文件

#ifndef HEAPSTRING_H_INCLUDED
#define HEAPSTRING_H_INCLUDED
//串的堆分配主要依靠malloc和rellaoc以及free等函数实现
//在C语言中,存在一个称为”堆“的自由存储区,并由malloc()和free()来管理。
//若空间分配成功,返回的地址作为串的基址,当空间超过时

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"Status.h"

//PS:在堆串中,串描述主体为一结构体
typedef struct
{
    char* ch;  //串的基地址
    int length;  //串的长度
}HString;


//函数列表

void InitString_H(HString* S);
//初始化S为空串

Status StrAssign_H(HString *T, char* chars);
//生成一个其值等于常量chars的串T

Status StrCopy_H(HString *T,HString S);
//由串S复制得到串T

Status StrEmpty_H(HString S);
//判空

Status StrCompare_H(HString S,HString T);
//比较字符串,若S>T,返回1  若S==T,返回0  若S<T,返回-1

int StrLength_H(HString S);
//求串长

Status ClearString_H(HString *S);
//清空

Status Concat_H(HString* T , HString S1 , HString S2);
//用T返回由S1和S2链接而成的新串

Status SubString_H(HString* Sub,HString S,int pos,int len);
//返回子串

int Index_H(HString S,HString T,int pos);
//返回从pos开始第一次子串T出现的序号,找到则返回0

Status Replace_H(HString *S,HString T ,HString V);
//用V来替换S中所有的不重叠的T子串

Status StrInsert_H(HString *S,int pos,HString T);
//在第pos个位置之前插入子串T

Status StrDelete_H(HString* H,int pos , int len);
//删除第pos个位置开始的len个字符

void DestroyString_H(HString* S);
//销毁

void ShowString_H(HString S);
//打印串


#endif // HEAPSTRING_H_INCLUDED

具体实现:HeapString.c

#include"HeapString.h"

void InitString_H(HString* S)
{
    (*S).ch = NULL;
    (*S).length = 0;
}

Status StrAssign_H(HString *T, char* chars)
{
    int charsLength = strlen(chars);
    (*T).ch = (char*)malloc(sizeof(char)*charsLength);
    if(!((*T).ch))
    {
        return ERROR;
    }
    int i;
    for( i=0; i<charsLength; i++)
    {
        (*T).ch[i] = chars[i];
    }
    (*T).length = charsLength;
    return SUCCESS;

}

Status StrCopy_H(HString *T,HString S)
{
    (*T).length = S.length;
    (*T).ch = (char*)malloc(S.length*sizeof(char));
    if(!(*T).ch)
    {
        printf("未申请到堆空间!\n");
        return ERROR;
    }
    int i;
    for(i = 0;i<S.length;i++)
    {
        (*T).ch[i] = S.ch[i];
    }
    return SUCCESS;
}

Status StrEmpty_H(HString S)
{
    if(S.length == 0)
    {
        return YES;
    }
    else
    {
        return FALSE;
    }
}

Status StrCompare_H(HString S,HString T)
{
    int count = 0;

    while(count<S.length&&count<T.length&&S.ch[count]==T.ch[count])
    {
        count++;

    }//循环退出情况:超过任意一个字符串的长度、当下的两个字符比较不相等

    if(count==T.length&&count == S.length)
    {
        return 0;
    }

    if(count==T.length)
    {
        return 1;
    }
    if(count == S.length)
    {
        return -1;
    }

    if(S.ch[count]>T.ch[count])
    {
        return 1;
    }
    else
    {
        return -1;
    }

}


Status ClearString_H(HString *S)
{
    (*S).length = 0;
    (*S).ch = (char *)realloc((*S).ch,0);    //是否能够直接释放已经分配的所有空间呢?

    return SUCCESS;

}

Status Concat_H(HString* T , HString S1 , HString S2)
{
    int i = 0;
    (*T).length = S1.length + S2.length;
    (*T).ch = (char*)malloc((S1.length+S2.length)*sizeof(char));
    for( ; i<S1.length ; i++)
    {
        (*T).ch[i] = S1.ch[i];
    }

    for( ; i<(*T).length ; i++)
    {
        (*T).ch[i] = S2.ch[i-S1.length];
    }
    return SUCCESS;



}

Status SubString_H(HString* Sub,HString S,int pos,int len)
{
    if(pos+len-1 > S.length)
    {
        printf("主串没有这么长!\n");
        return ERROR;
    }
    (*Sub).length = len;
    (*Sub).ch = (char*)malloc(sizeof(char)*len);
    if((*Sub).ch == NULL)
    {
        printf("分配内存失败!\n");
        return ERROR;
    }

    int i = pos - 1;
    for( ; i<=pos-1+len-1; i++)
    {
        (*Sub).ch[i-pos+1] = S.ch[i];
    }
    return SUCCESS;
}

int Index_H(HString S,HString T,int pos) //注意:该函数返回下标
{
    int i = pos - 1;
    HString Sub;
    if(T.length > S.length - pos +1)
    {
        printf("待寻子串不能长于目标主串!\n");
        return -1;
    }
    for ( ;i <= S.length - T.length ;i++ ) //从pos-1位置一直到最后能到达的位置
    {
         SubString_H(&Sub,S,i+1,T.length);
         if(!StrCompare_H(Sub,T))
         {
             return i;
         }
    }

    return -1;
}



Status StrInsert_H(HString *S,int pos,HString T)
{
   HString tmp ;
   SubString_H(&tmp,*S,1,pos-1); //先生成前面的字符串

   HString tmp1;
   Concat_H(&tmp1,tmp,T);

   ClearString_H(&tmp);  //将临时变量置空以重用
   HString tmp2;
   SubString_H(&tmp,*S,pos,(*S).length-pos+1);

   Concat_H(&tmp2,tmp1,tmp);


   StrCopy_H(S,tmp2);

   DestroyString_H(&tmp2);
   DestroyString_H(&tmp1);
   DestroyString_H(&tmp);


}


Status Replace_H(HString *S,HString T ,HString V)
{
    HString tmp,stringTmp;
    InitString_H(&tmp);
    HString tmp1;
    int i = 1 , qi = 1;
    while(1)
    {
        i = Index_H(*S,T,qi)+1;             //注意:index返回的是下标,这里让其增加1返回为序数
        if(i == 0)
        {
            SubString_H(&stringTmp,*S,qi,(*S).length-qi+1);

            Concat_H(&tmp1,tmp,stringTmp);
            StrCopy_H(&tmp,tmp1);
            ClearString_H(&tmp1);


            StrCopy_H(S,tmp);

            return SUCCESS;
        }
        SubString_H(&stringTmp,*S,qi,i-qi);
        ShowString_H(stringTmp);

        Concat_H(&tmp1,tmp,stringTmp);
        StrCopy_H(&tmp,tmp1);
        ClearString_H(&tmp1);



        Concat_H(&tmp1,tmp,V);
        StrCopy_H(&tmp,tmp1);
        ClearString_H(&tmp1);
        i = i+ T.length;  //i指向下一个pos
        qi = i;

    }


}


Status StrDelete_H(HString* S,int pos , int len)
{
    HString tmp,stringTmp;

    HString tmp1; // 中间变量
    InitString_H(&tmp);
    SubString_H(&stringTmp,*S,1,pos-1);

    Concat_H(&tmp1,tmp,stringTmp);
    StrCopy_H(&tmp,tmp1);
    ClearString_H(&tmp1);

    SubString_H(&stringTmp,*S,pos+len,(*S).length-pos-len+1);
    Concat_H(&tmp1,tmp,stringTmp);
    StrCopy_H(&tmp,tmp1);
    ClearString_H(&tmp1);
    StrCopy_H(S,tmp);



}
void ShowString_H(HString S)
{
    if(S.length == 0)
    {
        printf("S is empty! Nothing to show!\n");
        return ;
    }
    int i;
    for( i=0 ; i<S.length ; i++)
    {
        printf("%c",S.ch[i]);
    }
    printf("\n");
}

void DestroyString_H(HString* S)
{
    ClearString_H(S);
    free(&((*S).length));
    free(S);
}

具体的测试函数大家可以自己写一写,欢迎大家使用该实现方法,如有bug请及时联系我。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值