数据结构之串与数组(C语言)

串的基本操作:
假设有一个顺序串定义如下:

#define MAXSIZE 100
typedef struct
{
	char ch[MAXSIZE];
	int len;
}seqstr;
seqstr* S;

1.串的连接运算:

seqstr* Strcat(seqstr* s, seqstr* t)
{
	int i;
	seqstr* r;
	printf("s = %s,t = %s\n", s->ch, t->ch);
	if ((s->len + t->len) > MAXSIZE)printf("上溢\n");
	else
	{
		for (i = 0; i < s->len; i++)r->ch[i] = s->ch[i];
		for (i = 0; i < t->len; i++)r->ch[s->len + i] = t->ch[i];
		r->ch[s->len + i] = '\0';
		r->len = s->len + t->len;
	}
	printf("r = %s\n", r->ch);
	return r;
}//最后生成的串r为s+t的结果

2.求子串运算:

seqstr* Substr(seqstr* s, int i, int j)
{
	int k;
	seqstr* t;
	printf("s = %s\n",s->ch);
	if (i + j - 1 > s->len)printf("超界\n");
	else
	{
		for (k = 0; k < j; k++)t->ch[k] = s->ch[i + k - 1];
		t->len = j;
		t->ch[t->len] = '\0';
	}
	printf("t = %s\n",t->ch);
	return t;
}

3.子串定位(串的模式匹配):
在串 s 中找出一个与串 t 相同的子串,一般把串s成为目标,把串 t 成为模式,若在目标 s 中找到模式t则模式匹配成功,找不到则模式匹配失败。
朴素的模式匹配算法

int Index(seqstr* s, seqstr* t)
{
	int i = 1, j = 1;
	while ((i <= s->len) && (j <= t->len))
	{
		if (s->ch[i - 1] == t->ch[j - 1])
		{
			i++; j++;
		}
		else
		{
			i = i - j + 2; j = 1;
		}
	}
	if (j > t->len)return (i - t->len);//匹配成功
	else return -1;//匹配失败
}

时间复杂度的分析:
1.最好的情况,每次不成功的匹配都发生在 t 的第一个字符与 s 中的字符的比较时,设从 s 的第 i 个字符开始匹配,成功的概率为 pi,则在之前一共比较了(i-1)次。若在第i趟成功的匹配中匹配了 m 次,则总的比较次数为(i-1+m)次。
∑pi(i-1+m) = [1/(n-m+1)]∑(i-1+m) = 1/2(n+m) ( i 的取值从1 到 n-m+1)
由此,最好情况下算法的平均时间复杂度为O(n+m)
2.最坏的情况,每一次不成功的匹配都发生在t的最后一个字符与s中相应字符的比较时,新一趟的起始位置为 i-m+2,若在第i趟匹配成功,则在之前一共匹配了(i-1)趟,每趟m次,再加上第i次的比较,一共比较了(im)次。
∑pi(i
m) = m/(n-m+1)∑i = (m/(n-m+1)× 1/2 ×(n-m+1)×(n-m+2) = m(n-m+2)/2
由于n>>m,最坏情况下算法的时间复杂度为O(m×n)

链式存储结构下的模式匹配算法:

linkstr* Index(linkstr* s, linkstr* t)
{
	linkstr* first, * sr, * er;
	first = s;
	sr = first; er = t;
	while (sr && er)
	{
		if (sr->data == er->data)
		{
			sr = sr->next;
			er = er->next;
		}
		else
		{
			first = first->next;
			sr = first;
			er = t;
		}
	}
	if (er == NULL)return(first);
	else return NULL;
}

关于改进的模式匹配算法
当一趟匹配过程中出现字符比较不相等时,不再回溯 i 值,而是利用部分匹配的结果将模式向右移一段距离后,继续进行比较。
这样算法的时间复杂度为O(n+m)。

void GetNext(seqstr* t, int next[])
{
	int j, k;
	j = 1, k = 0;
	next[1] = 0;
	while (j < t->len)
	{
		if ((k == 0) || (t->ch[j - 1] == t->ch[k - 1]))
		{
			j++; k++; next[j] = k;
		}
		else k = next[k];
	}return;
}//得到模式串t的值,并存入数组

int Index(seqstr* s, seqstr* t)
{
	int i = 1, j = 1;
	while ((i <= s->len) && (j <= t->len))
	{
		if ((j == 0) || (s->ch[i - 1] == t->ch[j - 1]))
		{
			i++; j++;
		}
		else j = next[j];
	}
	if (j < t->len)return(i - t->len);
	else return -1;
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值