数据结构P3:字符串

字符串的定义和基本操作

字符串的定义和相关术语

  • 串:即字符串(String),由零个或多个字符组成的有限序列
  • 子串:串中任意个连续的字符组成的子序列
  • 主串:包含子串的串
  • 字符在主串中的位置:字符在串中第一次出现的序号
  • 子串在主串中的位置:子串的第一个字符在主串中的位置
  • 串 和 线性表:
关系:
串是一种特殊的线性表,数据元素之间呈线性关系,有位序
区别:
串的数据对象限定为字符集(各种字符)
串的基本操作对象通常为子串

字符串的基本操作

  • 赋值操作StrAssign:把串S赋值为MY
  • 复制操作StrCopy: 串S复制得到串T
  • 判空操作StrEmpty:判断串S是否为空串
  • 串长StrLength:返回串S中的字符个数即串长
  • 清空操作StrClear:将串S清为空串
  • 销毁StrDestory:将串S销毁
  • 连接Concat:串S1和串S2连接成串T
  • 子串SubString:返回串S的第pos个字符起长度为len的子串
  • 定位操作Index:返回子串Sub在主串S中的位置
  • 比较操作StrCompare:比较两个字符串的大小,如果S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0

字符串的实现(顺序存储结构)

  • 采用静态数组或者动态数组来实现串的顺序存储结构

顺序串的定义

#define MAXLEN 255              /*预定义最大串长为255*/

//静态顺序存储结构串的定义
typedef struct{                 /*顺序串的定义*/
    char ch[MAXLEN];            /*串结构体的每一个分量是字符型数据元素*/
    int len;                    /*串的当前实际长度*/
}SString;                      /*定长顺序存储*/

//动态顺序存储结构串的定义
typedef struct{                 /*顺序串的定义*/
    char ch*;                   /*按串长分配存储区,ch指针指向串的基地址*/
    int len;                    /*串的当前实际长度*/
}HString;                      /*堆分配存储*/

HString S;                                      /*声明HString结构体S*/
S.ch=(char *)malloc(MAXLEN*sizeof(char));       /*动态在内存中申请分配一片连续的存储空间,S.ch指针指向串的基地址*/
S.len=0;

字符串的基本操作

//赋值操作
bool StrAssign(SString &T,char *chars){
    int i;
    if (StrLenth(chars)>MAXLEN))
        return false;                   /*要分配的字符串长度大于字符串T的最大长度,分配失败*/
    else{
        T.ch[0]=StrLenth(chars);        /*字符串长度为要分配的字符串长度*/
        for(i=1;i<=T.ch[0];i++){
            T.ch[i]=*(chars+i-1);       /*T.ch[1]=*chars, T.ch[2]=*(chars+1),一次赋值*/
        }
        return true;
    }
}

//复制操作
bool StrCopy(SString &T,SString S){
    int i=0if (StrLenth(S)>MAXLEN)
        return false;
    else
        for (i=0;i<=StrLenth(S);i++){
            T.ch[i]=S.ch[i];
        }
        return true;
}

//判空操作
bool StrEmpty(SString S){
    if (StrLenth(S)==0)
        return true;
    else
        return false;
}

//求串长
int StrLenth(SString S){
    return S.ch[0];                         /*S[0]上存放的是串长度*/
}

//清空操作
bool StrClear(SString &S){
    if (StrLenth(S)==0)
        return false;
    else
        S.ch[0]==0;
        return true;
}

//销毁串
bool StrDestory(SString &S){
    int i;
    if (StrLenth(S)==0)
        return false;
    else{
        for(i=1;i<=StrLenth(S);i++){
            free(S.ch[i]);
        }
        StrClear(S);
        return true;
    }
}

//串连接
bool Concat(SString &T,SString S1,SString S2){
    int i;
    if(StrLenth(S1)+StrLenth(S2)<=MAXLEN){
        for(i=1;i<=StrLenth(S1);i++){
            T.ch[i]=S1.ch[i];
        }
        for(i=1;i<=StrLenth(S2);i++){
            T.ch[i+StrLenth(S1)]=S2.ch[i];
        }
        StrLenth(T)=StrLenth(S1)+StrLenth(S2);
        return true;
    }
    else
        return false;
}

