C语言数据结构(六),串

《C语言数据结构》严蔚敏,吴伟民版。

上章内容链接:https://blog.csdn.net/daqino1/article/details/88833633

以下内容为串

串或字符串(Sting): 由零个或者多个字符组成的有限序列。
串长度:串中字符的数目n,称为串的长度。
空串:零个字符的串。
子串:串中任意个连续的字符组成的子序列。
主串:包含子串的的串。
空格串(blank string):由一个或多个空格组成的串。

//--------------------------串的抽象数据类型-----------------------------------
ADT String {
	// 生成一个其值等于chars的串T
	StrAssign(&T, chars);
	// 由串S复制得到串T
	StrCopy(&T, S);
	// 若S为空串,则返回TRUE,否则返回FALSE
	StrEmpty(S);
	// 若S > T, 则返回值 > 0;若S = T,则返回值 = 0;若S < T,则返回值 < 0
	StrCompare(S, T);
	// 返回S的元素个数, 即串的长度
	StrLength(S);
	// 将S清为空串
	ClearString(&S);
	// 用T返回由S1和S2联接而成的新串
	Concat(&T, S1, S2);
	// 用Sub返回串S的第pos个字符起长度为len的子串
	SubString(&Sub, S, pos, len);
	/* 若主串S中存在和串T值相同的子串, 则返回它在主串S中第pos个字符之后第一次出现的位置;否则函数值为0*/
	Index(S, T, pos);
	// 用V替换主串S中出现的所有与T相等的不重叠的子串
	Replace(&S, T, V);
	// 在串S的第pos个字符之前插入串T
	StrInsert(&S, pos, T);
	// 从串S中删除第pos个字符起长度为len的子串
	StrDelete(&S, pos, len);
	// 串S被销毁
	DestroyString(&S);
}

串分三种存储表示:定长顺序存储,堆分配存储,块链存储表示。
块链存储需要考虑存储密度:存储密度 = 串值所占的存储位 / 实际分配的存储位

串的定长顺序存储表示如下:

#define MAXSTRLEN 255 // 用户可在255以内定义最大串长
typedef unsigned char SString[MAXSTRLEN + 1]; // 0号单元存放串的长度

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

	return uncut;
}

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

串的堆分配存储表示如下:

//-------------------------------------串的堆分配存储表示----------------------------------------
typedef struct {
	char *ch;   // 若是非空串,则按串长废品存储区,否则ch为NULL
	int length; // 串长度
}HString;

//------------------------------------基本操作的函数原型说明-------------------------------------
// 把字符串T插入到字符串S的pos位置
Status StrInsert(HString &S, int pos, HString T);
// 生成一个其值等于串常亮chars的串T
Status StrAssign(HString &T, char* chars);
// 返回S的元素个数,称为串的长度
int StringLength(HString S);
// 若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则`在这里插入代码片`返回值<0
int StrCompare(HString S, HString T);
// 将S清为空串,并释放S所占空间
Status ClearString(HString &S);
// 用T返回由S1和S2联接而成的新串
Status Concat(HString &T, HString S1, HString S2);
// 1<=pos<=StrLength(S)且0<=len<=StrLength(S)-pos+1。返回串S的第pos个字符起长度为len的子串
HString SubString(HString S, int pos, int len);

//-------------------------------------基本操作的算法描述-------------------------------------
Status StrInsert(HString &S, int pos, HString T) {
	// 1<=pos<=StrLength(S)+1,在串S的第pos个字符之前插入串T。
	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) * sizeof(char)))) {
			exit(OVERFLOW);
		}
		// 为插入T而腾出位置
		for (i = S.length - 1; i >= pos - 1; --i) {
			S.ch[i+T.length] = S.ch[i];
		}

		// 插入
		S.ch[pos-1..pos + T.length - 2] = T.ch[0..T.length - 1]
		S.length += T.length;
	}

	return OK;
}

