Files
2019-10-28 23:57:46 +08:00

368 lines
7.3 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*=========================
* 串的堆分配存储表示(堆串)
*
* 包含算法: 4.4
==========================*/
#include "HString.h" //**▲04 串**//
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(HString* T, const char* chars) {
int i, j;
// 求chars的长度
i = (int) strlen(chars);
// 没有有效元素
if(i == 0) {
(*T).ch = NULL;
(*T).length = 0;
return OK;
}
// 存在有效元素时,需要分配存储空间
(*T).ch = (char*) malloc(i * sizeof(char));
if(!((*T).ch)) {
exit(OVERFLOW);
}
for(j = 0; j < i; j++) {
(*T).ch[j] = chars[j];
}
(*T).length = i;
return OK;
}
/*
* 销毁
*
* 将串S销毁。
*
*【注】
* 堆串的结构可以销毁,但不是在销毁操作中
*/
Status DestroyString(HString* S) {
return OK;
}
/*
* 清空
*
* 将串S清空。
*/
Status ClearString(HString* S) {
// 没有有效元素时,销毁堆串结构
if((*S).ch != 0) {
free((*S).ch);
(*S).ch = NULL;
}
(*S).length = 0;
return OK;
}
/*
* 判空
*
* 判断串S中是否包含有效数据。
*
* 返回值:
* TRUE : 串S为空
* FALSE: 串S不为空
*/
Status StrEmpty(HString S) {
return S.length == 0 ? TRUE : FALSE;
}
/*
* 计数
*
* 返回串S中元素的个数。
*
*【注】
* 该操作属于最小操作子集
*/
int StrLength(HString S) {
return S.length;
}
/*
* 求子串
*
* 用Sub返回S[pos, pos+len-1]。
* 返回值指示是否截取成功。
*
*【注】
* 该操作属于最小操作子集
*/
Status SubString(HString* Sub, HString S, int pos, int len) {
int i;
if(pos < 1 || pos > S.length || len < 0 || pos + len - 1 > S.length) {
return ERROR;
}
// 如果是截取0个字符不需要分配空间
if(len == 0) {
(*Sub).ch = NULL;
(*Sub).length = 0;
return OK;
}
(*Sub).ch = (char*) malloc(len * sizeof(char));
if(!(*Sub).ch) {
exit(OVERFLOW);
}
// 复制元素
for(i = 0; i < len; i++) {
(*Sub).ch[i] = S.ch[i + pos - 1];
}
// 确定新长度
(*Sub).length = len;
return OK;
}
/*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置如果不存在则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.此实现需要依赖串的最小操作子集
* 2.该实现比较低效
*/
int Index(HString S, HString T, int pos) {
int i, s, t;
HString sub;
if(pos < 1 || pos > S.length || StrEmpty(T)) {
return 0;
}
s = S.length;
t = T.length;
i = pos;
// 保证长度不越界
while(i + t - 1 <= s) {
// 获取S[i, i+t-1]
SubString(&sub, S, i, t);
// 如果子串与模式串不匹配,则需要继续推进
if(StrCompare(sub, T) != 0) {
++i;
} else {
return i;
}
}
return 0;
}
/*
* ████████ 算法4.4 ████████
*
* 插入
*
* 将串T插入到主串S的pos位置处。
*/
Status StrInsert(HString* S, int pos, HString T) {
int i;
if(pos < 1 || pos > (*S).length + 1) {
return ERROR;
}
// 如果待插入的串为空,则提前返回
if(StrEmpty(T)) {
return OK;
}
// 分配新空间,会将旧元素一起复制过去
(*S).ch = (char*) realloc((*S).ch, ((*S).length + T.length) * sizeof(char));
if(!(*S).ch) {
exit(OVERFLOW);
}
// 在S中腾出位置为插入T做准备
for(i = (*S).length - 1; i >= pos - 1; i--) {
// 从后向前遍历,将前面的元素挪到后面
(*S).ch[i + T.length] = (*S).ch[i];
}
// 将串T插入在S中腾出的位置上
for(i = pos - 1; i <= pos + T.length - 2; i++) {
(*S).ch[i] = T.ch[i - pos + 1];
}
// 长度增加
(*S).length += T.length;
return OK;
}
/*
* 删除
*
* 删除S[pos, pos+len-1]。
*/
Status StrDelete(HString* S, int pos, int len) {
int i;
if(pos < 1 || pos + len - 1 > (*S).length || len < 0) {
return ERROR;
}
// 如果待删除的长度为0则提前返回
if(len == 0) {
return OK;
}
// 把后面的元素挪到前面,覆盖掉被删除的元素
for(i = pos + len - 1; i <= (*S).length - 1; i++) {
(*S).ch[i - len] = (*S).ch[i];
}
// 长度减少
(*S).length -= len;
// 缩减分配的空间如果长度减少为0这里会返回空指针
(*S).ch = (char*) realloc((*S).ch, (*S).length * sizeof(char));
return OK;
}
/*
* 比较
*
* 比较串S和串T返回比较结果。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrCompare(HString S, HString 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;
}
/*
* 复制
*
* 将串S复制到串T。
*/
Status StrCopy(HString* T, HString S) {
int i;
if(StrEmpty(S)) {
(*T).ch = NULL;
(*T).length = 0;
} else {
// 分配空间
(*T).ch = (char*) malloc(S.length * sizeof(char));
if(!(*T).ch) {
exit(OVERFLOW);
}
// 复制元素
for(i = 0; i < S.length; i++) {
(*T).ch[i] = S.ch[i];
}
// 复制长度信息
(*T).length = S.length;
}
return OK;
}
/*
* 替换
*
* 用V替换主串S中出现的所有与T相等的且不重叠的子串。
*
*【注】
* 1.该操作依赖最小操作子集
* 2.该实现比较低效
*/
Status Replace(HString* S, HString T, HString V) {
int i;
if(StrEmpty(*S) || StrEmpty(T)) {
return ERROR;
}
// 在主串S中寻找模式串T第一次出现的位置
i = Index(*S, T, 1);
// 如果存在匹配的字符串
while(i != 0) {
StrDelete(S, i, StrLength(T)); // 从S中删除T
StrInsert(S, i, V); // 向S中插入V
i += StrLength(V); // i切换到下一个位置
i = Index(*S, T, i); // 查找下一个匹配的字符串
}
return OK;
}
/*
* 串联接
*
* 联接S1和S2并存储到T中返回。如果联接后的长度溢出则只保留未溢出的部分。
* 返回值表示联接后的串是否完整。
* 堆串的空间被认为是无限的因此这里总是返回TRUE指示串不会被裁剪。
*
*【注】
* 该操作属于最小操作子集
*/
Status Concat(HString* T, HString S1, HString S2) {
int i;
// 确定新长度
(*T).length = S1.length + S2.length;
// 分配空间
(*T).ch = (char*) malloc((*T).length * sizeof(char));
if(!(*T).ch) {
exit(OVERFLOW);
}
// 先把S1的内容拷贝出来
for(i = 0; i < S1.length; i++) {
(*T).ch[i] = S1.ch[i];
}
// 再拷贝S2的内容
for(i = 0; i < S2.length; i++) {
(*T).ch[S1.length + i] = S2.ch[i];
}
return TRUE;
}