数据结构:定长顺序串(SString)基本操作的算法描述(C语言)

作者在学习数据结构时,发现鲜有完全按照 C 语言描述的算法操作,这让习惯于写 .c 而不是 .cpp 的初学者很是头疼。本文将基于 C 语言描述算法操作,如有错漏还望大佬们指正。


前言

本文将按照严惠敏所著《数据结构(C语言版)》所做的函数原型声明进行算法描述,由于C语言不支持函数参数中出现取地址符,我将函数参数更改为指针,调用函数时需要使用一级指针。基本操作调用示例将在本文后给出。

2023.4.10   08 : 20 2023.4.10\ 08:20 2023.4.10 08:20 新增了 I n d e x Index Index K M P KMP KMP 算法及其调用示例


一、定长顺序串基本操作的函数声明

//生成一个其值等于 chars 的串 S
extern Status StrAssign(SString* S, char* chars);
//由串 S 复制得串 T
extern Status StrCopy(SString *T, SString S);
//若 S 为空串,则返回 TRUE,否则返回 FAUSE
extern Status StrEmpty(SString S);
//若 S > T,则返回值 > 0;若 S = T,则返回值 = 0;若 S < T,则返回值 < 0
extern int StrCompare(SString S, SString T);
//返回串 S 的元素个数,称为串的长度
extern int StrLength(SString S);
//将 S 清为空串
extern Status ClearString(SString *S);
//用 T 返回由 S1 和 S2 联接而成的新串,如果连接时未截断则返回 TRUE,否则返回 FAUSE
extern Status Concat(SString *T, SString S1, SString S2);
//用 Sub 返回串 S 的第 pos 个字符起长度为 len 的子串
extern Status SubString(SString *Sub, SString S, int pos, int len);
//如果主串 S 中存在和串 T 值相同的子串,则返回它在主串 S 中第 pos 个字符之后第一次出现的位置;否则函数值为 0
extern int Index(SString S, SString T, int pos);
//用串 V 替换主串 S 中出现的所有与串 T 相等的不重叠的子串
extern Status Replace(SString *S, SString T, SString V);
//在串 S 的第 pos 个字符前插入串 T
extern Status StrInsert(SString *S, int pos, SString T);
//从串 S 的第 pos 个字符起长度为 len 的子串
extern Status StrDelete(SString *S, int pos, int len);
//销毁串 S
extern Status DestroyStr(SString *S);
//打印串 S
extern Status PrintStr(SString S);
//模式匹配的的 KMP 算法:如果主串 S 中存在和串 T 值相同的子串,则返回它在主串 S 中第 pos 个字符之后第一次出现的位置;否则函数值为 -1
extern int Index_KMP(SString S, SString T, int pos);
//计算 KMP 算法中串 T 的 next 函数值
extern void get_nextval(SString T, int *nextval);

二、定长顺序串基本操作的完整描述

/* 定长顺序串 */
#include <stdio.h>
#include <stdlib.h>
#define MAXSTRLEN   255
#define OK          0
#define ERROR       1
#define TRUE        0
#define FAUSE       1
#define OVERFLOW    -2

typedef char Elemtype;
typedef int Status;
/*--------串的定长顺序表示--------*/

typedef unsigned char SString[MAXSTRLEN + 1];

//--------定长顺序串的基本操作的函数声明--------

//生成一个其值等于 chars 的串 S
extern Status StrAssign(SString* S, char* chars);
//由串 S 复制得串 T
extern Status StrCopy(SString *T, SString S);
//若 S 为空串,则返回 TRUE,否则返回 FAUSE
extern Status StrEmpty(SString S);
//若 S > T,则返回值 > 0;若 S = T,则返回值 = 0;若 S < T,则返回值 < 0
extern int StrCompare(SString S, SString T);
//返回串 S 的元素个数,称为串的长度
extern int StrLength(SString S);
//将 S 清为空串
extern Status ClearString(SString *S);
//用 T 返回由 S1 和 S2 联接而成的新串,如果连接时未截断则返回 TRUE,否则返回 FAUSE
extern Status Concat(SString *T, SString S1, SString S2);
//用 Sub 返回串 S 的第 pos 个字符起长度为 len 的子串
extern Status SubString(SString *Sub, SString S, int pos, int len);
//如果主串 S 中存在和串 T 值相同的子串,则返回它在主串 S 中第 pos 个字符之后第一次出现的位置;否则函数值为 0
extern int Index(SString S, SString T, int pos);
//用串 V 替换主串 S 中出现的所有与串 T 相等的不重叠的子串
extern Status Replace(SString *S, SString T, SString V);
//在串 S 的第 pos 个字符前插入串 T
extern Status StrInsert(SString *S, int pos, SString T);
//从串 S 的第 pos 个字符起长度为 len 的子串
extern Status StrDelete(SString *S, int pos, int len);
//销毁串 S
extern Status DestroyStr(SString *S);
//打印串 S
extern Status PrintStr(SString S);
//模式匹配的的 KMP 算法:如果主串 S 中存在和串 T 值相同的子串,则返回它在主串 S 中第 pos 个字符之后第一次出现的位置;否则函数值为 -1
extern int Index_KMP(SString S, SString T, int pos);
//计算 KMP 算法中串 T 的 next 函数值
extern void get_nextval(SString T, int *nextval);

Status StrAssign(SString* S, char* chars) {
    int len; char* c;
    for (len = 0, c = chars; *c; len++, c++) {
        (*S)[len + 1] = *c;
    }
    (*S)[0] = len;
    return OK;
}// StrAssign

Status StrCopy(SString *T, SString S) {
    for (int i = 1; i <= S[0]; i++) (*T)[i] = S[i];
    (*T)[0] = S[0];
    return OK;
}// StrCopy

