串的存储结构和基本操作

串的存储结构

以 C 语言为例

定长顺序存储

结构定义

#define MAXSTRLEN 255
typedef struct {
    char ch[MAXSTRLEN + 1];  // 存储串的字符数组,ch[0]存放串的长度
    int length;              // 串的当前长度
} SString;

特点

  • 用一维数组存储串中字符
  • 数组的 0 号位置存储串的长度,从 1 号位置开始存储字符
  • 串长度固定,最大为 MAXSTRLEN
  • 存储密度高,操作简单
  • 缺点:串长度受限,可能造成存储空间浪费

基本操作时间复杂度

  • 求串长:O(1)
  • 串赋值:O(n)
  • 串比较:O(min(m,n))

堆分配存储

结构定义

typedef struct {
    char *ch;      // 指向动态分配存储区的指针
    int length;    // 串的当前长度
} HString;

特点

  • 动态分配存储空间,按需分配
  • 存储空间利用率高,无长度限制
  • 需要手动管理内存,防止内存泄漏
  • 操作相对复杂,需要考虑内存分配和释放

内存管理

  • 初始化:malloc() 分配初始空间
  • 扩容:realloc() 重新分配更大空间
  • 释放:free() 释放内存空间

块链存储

结构定义

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

特点

  • 用链表结构存储,每个节点存储固定数量的字符
  • 适合频繁插入和删除操作
  • 存储密度相对较低(存在指针开销)
  • 操作复杂度较高,但灵活性好
  • 适用于长度变化频繁的串

优缺点对比

存储方式存储密度时间效率空间效率适用场景
定长顺序串长度相对固定
堆分配串长度变化较大
块链频繁插入删除

串的基本操作

基本操作定义

1. StrAssign(&T, chars)

  • 功能:将字符串常量 chars 赋值给串 T
  • 时间复杂度:O(n)

2. StrCopy(&T, S)

  • 功能:将串 S 复制到串 T
  • 时间复杂度:O(n)

3. StrEmpty(S)

  • 功能:判断串 S 是否为空串
  • 时间复杂度:O(1)

4. StrCompare(S, T)

  • 功能:比较串 S 和 T 的大小关系
  • 返回值:S>T 返回正数,S=T 返回 0,S<T 返回负数
  • 时间复杂度:O(min(m,n))

5. StrLength(S)

  • 功能:返回串 S 的长度
  • 时间复杂度:O(1) 或 O(n)(取决于存储方式)

6. SubString(&Sub, S, pos, len)

  • 功能:从串 S 的第 pos 个字符起取长度为 len 的子串赋给 Sub
  • 时间复杂度:O(len)

7. Concat(&T, S1, S2)

  • 功能:连接串 S1 和 S2,结果赋给 T
  • 时间复杂度:O(m+n)

8. Index(S, T, pos)

  • 功能:从串 S 的第 pos 个字符开始查找串 T 首次出现的位置
  • 时间复杂度:O(mn)(朴素算法)

9. Replace(&S, T, V)

  • 功能:用串 V 替换串 S 中所有与串 T 相等的不重叠子串
  • 时间复杂度:O(mn)

10. StrInsert(&S, pos, T)

  • 功能:在串 S 的第 pos 个字符前插入串 T
  • 时间复杂度:O(n+m)

11. StrDelete(&S, pos, len)

  • 功能:从串 S 中删除第 pos 个字符起长度为 len 的子串
  • 时间复杂度:O(n)

核心算法实现要点

串匹配算法

  • 朴素模式匹配:时间复杂度 O(mn),空间复杂度 O(1) 简单的模式匹配
  • KMP 算法:时间复杂度 O(m+n),需要构造 next 数组 KMP 算法
  • KMP 改进算法:构造 nextval 数组,避免不必要的比较 KMP 改进算法

字符串操作注意事项

  • 边界条件检查(位置参数的有效性)
  • 内存管理(堆分配方式需要注意内存泄漏)
  • 字符串结束符的处理(C 语言中的 ‘\0’)
  • 串长度的维护和更新