数据结构基础与算法图解(5)——串

5 串

5.1 串的逻辑结构

  • 串时有限长的字符序列,由一对单括号相括,如’a string’

  • 串的逻辑结构与线性表相似,区别仅在于串的数据对象约束为字符集

  • 串的基本操作和线性表有很大差别:

    在线性表的基本操作中,大多以“单个元素”作为操作对象;

    在串的基本操作中,通常以“串的整体”作为操作对象。

ADT String{
数据对象:
D={ai|ai∈CharacterSet, i=1,2,....,n, n>=0}
数据关系:
R1={<ai-1,ai>|ai-1,ai∈D,i=2,....,n}
基本操作:
StrAssign(&T,chars)
DestroyString(&S)
StrCopy (&T, S)                 
StrLength(S)
StrCompare (S, T)             
Concat (&T, S1, S2)
StrEmpty (S)                    
SubString (&Sub, S, pos, len)
ClearString (&S)              
Index (S, T, pos)
Replace (&S, T, V)           
StrInsert (&S, pos, T)
StrDelete (&S, pos, len)
}ADT String

5.1.1 例题

  1. 串的数据对象约束为 字符集
  2. 空串‘’的长度为零
  3. 在串的基本操作中,通常以 串的整体 作为操作对象
StrAssign (&T, chars)
  初始条件:chars 是字符串常量。
  操作结果:把 chars 赋为 T 的值。
StrCopy (&T, S)
  初始条件:串 S 存在。
  操作结果:由串 S 复制得串 T。
DestroyString (&S)
  初始条件:串 S 存在。
  操作结果:串 S 被销毁。
StrEmpty(S)
  初始条件:串S存在。
  操作结果:若 S 为空串,则返回TRUE,否则返回 FALSE。
 ('' 表示空串,空串的长度为零。)
StrCompare(S,T)
   初始条件:串 S 和 T 存在。
   操作结果:
    若S > T,则返回值 > 0; 
    若S = T,则返回值 = 0; 
    若S < T,则返回值 < 0 。
例如:StrCompare('data', 'state') < 0
            StrCompare('cat', 'case') > 0
StrLength(S)
  初始条件:串 S 存在。
  操作结果:返回 S 的元素个数, 称为串的长度。
Concat(&T,S1,S2)
  初始条件:串 S1 和 S2 存在。
  操作结果:用 T 返回由 S1 和 S2联接而成的新串。
例如: Concat( T, 'man', 'kind')
          求得  T = 'mankind'
    
SubString (&Sub, S, pos, len)
初始条件:
串 S 存在,1≤pos≤StrLength(S),且0≤len≤StrLength(S)-pos+1。
操作结果:        
用 Sub 返回串 S 的第 pos 个字符起长度为 len 的子串,子串为“串” 中的一个字符子序列。

Index (S, T, pos)
 初始条件:串S和T存在,T是非空串,1≤pos≤StrLength(S)。  操作结果: 若主串 S 中存在和串 T 值相同的子串, 则返回它在主串 S 中第pos个字符之后第一次出现的位置;否则函数值为0。
( “子串在主串中的位置”意指子串中的第一个字符在主串中的位序。)
假设 S = 'abcaabcaaabc',  T = 'bca' 
Index(S, T, 1) = 2Index(S, T, 3) = 6Index(S, T, 8) = 0

5.1.2 例题

  1. Concat( T, ‘human’, ‘bing’), 求得 T = ‘humanbing’ 。
  2. SubString( sub, ‘discovery’, 4, 5), 求得 sub = ‘cover’。
  3. 假设 S = ‘alphaphazero’, T = ‘pha’ , Index(S, T, 2) = 3。
  4. 假设 S = ‘alphaphamaster’,
    StrDelete (&S, 6, 3), 则S= ‘alphamaster’。
  5. 若串S1=‘ABCDEFG’,S2= '1223’,S3=‘###’,执行Substring(&Sub, S1, Strlength(S3) ,Index(S2, ‘2’,1)),
    则Sub= ‘CD’。

5.2串的定长顺序表示

#define MAXSTRLRN 255
//用户可在255内定义最大串长
typedef unsigned char SString [MAXSTRLEN+1];
//0号单元存放串的长度


