串的概述
串是一种特殊的线性结构,他的数据元素仅由一个字符组成
串(String) : 是由零个或多个任意字符串组成的有限序列.
子串(SubString): 串中任意连续字符组成的子序列
主串: 包含子串的串称为主串。
字符在串中的序号表示该字符在串中的位置
字串的第一个字符在主串中的序号称为子串的位置
串相等: 当且仅当两个串的长度相等且对应位置上的字符都相等
串的表示和实现
串的顺序表示
用一组地址连续的存储单元存储字符串
一般采用动态数组实现
#define INITSIZE 128
#define INCRE 20
typedef struct
{
char * data;
int length;
int stringsize;
}SqString;
int InitString(SqString *s)
{
s->data = (char *)malloc(sizeof(char)*INITSIZE);
if (!s->data) return ERROR;
s->length = 0;
s->stringsize = INITSIZE;
return OK;
}
int StrLength(SqString *s)
{
return s->length;
}
int StrEmpty(SqString *s)
{
if (s->length == 0) return OK;
else return ERROR;
}
int StrAssign(SqString *S , char *str)
{
int i = 0;
while (*str)
{
S->data[i++] = *str++;
}
S->data[i] = '\0';
S->length = i;
return OK;
}
int StrCopy(SqString *S,SqString *T)
{
int i = 0;
S->length = T->length;
while (i<T->length)
{
S->data[i] = T->data[i++];
}
S->data[i] = '\0';
return OK;
}
int StrCompare(SqString *S, SqString *T)
{
int i = 0;
for (i = 0; i < S->length&&i < T->length; i++)
{
if (S->data[i] != T->data[i])
{
return S->data[i] - T->data[i];
}
}
return S->length - T->length;
}
int SubString(SqString *Sub, SqString *S , int pos , int len)
{
int i;
if (pos<1 || pos>S->length || len<0 || len>S->length - pos + 1)
return ERROR;
Sub->length = 0;
for (i = 0; i < len; i++)
{
Sub->data[i] = S->data[pos-1+i];
}
Sub->data[i] = '\0';
return OK;
}
int StrConcat(SqString *S , SqString *s1 , SqString *s2)
{
int i = 0, j = 0;
if (s1->length + s2->length >= S->stringsize)
{
S->data = (char *)realloc(S->data, (S->stringsize + INCRE) * sizeof(char));
if (!S->data) return ERROR;
S->stringsize += INCRE;
}
while (i < s1->length)
{
S->data[i] = s1->data[i++];
}
while (j < s2->length)
{
S->data[i++] = s2->data[j++];
}
S->data[i] = '\0';
S->length = s1->length + s2->length;
return OK;
}
串的链式存储表示
每个节点可以可以存放一个字符,也可以存放多个字符
当以链表存储串值时,除头指针外可增设一个尾指针指示链表的最后一个节点,
并给出当前串的长度. 称为快链结构
#define NODESIZE 20
typedef struct Node
{
char char[NODESIZE];
struct Node * next;
}Node;
typedef struct Link
{
Node *head ,*tail;
int curlen;
}Link;
模式匹配
串的模式匹配,即子串定位, 子串首次出现在主串的位置;
若s="abcdede" , t="de" , 则模式t在主串中的序号为5;
1.蛮力法(Brute Force,BF算法):
按照自左向右的顺序,从主串的第start个字符起和模式串的第一个字符比较,若
相等,则继续逐个比较后续字符;否则从主串的第start+1个字符起重新和模式的字符比较.以此类推,
直到模式串t中的每个字符依次和主串s中的一个连续字符序列相等,则匹配成功;否则失败
int IndexBF(SqlString *s,SqlString *t, int start)
{
int i=start-1 , j=0;
while(i<s->length && j<t->length)
{
if(s->data[i] ==t->data[j])
{
i++;
j++;
}else{
i=i-j+1;
j=0;
}
}
if(j==t->length) return i-j+1;
else return -1;
}
KMP 算法
BF算法效率低的原因是i和j的回溯, 即在某趟的匹配过程中失败后,对于s串要回溯到本躺开始字符的下一个
字符,这些回溯并不是完全必要的;