第四章------------------串

字符串是最基本的非数值数据,字符串是一种特定的线性表,其特殊性在于组成线性表的每个元素就是一个单字符。
串的存储结构
(1)定长顺序串:定长顺序存储表示:用一组地址连续的存储单元存储串值的字符序列

#define MaxSize 255//预定义最大串长为255
typedef struct {
    char ch[MaxSize];//每个分量存储一个字符
    int length;//串的实际长度
}SString;
//在串s中下标为pos的字符之前插入串t
int StrInsert(SString* s, int pos, SString t) {
	int i;
	if (pos<0 || pos>s->length)//插入位置不合法
		return (0);
	if (s->length + t.length <= MaxSize) {//插入后串长<=MaxSize
		for (i = s->length + t.length - 1; i >= t.length + pos; i--)
			s->ch[i] = s->ch[i - t.length];
		for (i = 0; i < t.length; i++)
			s->ch[i + pos] = t.ch[i];
		s->length = s->length + t.length;
	}
	else if (pos + t.length <= MaxSize) {//插入后串长>MaxSize,但串t的字符序列可以全部插入
		for (i = MaxSize - 1; i > t.length + pos - 1; i--)
			s->ch[i] = s->ch[i-t.length];
		for (i = 0; i < t.length; i++)
			s->ch[i + pos] = t.ch[i];
		s->length = MaxSize;
	}
	else {//插入后串长>MaxSize,但串t的部分字符也要舍弃
		for (i = 0; i < MaxSize - pos; i++)
			s->ch[i + pos] = t.ch[i];
		s->length = MaxSize;
	}
	return (1);
}
//顺序串删除函数,在串s中删除从下标pos起len个字符
int StrDelete(SString* s, int pos, int len) {
	int i;
	if (pos<0 || pos>(s->length - len))//删除参数不合法
		return (0);
	for (i = pos + len; i < s->length; i++)
		s->ch[i - len] = s->ch[i];//从pos+len开始至串依次向前移动,实现删除len个字符
	s->length = s->length - len;//s串长减len
	return (1);
}
//串比较函数,若串s和t相等返回0,若s>t则返回正数,若s<t则返回负数
int StrCompare(SString s, SString t) {
	int i;
	for (i = 0; i < s.length && i < t.length; i++)
		if (s.ch[i] != t.ch[i])
			return (s.ch[i] - t.ch[i]);
	return (s.length - t.length);
}

//串的实际长度只能小于等于MaxSize,超过预定义长度的串值会被舍去,称为截断
(2)堆串:堆分配存储仍然是以一组地址连续的存储单元存放串值的字符序列,但它们的存储空间是在程序执行过程中动态分配得到的。

typedef struct {
    char* ch;//按串长分配存储区,ch指向串的基地址
    int length;//串的长度
}HString;
//在串s下标为pos的字符之前插入串t
int StrInsertd(HString* s, int pos, HString* t) {
	int i;
	char* temp;
	if (pos < 0 || pos>s->length || s->length == 0)//插入位置不合法
		return (0);
	temp = (char*)malloc(s->length + t->length);//动态产生足够的空间存放插入后的串
	if (temp == NULL)
		return (0);
	for (i = 0; i > pos; i++)
		temp[i] = s->ch[i];
	for (i = 0; i < t->length; i++)
		temp[i + pos] = t->ch[i];
	for (i = pos; i < s->length; i++)
		temp[i + t->length] = s->ch[i];
	s->length += t->length;
	free(s->ch);
	s->ch = temp;
	return(1);
}
//堆串赋值函数
int StrAssign(HString* s, char* tval) {
	//将字符串常量tval的值赋给堆串s
	int len, i = 0;
	if (s->ch != NULL)
		free(s->ch);
	while (tval[i] != '\0')
		i++;
	len = i;
	if (len) {
		s->ch = (char*)malloc(len);
		if (s->ch == NULL)
			return (0);
		for (i = 0; i < len; i++)
			s->ch[i] = tval[i];
	}
	else
		s->ch = NULL;
	s->length = len;
	return(1);
}
//堆串删除字符串:删除字符串S中从pos位置开始的len长度子串
void StrDelete(HString* S, int pos, int len)
{
    //判断是否不满足删除条件
    if (pos<0 || pos>S->length)
        return;
    if (len <= 0 || len > S->length)
        return;
    int j = pos; //设置开始删除的位置
    //将pos+len处及其之后的字符全部往前移动len长度,通过覆盖实现删除
    for (int i = j + len; i < S->length; ++i)
    {
        S->ch[i - len] = S->ch[i];
    }
    //修改删除后S的长度
    S->length -= len;
}

(3)块链串

typedef struct StringNode {
    char ch;//每个结点存一个字符
    struct StringNode* next;
}StringNode,*String;
typedef struct Stringnode {
    char ch[4];//每个结点存四个字符
    struct Stringnode* next;
}Sstringnode,*Sstring;

简单模式匹配算法思想:从主串S的第pos个字符开始,和模式串T的第一个字符开始比较,如果相等,就继续比较后续字符,如果不等,则从主串S的第pos+1个字符开始重新和模式串T比较,直到模式串T中的每个字符和主串S中的一个连续字符子序列全部相等,则称匹配成功,返回和T中第一个字符相等的字符在主串S中的位置;或者主串中没有和模式串相等的字符序列,则称匹配不成功。
实现时设i,j,start三个指示器:
i指向主串S中当前比较的字符,起始指向S的首字符,此后,每比较一步,后移一个位置,一趟匹配失败时,回溯到该趟比较起点的下一个位置。
j指向子串T中当前比较的字符,起始指向T的首字符,此后,每比较一步,后移一个位置,一趟匹配失败时,回溯到T的首字符处。
start记录每趟比较时在主串S中的起点,每趟比较后,后移一个位置,以便确定下一趟的起始位置。

//求主串S的下标pos起,串t第一次出现的位置,成功返回位置序号,不成功返回-1
int StrIndex(SString S,int pos, SString T) {
    int i, j,start;
    if (T.length == 0)//当模式串为空串时,是任意串的匹配串
        return (0);
    start = pos; i = start; j = 0;//主串从pos开始,模式串从头(0)开始
    while (i < S.length && j < T.length) {
        if (S.ch[i] == T.ch[j]) {//当前对应字符相等时推进
            ++i;
            ++j;
        }
        else {//当前对应字符不等时回溯
            start++;
            i = start;//主串从start+1开始,模式串从头(0)开始
            j = 0;
        }
    }
    if (j >=T.length)
        return (start);//匹配成功时,返回匹配起始位置
    else
        return -1;//匹配不成功时,返回-1
}

主串长度为n,模式串长度为m:
简单模式匹配最好的情况是每个子串的第一个字符就匹配失败O(n-m+1)=O(n)
简单模式匹配最坏的情况是每个子串都要对比m个字符,共n-m+1个子串,时间复杂度:O((n-m+1)*m)=O(nm)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值