Status Concat(SString S1,SString S2,SString &T){
    //用T返回S1和S2联结而成的新串。若未截断,则返回TRUE,否则返回Flase
    if(S1[0]+S2[0]<=MAXSTRLEN){//未截断
        T[1...S1[0]]=S1[1....S1[0]];
        T[S1[0]+1...S1[0]+S2[0]]=S2[1...S2[0]];
        T[0]=S1[0]+S2[0];
        uncut=TRUE;
    }
    else if(S1[0]<MAXSTRLEN)//截断
    {
        T[1...S1[0]]=S1[1..S1[0]];
        T[S1[0]+1...MAXSTRLEN]=S2[1...MAXSTRLEN-S1[0]];
        T[0]=MAXSTRLEN;
        uncut=FALSE;
}
    else{
        T[0...MAXSTRLEN]=S1[0...MAXSTRLEN];
        uncut=FALSE;
    }
    return uncut;
}//Concat

5.3 串的堆分配存储表示

typedef struct{
    char *ch;  //若是非空串,则按串长分配存储区,否则ch为NULL
    int length;  //串长度
}Hstring
    
Status Concat(HString &T, HString S1, HString S2) {  // 用T返回由S1和S2联接而成的新串
   if (T.ch)  free(T.ch);        // 释放旧空间
   if (!(T.ch = (char *)  
             malloc((S1.length+S2.length)*sizeof(char))))
         exit (OVERFLOW);
   T.ch[0..S1.length-1] = S1.ch[0..S1.length-1];
   T.length = S1.length + S2.length;
   T.ch[S1.length..T.length-1] = S2.ch[0..S2.length-1];
   return OK;
} // Concat

 Status SubString(HString &Sub, HString S, int pos, int len) {
                               // 用Sub返回串S的第pos个字符起长度为len的子串
   if (pos < 1  ||  pos > S.length  ||  len < 0  ||  len > S.length-pos+1)  
       return ERROR;
   if (Sub.ch)  free (Sub.ch);             // 释放旧空间
   if (!len)   { Sub.ch = NULL;  Sub.length = 0; }        // 空子串
   else {  Sub.ch = (char *)malloc(len*sizeof(char));
              Sub.ch[0..len-1] = S[pos-1..pos+len-2];
              Sub.length = len;  }        // 子串的长度
   return OK;
} // SubString


5.4 串的块链存储表示

5.4.1 用链表存储串

也可用链表来存储串值,由于串中的每一个字符是只有 8 位的二进制数,因此用链表存储串时,通常一个结点中存放的不是一个字符,而是一个子串。
存储密度 = 数据元素所占存储位/实际分配的存储位
存储密度小,处理方便,但是存储量大。

#define  CHUNKSIZE  80  // 可由用户定义的块大小
  typedef  struct Chunk {  // 结点结构
    char  ch[CUNKSIZE];
    struct Chunk  *next;
  } Chunk;
  typedef struct {  // 串的链表结构
    Chunk *head, *tail; // 串的头和尾指针
     int   curlen;     // 串的当前长度
  } LString;


5.5 串的模式匹配*

5.5.1 一般算法

在这里插入图片描述

int Index(SStirng S,SString T,int pos){
i=pos;
j=1;
    while(i<=S[0]&&j<=T[0]){
        if(S[i]==T[j]){++i;++j;}//继续比较后继字符
        else{
            i=i-j+2;  //指针后退重新开始匹配
            j=1;}
    }
    if(j>T[0])return i-T[0];
    else return 0;
}


5.5.2 KMP

在这里插入图片描述
在这里插入图片描述

KMP算法的时间复杂度可以达到O(m+n), 基本思想是每当字符比较不等时,不需回溯i指针,而是利用已经得到的“部分匹配的结果”将模式向右“滑动”尽可能远的距离,继续进行比较。

int Index_KMP(SString S, SString T, int pos)
{ // 1≤pos≤StrLength(S)
     i = pos;   j = 1;
     while (i <= S[0] && j <= T[0]) {
         if (j = 0 || S[i] == T[j]) { ++i;  ++j; } // 继续比较后继字符
         else  j = next[j];         // 模式串向右移动
     }
    if (j > T[0])  return  i-T[0];    // 匹配成功
    else return 0;
} // Index_KMP

 void get_next(SString &T, int &next[] ) {
     // 求模式串T的next函数值并存入数组next
     i = 1;   next[1] = 0;   j = 0;
      while (i < T[0]) {
           if (j = 0 || T[i] == T[j])
                 {++i;  ++j; next[i] = j; }
           else  j = next[j];
      }
    } // get_next


void get_nextval(SString &T, int &nextval[]) {
      i = 1;   nextval[1] = 0;   j = 0;
      while (i < T[0]) {
          if (j = 0 || T[i] == T[j]) {
              ++i;  ++j;
              if (T[i] != T[j])  nextval[i] = j;
              else  nextval[i] = nextval[j];
         }
        else  j = nextval[j];
     }
  } // get_nextval

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

zyw2002

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

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

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

打赏作者

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

抵扣说明:

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

余额充值