4.2串的表示和实现

串连接Concat(&T,S1,S2)

S1,S2为要连接的两个串,T为连接后的串

串T值产生的三种结果:

1.S1[0]+S2[0]<=MAXSTRLEN。

2.S1[0]<MAXSTRLEN,而S1[0]+S2[0]>MAXSTRLEN,则将串S2的一部分截断。

3.S1[0]=MAXSTRLEN,此时串T和S1[0]相同。


如下图所示:


代码如下所示:

Status Concat(SString &T, SString S1, SString S2)
{ 
	// 用T返回由S1和S2联接而成的新串。若未截断,则返回TRUE,否则FALSE。
	int i;
	Status uncut;
	if (S1[0] + S2[0] <= MAXSTRLEN)  // 未截断
	{
		for (i = 1; i <= S1[0]; i++) T[i] = S1[i];
		for (i = 1; i <= S2[0]; i++) T[i + S1[0]] = S2[i];
		T[0] = S1[0] + S2[0];
		uncut = TRUE;
	}
	else if (S1[0] < MAXSTRLEN)		// 截断
	{  
		for (i = 1; i <= S1[0]; i++) T[i] = S1[i];
		for (i = S1[0] + 1; i <= MAXSTRLEN; i++) T[i] = S2[i - S1[0]];
		T[0] = MAXSTRLEN;
		uncut = FALSE;
	}
	else // 截断(仅取S1)
	{                         
		for (i = 0; i <= MAXSTRLEN; i++) T[i] = S1[i];
		uncut = FALSE;
	}
	return uncut;
} // Concat
分析:

这里的MAXSTRLEN是宏,书上把他定义为255。这里,代码是比较乱,毕竟书上只提供了思路和伪代码,在此我只能说下思路。

他这个数组里面S1[0],和S2[0],保存了整个字符串长度,从S1[1],S2[1]开始才是存数据,



算法:4.3求子串SubString(&Sub,S,pos,len)

求子串过程即为复制字符串序列的过程,将串S中的从第pos个字符开始长度为len的字符序列复制到串Sub中。当参数非法是,返回ERROR

代码如下:

Status SubString(SString &Sub, SString S, int pos, int len) 
{
	// 用Sub返回串S的第pos个字符起长度为len的子串。
	// 其中,1≤pos≤StrLength(S)且0≤len≤StrLength(S)-pos+1。
	int i;
	if (pos < 1 || pos > S[0] || len < 0 || len > S[0] - pos + 1)
		return ERROR;
	for (i = 1; i <= len; i++)
		Sub[i] = S[pos + i - 1];
	Sub[0] = len;
	return OK;
} // SubString
下面来分析下:

这里的StrLength(S)意思就是S的长度。这里面len<=StrLength(S)-pos+1。大家可以举个例子,如果Strlength(S)是5,pos也是5,那么就是在第五个位置开始寻址,所以要+1。

这里的pos+i-1也差不多,大家带个数进去看看,就知道为什么要-1了。



4.2.2堆分配存储表示:

用malloc()和free()来管理。分配成功则返回起始地址指针,作为串基址。

下面是他的结构体:

typedef struct{
	char *ch;	//若是非空串,则按串长分配存储区,否则为NULL
	int length;	//串长
}HString;


算法4.3:串插入操作StrInsert(&S,pos,T)为串S重新分配大小等于串S和串T长度之和的存储科技,然后进行串值复制。

代码如下:

Status StrInsert(HString &S, int pos, HString T) 
{ 
	// 1≤pos≤StrLength(S)+1。在串S的第pos个字符之前插入串T。
	int i;
	if (pos < 1 || pos > S.length + 1)  // pos不合法
		return ERROR;
	if (T.length) {    // T非空,则重新分配空间,插入T
		if (!(S.ch = (char *)realloc(S.ch, (S.length + T.length + 1)*sizeof(char))))
			return ERROR;
		for (i = S.length - 1; i >= pos - 1; --i)  // 为插入T而腾出位置
			S.ch[i + T.length] = S.ch[i];
		for (i = 0; i < T.length; i++)         // 插入T
			S.ch[pos - 1 + i] = T.ch[i];
		S.length += T.length;
	}
	return OK;
} // StrInsert
分析:

这里的realloc当扩大堆区时,原数据没有被破坏,当比以前小了后,才会被破坏。



算法4.4:

下面的代码是对堆分配的存储结构的操作:

生成一个其值等于串常量chars的串T

 代码如下:

Status StrAssign(HString& T, char* chars)
{
	int i;
	char *c;
	if (T.ch)
		free(T.ch);
	for (i = 0, c = chars; *c; ++i, ++c);	//求chars的长度
	if (!i)
	{
		T.ch = NULL;
		T.length = 0;
	}
	else
	{
		if (!(T.ch = (char*)malloc(i*sizeof(char))))
			exit(OVERFLOW);
		for (int j = 0; i < i; j++)
		{
			T.ch[j] = chars[j];
		}
		T.length = i;
	}
	return Ok;
}


这个程序的思路就是:

把char*型变量转成HString。首先获取chars长度,在到HString里面的 char*在堆区开辟空间,然后把chars依次给T.ch【x】。



求串S的长度:

int StrLength(HString S)
{
	return S.length;
}



字符串比较:

代码如下:

int StrCompare(HString S, HString T)
{
	//S>T返>0,S=T返0,S<T返<09
	for (int 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;
}


分析下:

这里S.ch[i]-T.ch[i]这个地方是比较ASCII。前者大返回正,后者大返回负。

当某一个串比到最后,说明前面的都一样,最后看长度,如果长度一样就返回0,不一样的话,大家懂的



清空S串:

代码如下:

Status ClearString(HString& S)
{
	if (S.ch)
	{
		free(S.ch);
		S.ch = NULL;
	}
	S.length = 0;
	return Ok;
}



4.23串的块链存储表示:

每个结点可以存放一个字符,或者存放多个字符

也可以是结点大小为1的链表

如下图所示:


为了便于进行串的操作,当以链表存储串时,除头指针外还可以附设一个尾指针指示链表中的最后一个结点,并给出当前串的长度。称如此定义的串存储结构为块链结构,说明如下:

#define CHUNKSZIE 80
typedef struct Chunk{
	char ch[CHUNKSZIE];
	struct Chunk* next;
}Chunk;
typedef struct{
	Chunk* head, *tail;		//串头和串尾指针
	int curlen;		//串的当前长度
}LString;


下面是一个存储密度的概念:


存储密度=串值所占的存储位/实际分配的存储位


密度小:运算处理方便,存储占用大

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

IT1995

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

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

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

打赏作者

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

抵扣说明:

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

余额充值