Status StrAssign(HString &T, char *chars) {
	// 生成一个其值等于串常量chars的串T
	if (T.ch) {
		// 释放T原有空间
		free(T.ch);
	}
	// 求chars的长度i
	for (i = 0, c = chars; c; ++i, ++c)
	
	if (!i) {
		T.ch = NULL;
		T.length = 0;
	} else {
		if (!(T.ch = (char *)malloc(i*sizeof(char)))) {
			exit(OVERFLOW);
		}
		
		T.ch[0..i-1] = chars[0..i-1];
		T.length = i;
	}

	return OK;
}

int StrLength(HString S) {
	// 返回S的元素个数, 称为串的长度
	return S.length;
}

int StrCompare(HString S, HSting T) {
	// 若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0
	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;
}

Status ClearString(HString &S) {
	// 将S清为空串
	if (S.ch) {
		free(S.ch);
		S.ch = NULL;
	}
	S.length = 0;
	return OK;
}

Status Concat(HString &T, HString S1, HString S2) {
	// 用T返回由S1和S2联接而成的新串
	if (T.ch) {
		// 释放旧空间
		free(T.ch);
	}

	if (!(T.ch = (char *)malloc((S1.length + S2.length) * sizeof(char)))) {
		exit(OVERFLOW);
	}

	T.ch[0..S1.length - 1] = S1.ch[0..S1.length - 1];
	T.length = S1.length + S2.length;
	T.ch[S1.length..T.length-1] = S2.ch[0..S2.length - 1];
	return OK:
}

Status SubString(HString &Sub, HString S, int pos, int len) {
	// 用Sub返回串S的第pos个字符起长度为len的子串
	// 其中, 1<=pos<=StrLength(S)且0<=len<=StrLength(S) - pos + 1
	if (pos < 1 || pos > S.length || len < 0 || len > S.length - pos + 1) {
		return ERROR;
	}

	if (Sub.ch) {
		// 释放旧空间
		free(Sub.ch);
	}

	if (!len) {
		// 空子串
		Sub.ch = NULL;
		Sub.length = 0;
	} else {
		Sub.ch = (char *)malloc(len * sizeof(char));
		Sub.ch[0..len-1] = S[pos-1..pos + len - 2];
		Sub.length = len;
	}
	
	return OK;
}

//-------------------------------------------串的块链存储表示-----------------------------------
#define CHUNKSIZE 80 // 可有用户定义块的大小
typedef struct Chunk {
	char ch[CHUNKSIZE];
	struct Chunk *next;
}Chunk;
typedef struct {
	Chunk *head, *tail; // 串的头和尾指针
	int curlen;   		// 串的 当前长度
}LString;

串的模式匹配算法如下:

int Index(SString S, SString T, int pos) {
	// 返回子串T在主串S中的第pos个字符之后的位置。若不存在,则函数值为0。
	// 其中,T非空,1<=pos<=StrLength(S)
	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;
		}
	}
	
	if (j > T[0]) {
		return i - T[0];
	} else {
		return 0;
	}
}

int Index_KMP (SString S, SString T, int pos) {
	// 利用模式串T的next函数求T在主串S中第pos个字符之后的位置的KMP算法
	// 其中,T非空, 1<=pos <= StrLength(S)
	i = pos;
	j = 1;
	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;
	}
}

void get_next(SString T, int &next[]) {
	// 求模式串T的next函数值,并存入数组next
	i = 1;
	next[1] = 0;
	j = 0;
	while (i < T[0]) {
		if (j == 0 || T[i] == T[j]) {
			++i;
			++j;
			next[i] = j;
		} else {
			j = next[j];
		}
	}
}

void get_nextval(SString T, int &nextval[]) {
	// q求模式串T的next函数修正值,并存入数组nextval
	i = 1;
	nextval[1] = 0;
	j = 0;
	while (i < T[0]) {
		if (j == 0 || T[i] == T[j]) {
			++i;
			++j;
			if (T[i] != T[j]) {
				nextval[i] = j;
			} else {
				nextval[i] = nextval[j];
			}
		} else {
			j = nextval[j];
		}
	}
}

串的应用: 文本编辑, 建立词索引

上章内容链接:https://blog.csdn.net/daqino1/article/details/88833633

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值