字符串的特殊操作

//求子串
//返回串S的第pos个字符起长度为len的子串Sub
bool SubString(SString &Sub, SString S, int pos, int len){
    if((pos+len-1)>S.ch[0])
        return false;               /*子串越界*/
    for(i=pos;i<(pos+len);i++){
        Sub.ch[i-pos+1]=S.ch[i];
    }
    Sub.len=Sub.ch[0]=len;
    return true;
}

//比较操作
//比较两个字符串的大小,如果S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0
int StrCompare(SString S, SString T){
    for(int i=1;i<=S.ch[0] && i<=T.ch[0];i++){
        if (S.ch[i]!=T.ch(i))
            return S.ch[i]-T.ch(i);
    }
    return S.ch[0]-T.ch(0);                 /*扫描过的所有字符都相同,则返长度长的长度更大*/
}

//定位操作
//若主串S中存在与串T相同的子串,则返回它在主串S中第一次出现的位置;否则函数值为0
int Index(SString S, SString T){
    int i=1, n=StrLenth(S),m=StrLenth(T);
    SString sub;                            /*暂时存子串*/
    while(i<n-m+1){                         /*每次遍历S中m个字符,需要遍历n-m+1次*/
        SubString(sub,S,i,m);               /*返回串S的第i个字符起长度为m的子串Sub*/
        if(StrCompare(sub,T)!=0)
            ++i;
        else
            return i;                       /*返回子串在S中位置*/
    }
    return 0;                               /*S中不存在与T相等的子串*/
}

字符串的实现(链式存储结构)

//链式存储结构串的定义
typedef struct StringNode{
    char ch[4];                 /*每个结点存储多个字符,存储密度会高一些*/
    struct StringNode *next;    /*指向下一个结构体的指针*/
}StringNode,*LinkStringNode;

字符串的模式匹配算法

  • 什么是模式匹配:搜索关键字(文件、搜索引擎),即子串的定位操作
  • 术语:主串S模式串T
主串:被搜索的字符串
模式串:要搜索出的字符串
  • 字符串模式匹配:在主串中找到模式串相同的子串,并返回其所在位置
子串:主串的一部分,一定存在的
模式串:不一定能在主串中找到
ex: 主串S = “Google”。找到T = “gle”这个子串的位置。

字符串的朴素模式匹配算法

  • 朴素模式匹配算法:主串长度n,模式串长度m,将主串中所有长度为m的子串依次与模式串对比直到找到一个与模式串完全匹配的子串,或所有的子串都不匹配为止
  • 策略:比较普通比较暴力的模式匹配算法
从目标串s的第一个字符(指针i)起和模式串t的第一个字符(指针j)进行比较
若相等,则继续逐个比较后续字符;
若当前子串匹配失败,则主串指针i指向下一个子串的第一个位置(i-i+2),模式串指针j回到模式串第一个位置,直至串t 中的每个字符依次和串s的一个连续的字符序列相等,则称模式匹配成功,此时串t的第一个字符在串s 中的位置就是t 在s中的位置;
否则模式匹配不成功。
  • 复杂度:最坏的情况下,算法的时间复杂度为O(n*m) ,n和m分别为主串和模式串的长度;最好的情况下,时间复杂度为O(n)
朴素模式匹配算法的实现
//朴素模式算法
int Index(SString S,SString T){
    int i=1,j=1;
    while(i<=S.lengh && j<=T.lengh){
        if(S.ch[i]==T.ch[j]){
            ++i;
            ++j;                                /*继续比较当前子串中的后续字符*/
        }
        else{
            i=i-j+2;                            /*匹配下一个子串*/
            j=1;                                
        }
    }
    if(j>T.lengh)
        return i-T.lengh;                       /*匹配成功,返回子串的位置*/
    else
        return 0;                               /*匹配失败,返回0*/
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kxwang_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值