Status StrEmpty(SString S) {
    if (S[0]) return FAUSE;
    else return TRUE;
}// StrEmpty

int StrCompare(SString S, SString T) {
    if (S[0] > T[0]) return 1;
    else if (S[0] < T[0]) return -1;
    else {
        for (int i = 1; i <= S[0]; i++) {
            if (S[i] > T[i]) return 1;
            else if (S[i] < T[i]) return -1;
        }
        return 0;
    }
}// StrCompare

int StrLength(SString S) {
    return S[0];
}// StrLength

Status ClearString(SString *S) {
    (*S)[0] = 0;
    return OK;
}// ClearString

Status Concat(SString *T, SString S1, SString S2) {
    int uncut = 0;
    if (S1[0] + S2[0] <= MAXSTRLEN) {
        for (int i = 1; i <= S1[0]; i++) (*T)[i] = S1[i];
        for (int i = S1[0] + 1; i <= S1[0] + S2[0]; i++) (*T)[i] = S2[i - S1[0]];
        (*T)[0] = S1[0] + S2[0]; uncut = TRUE;
    }
    else if (S1[0] < MAXSTRLEN) {
        for (int i = 1; i <= S1[0]; i++) (*T)[i] = S1[i];
        for (int i = S1[0] + 1; i <= MAXSTRLEN; i++) (*T)[i] = S2[i - S1[0]];
        (*T)[0] = MAXSTRLEN; uncut = FAUSE;
    }
    else {
        for (int i = 0; i <= MAXSTRLEN; i++) (*T)[i] = S1[i];
        uncut = FAUSE;
    }
    return uncut;
}// Concat

Status SubString(SString *Sub, SString S, int pos, int len) {
    if (pos < 1 || pos > S[0] || len < 0 || len > S[0] - pos + 1) return ERROR;
    for (int i = 1; i <= len; i++) (*Sub)[i] = S[pos + i - 1];
    (*Sub)[0] = len; return OK;
}// SubString

int Index(SString S, SString T, int pos) {
    if (pos > 0) {
        int n = StrLength(S), m = StrLength(T), i = pos;
        SString sub;
        while (i <= n - m + 1) {
            SubString(&sub, S, i, m);
            if (StrCompare(sub, T) != 0) ++i;
            else return i;
        }
    }
    return 0;
}// Index

Status Replace(SString *S, SString T, SString V) {
    int pos = Index(*S, T, 1);
    if (!pos) return ERROR;
    StrDelete(S, pos, T[0]);
    StrInsert(S, pos, V);
    return OK;
}// Replace

Status StrInsert(SString* S, int pos, SString T) {
    if ((*S)[0] + T[0] > MAXSTRLEN) exit(OVERFLOW);
    SString tmp;
    for (int i = 1; i <= (*S)[0] - pos + 1; i++) tmp[i] = (*S)[pos + i - 1];
    tmp[0] = (*S)[0] - pos + 1;
    for (int i = 1; i <= T[0]; i++) 
        (*S)[pos + i - 1] = T[i];
    for (int i = 1; i <= tmp[0]; i++) (*S)[pos + T[0] + i - 1] = tmp[i];
    (*S)[0] = (*S)[0] + T[0];
    return OK;
}// StrInsert

Status StrDelete(SString* S, int pos, int len) {
    for (int i = 0; i <= (int)(*S)[0] - pos - len; i++) 
        (*S)[pos + i] = (*S)[pos + len + i];
    (*S)[0] -= len;
    return 0;
}// StrDelete

Status DestroyStr(SString *S) {
    free(S);
    return OK;
}// DestroyStr

Status PrintStr(SString S) {
    for (int i = 1; i <= S[0]; i++) {
        printf("%c", S[i]);
    }
    printf("\n");
    return OK;
}// PrintList

int Index_KMP(SString S, SString T, int pos) {
    int i = pos, j = 1;
    int next[MAXSTRLEN + 1];
    get_nextval(T, next);
    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]);
}// Index_KMP

void get_nextval(SString T, int *nextval) {
    * nextval = (long int)malloc(MAXSTRLEN * sizeof(int));
    int i = 1; nextval[1] = 0; int 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];
    }
}// get_nextval

三、调用示例

int main() {
    char chars[MAXSTRLEN + 1] = {0};
    SString S, T, P;
    printf("Please enter a string: ");
    scanf("%s", chars);
    StrAssign(&S, chars);
    printf("The resulting string: ");
    PrintStr(S);
    StrCopy(&T, S);
    printf("StrCopy(&T, S): ");
    PrintStr(T);
    printf("StrCompare(S, T): result = %d\n", StrCompare(S, T));
    printf("StrLength(S): %d\n", StrLength(S));
    Concat(&P, S, T);
    printf("Concat(&P, S, T): P = ");
    PrintStr(P);
    char chars1[MAXSTRLEN + 1] = { 0 }, chars2[MAXSTRLEN + 1] = { 0 };
    SString S, T;
    printf("Index_KMP: Please enter chars1: ");
    scanf("%s", chars1);
    printf("Index_KMP: Please enter chars2: ");
    scanf("%s", chars2);
    StrAssign(&S, chars1);
    StrAssign(&T, chars2);
    printf("Index_KMP: result = %d\n", Index_KMP(S, T, 1));
    return 0;
}

终端输出结果如下:

Please enter a string: abcde
The resulting string: abcde
StrCopy(&T, S): abcde
StrCompare(S, T): result = 0
StrLength(S): 5
Concat(&P, S, T): P = abcdeabcde
Index_KMP: Please enter chars1: samples
Index_KMP: Please enter chars2: sam
Index_KMP: result = 0

总结

以上是定长顺序串的基本操作的算法描述,更多数据结构的算法描述还在更新中,敬请关注作者专栏。

  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值