mirror of
https://github.com/kangjianwei/Data-Structure.git
synced 2026-09-30 16:23:17 +08:00
381 lines
6.7 KiB
C++
381 lines
6.7 KiB
C++
/*=========================
|
|
* 串的堆分配存储表示(堆串)
|
|
*
|
|
* 包含算法: 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;
|
|
}
|
|
|
|
// 输出:打印字符串
|
|
void StrPrint(HString S) {
|
|
int i;
|
|
|
|
if(S.length == 0) {
|
|
return;
|
|
}
|
|
|
|
for(i = 0; i < S.length; i++) {
|
|
printf("%c", S.ch[i]);
|
|
}
|
|
printf("\n");
|
|
} |