数据结构 串


1.串:由零个或多个字符所组成的有限序列,称为字符串。

2.空串和空格串:空串是零个字符的串,长度为零。空格串是只包含空格的串,有长度,可以不止一个空格。

3.串的比较:比较第一个不同的字符来比较串的大小。排在前面的字符小于排在后面的字符。大写字符全部排在前面。

4.串的应用:

   计算机中常用的是ASCII编码,由八位二进制位表示一个字符,总共可以表示256个字符。后来又有了Unicode编码,常用16为二进制数表示一个字符,总共就可以表示约65万多个字符,足够表示世界上所有语言的字符了。


5.串的存储结构:

   顺序存储时分配一组连续的存储单元,实现定义固定的长度来存储串。若超过这个长度就截断。要得到串长度,可以在末尾加上一个null位表示结束,也可以在串首s[0]存储串的长度,两者都会占用一个空间,后者更为方便。

   堆分配存储表示:在堆的自由存储区里动态分配malloc(),free()一块连续的存储空间给串。

typedef struct{
  char *ch;
  int length;
}HString;

在串s的第pos个字符之前插入串T。

Status StrInsert(HString &S, int pos, HString T)
{
  if(pos<1 | pos>S.length+1) return ERROR;
  if(T.length)
  {
    if(!(S.ch= (char *)realloc(S.ch,(S.length+T.length)*sizeof(char))))
        exit(OVERFLOW);
    for(i = S.length-1; i>=pos-1; --i)//为插入T 腾出空间
        S.ch[i+T.length] = S.ch[i];
    S.ch[pos-1..pos+T.length-2] = T.ch[0..T.lenth-1];
    S.length += T.length;
  }
  return OK;
}


串的块链存储表示:每个节点只存放一个字符太过浪费,可以多个字符存在一个节点中,不足的空间存放#。

typedef struct Chunk{
   char ch[CHUNKSIZE];
   struct Chunk *next;
}Chunk;
typedef struct{
  Chunk *head, *tail;
  int curlen;
}String;

串的存储密度是串值所占的存储位/实际分配的存储位。显然,存储密度小时,运算处理方便,存储占用量大。总的来说,如果需要连接操作链式存储结构比较好,其他时候链式存储没有另外两种存储结构灵活,占用存储量大,且操作复杂。


6.朴素的模式匹配算法:子串的定位操作通常称作串的模式匹配。

返回子串T在主串S中第pos个字符之后的位置。若不存在返回0。

int Index(String S, String T, int pos)
{
  int 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;} //i要退到上次匹配首位的下一位
  }
  if(j>T[0]) return i-T[0];
  else return 0;
}

时间复杂度分析:最好就是第一次就成功了,O(1).其次就是首字母每次都不匹配,对T串的循环就不用了,这时的时间复杂度是O(n+m).最坏的情况是每一次的不匹配发生在串T的最后一个字符,时间复杂度为O((n-m+1)*m).


7.KMP模式匹配算法:根据T串的性质来决定每次循环中j退回到哪里。i从来不回退,避免重复的比较。时间复杂度是O(n+m)。

void get_next(String T, int *next)
{
  int i=1,j=0;//i表示后缀,j表示前缀
  next[1]=0;
  while(i<T[0])
  {
    if( j==0 || T[i]==T[j])
    {
      ++i;++j;
      next[i] = j;
    }
    else j = next[j];
  }
}

void get_nextval(String T, int *next)
{
  int i=1,j=0;//i表示后缀,j表示前缀
  next[1]=0;
  while(i<T[0])
  {
    if( j==0 || T[i]==T[j])
    {
      ++i;++j;
      if(T[i]!=T[j]) next[i] = j;
      else next[i] = next[j];
    }
    else j = next[j];
  }
}

理解:next数组跟T等长,其实就是规定了在T串的第j个位置发生了不匹配,j要回退到哪里。如果T串j位置前没有重复的子串,j当然要退回到1,重新匹配,但这时i不用回退也知道这期间的字符不会匹配。如果j位置前存在重复子串,就需要按next指定的位置回退到指定位置。

int Index_KMP(String S,String T,int pos)
{
  int i = pos;
  int j=1;
  int next[255];
  get_next(T,next);
  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;
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值