数据结构--串

目录

一、串的基本操作

1 . 静态数组实现(定长顺序存储)

1-1 代码运行结果​

 2 . 动态数组实现(堆分配存储)

2-1 代码运行结果​

二、串的匹配模式

1 . 简单的匹配算法

1-1 代码运行结果​

2 . 改进的模式匹配算法——KMP算法

2-1 代码运行结果​

3 . KMP算法的进一步优化

3-1 代码运行结果​


一、串的基本操作

1 . 静态数组实现(定长顺序存储)

#include <iostream>
#include <string.h>

using namespace std;

#define MAXLEN 255//预定义最大串长 255
typedef struct {
    //静态数组实现(定长顺序存储)
    char ch[MAXLEN];//每个分量存储一个字符
    int length;//串的实际长度
} SString;

//初始化
bool InitString(SString &S) {
    S.length = 0;
    return true;
}
//赋值操作 把串T赋值为 chars
bool StrAssign(SString &T, const char *chars) {
    if(strlen(chars) > MAXLEN) {
        return false;
    }
    for (int i = 1; i <= strlen(chars); i++) {
        T.ch[i] = chars[i - 1];
        T.length++;
    }
    return true;
}
//复制操作 由串S复制得到T
bool StrCopy(SString &T, SString S) {
    for(int i = 1; i <= S.length; i++) {
        T.ch[i] = S.ch[i];
        T.length++;
    }
    return true;
}
//判空操作 空返回true 非空则false
bool StrEmpty(SString S) {
    if(S.length == 0) {
        return true;
    }
    return false;
}
//若s>t 返回>0  s==t 返回=0  s<t 返回<0
int StrCompare(SString S, SString T) {
    for (int i = 1; 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;
}
//返回串长
int StrLength(SString S) {
    return S.length;
}
//求子串 用sub返回串s的第pos个位置开始的长度为len的串
bool SubString(SString &Sub, SString S, int pos, int len) {
    if(pos + len - 1 > S.length || pos < 1 || pos > S.length) { //字串范围越界 下标不合法
        return false;
    }
    for (int i = pos; i < pos + len; i++) {
        Sub.ch[i - pos + 1] = S.ch[i];
    }
    Sub.length = len;
    return true;
}
//字符串拼接 用T返回由S1和S2连接的新串
bool Concat(SString &T, SString S1, SString S2) {
    if(S1.length + S2.length > MAXLEN) { //字符串拼接会被截断
        for (int i = 1; i <= S1.length ; i++) {
            T.ch[i] = S1.ch[i];
        }
        for (int i = 1; i <= MAXLEN - S1.length ; i++) {
            T.ch[S1.length  + i] = S2.ch[i];
        }
        T.length  = MAXLEN;
        return false;
    } else { //字符串拼接不会被截断
        for (int i = 1; i <= S1.length ; i++) {
            T.ch[i] = S1.ch[i];
        }
        for (int i = 1; i <= S2.length ; i++) {
            T.ch[S1.length  + i] = S2.ch[i];
        }
        T.length  = S1.length + S2.length ;
        return true;
    }
}
//返回串T在S中第一次出现的位置 不存在返回0
int Index(SString S, SString T) {
    int i = 1, n = StrLength(S), m = StrLength(T);
    SString sub;
    while(i <= n - m + 1) {
        SubString(sub, S, i, m);
        if(StrCompare(sub, T) != 0) {
            ++i;
        } else {
            return i;//返回字串在主串中的位置
        }
    }
    return 0;//S 中不存在与 T相等的字串
}
//清空操作
bool ClearString(SString &S) {
    S.length = 0;
    return true;
}
//打印串
bool showString(SString S) {
    if(StrEmpty(S)) {
        return false;
    }
    for (int i = 1; i <= S.length; i++) {
        cout << S.ch[i];
    }
    cout << endl;
    return true;
}
void test() {
    SString S1;
    InitString(S1);
    if(StrEmpty(S1)) {
        cout << "S1 Is Empty!" << endl;
    } else {
        cout << "S1 Isn't Empty!" << endl;
    }
    StrAssign(S1, "SString");
    showString(S1);
    SString S2;
    InitString(S2);
    StrCopy(S2, S1);
    showString(S2);
    cout << "StrCompare(S1, S2): " << StrCompare(S1, S2) << endl; // =0
    cout << "StrLength(S1): " << StrLength(S1) << endl;
    cout << "StrLength(S2): " << StrLength(S2) << endl;
    //求字串,用 Sub返回 串S 的第 pos 个位置开始的长度为 len 的串
    SString Sub;
    InitString(Sub);
    SubString(Sub, S1, 2, 4);
    showString(Sub);
    SString T;
    InitString(T);
    Concat(T, S1, S2);
    showString(T);
//    //返回 串Sub 在 S1 中第一次出现的位置,不存在返回0
    cout << "Index(S1, Sub):" << Index(S1, Sub) << endl;
    ClearString(S1);
    cout << "StrLength(S1):" << StrLength(S1) << endl;
}
int main() {
    test();
    return 0;
}

1-1 代码运行结果

 2 . 动态数组实现(堆分配存储)

#include <iostream>
#include <string.h>

using namespace std;

#define MAXLEN 10//预定义最大串长 10
typedef struct {
    //动态数组实现(堆分配存储)
    char *ch;//按串长分配存储区 ch指向串的基地址
    int length;//串的长度
    int maxSize;
} HString;

typedef struct StringNode { //存储密度低 每个字符 1B 每个指针 4B(以32位系统为例)
    //串的链式存储
    char ch;//每个结点存 1 个字符
    struct StringNode *next;
} StringNode, *String;
//typedef struct StringNode { //存储密度提高
//    //串的链式存储(推荐)
//    //如果结点存不满 可以用特殊字符(如 '\0')填充
//    char ch[4];//每个结点存 多 个字符
//    struct StringNode *next;
//} StringNode, *String;

//初始化
bool InitString(HString &S) {
    S.ch = (char *)malloc(MAXLEN * sizeof(char));
    S.length = 0;
    S.maxSize = MAXLEN;
}
//增加串 长度
bool increaseStringSize(HString &S, int len) {
    char *p = S.ch;
    S.ch = (char *)malloc((S.maxSize + len) * sizeof(char));
    if(!S.ch) { //申请空间失败
        return false;
    }
    for (int i = 1; i <= S.length; i++) {
        S.ch[i] = p[i];
    }
    S.maxSize += len;
    free(p);
}
//赋值操作 把串T赋值为 chars
bool StrAssign(HString &T, const char *chars) {
    if(strlen(chars) > T.maxSize) {
        increaseStringSize(T, strlen(chars) - T.maxSize);
    }
    for (int i = 1; i <= strlen(chars); i++) {
        T.ch[i] = chars[i - 1];
        T.length++;
    }
    return true;
}
//复制操作 由串S复制得到T
bool StrCopy(HString &T, HString S) {
    if(T.length < S.length) {
        increaseStringSize(T, S.length - T.length);
    }
    for(int i = 1; i <= S.length; i++) {
        T.ch[i] = S.ch[i];
        T.length++;
    }
    return true;
}
//判空操作 空返回true 非空则false
bool StrEmpty(HString S) {
    if(S.length == 0) {
        return true;
    }
    return false;
}
//若s>t 返回>0  s==t 返回=0  s<t 返回<0
int StrCompare(HString S, HString T) {
    for (int i = 1; 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;
}
//返回串长
int StrLength(HString S) {
    return S.length;
}
//求子串 用sub返回串s的第pos个位置开始的长度为len的串
bool SubString(HString &Sub, HString S, int pos, int len) {
    if(pos + len - 1 > S.length || pos < 1 || pos > S.length) { //字串范围越界 下标不合法
        return false;
    }
    for (int i = pos; i < pos + len; i++) {
        Sub.ch[i - pos + 1] = S.ch[i];
    }
    Sub.length = len;
    return true;
}
//字符串拼接 用T返回由S1和S2连接的新串
bool Concat(HString &T, HString S1, HString S2) {
    if(S1.length + S2.length > T.maxSize) { //字符串拼接会被截断 需要拓展容量
        increaseStringSize(T, S1.length + S2.length - T.maxSize);
    }
    for (int i = 1; i <= S1.length ; i++) {
        T.ch[i] = S1.ch[i];
    }
    for (int i = 1; i <= S2.length ; i++) {
        T.ch[S1.length  + i] = S2.ch[i];
    }
    T.length  = S1.length + S2.length ;
    return true;
}
//返回串T在S中第一次出现的位置 不存在返回0
int Index(HString S, HString T) {
    int i = 1, n = StrLength(S), m = StrLength(T);
    HString sub;
    while(i <= n - m + 1) {
        SubString(sub, S, i, m);
        if(StrCompare(sub, T) != 0) {
            ++i;
        } else {
            return i;//返回字串在主串中的位置
        }
    }
    return 0;//S 中不存在与 T相等的字串
}
//清空操作
bool ClearString(HString &S) {
    S.length = 0;
    return true;
}
//销毁串
bool DestoryString(HString &S) {
    S.length = 0;
    if(!S.ch) {
        free(S.ch);
    }
    return true;
}
//打印串
bool showString(HString S) {
    if(StrEmpty(S)) {
        return false;
    }
    for (int i = 1; i <= S.length; i++) {
        cout << S.ch[i];
    }
    cout << endl;
    return true;
}
void test() {
    HString S1;
    InitString(S1);
    if(StrEmpty(S1)) {
        cout << "S1 Is Empty!" << endl;
    } else {
        cout << "S1 Isn't Empty!" << endl;
    }
    StrAssign(S1, "googooglegoogoogle");
    showString(S1);
    HString S2;
    InitString(S2);
    StrCopy(S2, S1);
    showString(S2);
    cout << "StrCompare(S1, S2): " << StrCompare(S1, S2) << endl; // =0
    cout << "StrLength(S1): " << StrLength(S1) << endl;
    cout << "StrLength(S2): " << StrLength(S2) << endl;
    //求字串,用 Sub返回 串S 的第 pos 个位置开始的长度为 len 的串
    HString Sub;
    InitString(Sub);
    SubString(Sub, S1, 13, 6);
    showString(Sub);
    HString T;
    InitString(T);
    Concat(T, S1, S2);
    showString(T);
    cout << "StrLength(T):" << StrLength(T) << endl;
    //    //返回 串Sub 在 S1 中第一次出现的位置,不存在返回0
    cout << "Index(S1, Sub):" << Index(S1, Sub) << endl;
    ClearString(S1);
    cout << "StrLength(S1):" << StrLength(S1) << endl;
    DestoryString(T);
}
int main() {
    test();
    return 0;
}

2-1 代码运行结果

二、串的匹配模式

1 . 简单的匹配算法

//简单的模式匹配算法
int Index_01(HString S, HString T) {
    //分别用计数指针 i j 指示主串 S 和模式串 T当前正待比较字符的位置
    int i = 1, j = 1;
    while(i <= S.length && j <= T.length) {
        if(S.ch[i] == T.ch[j]) { //继续比较字符
            ++i;
            ++j;
        } else { //指针后退重新匹配
            i = i - j + 2;
            j = 1;
        }
    }
    if(j > T.length) {
        return i - T.length;
    } else {
        return 0;
    }
}
void test02() {
    HString S;
    InitString(S);
    StrAssign(S, "sdbdnhfvfnjgoogooglegoogoogle");
    showString(S);
    HString T;
    InitString(T);
    StrAssign(T, "google");
    showString(T);
    cout << Index_01(S, T) << endl;
}

1-1 代码运行结果

2 . 改进的模式匹配算法——KMP算法

//改进的的模式匹配算法--(KMP算法)

//获得next值
void getNext(HString T, int next[]) {
    int i = 1, j = 0;
    next[1] = 0;
    while (i < T.length) {
        if(j == 0 || T.ch[i] == T.ch[j]) {
            ++i;
            ++j;
            next[i] = j; //若pi=pj 则next[j+1]=next[j]+1;
        } else {
            j = next[j];//否则令j=next[j] 循环继续
        }
    }
}
//KMP算法
int Index_KMP(HString S, HString T, int next[]) {
    //分别用计数指针 i j 指示主串 S 和模式串 T当前正待比较字符的位置
    int i = 1, j = 1;
    while(i <= S.length && j <= T.length) {
        if(j == 0 || S.ch[i] == T.ch[j]) { //继续比较后继字符
            ++i;
            ++j;
        } else { //模式串向右移动
            j = next[j];
        }
    }
    if(j > T.length) {
        return i - T.length;//匹配成功
    } else {
        return 0;
    }
}
void test03() {
    HString S;
    InitString(S);
    StrAssign(S, "sdbdnhfvfnjgoogooglegoogoogle");
    showString(S);
    HString T;
    InitString(T);
    StrAssign(T, "google");
    showString(T);
    int next[10];
    getNext(T, next);
    cout << Index_KMP(S, T, next) << endl;
}

2-1 代码运行结果

3 . KMP算法的进一步优化

//KMP算法的进一步优化
void getNextVal(HString T, int nextval[]) {
    int i = 1, j = 0;
    nextval[1] = 0;
    while (i < T.length) {
        if(j == 0 || T.ch[i] == T.ch[j]) {
            ++i;
            ++j;
            if(T.ch[i] != T.ch[j]) {
                nextval[i] = j;
            } else {
                nextval[i] = nextval[j];
            }
        } else {
            j = nextval[j];
        }
    }
}
//KMP算法
int Index_KMP(HString S, HString T, int next[]) {
    //分别用计数指针 i j 指示主串 S 和模式串 T当前正待比较字符的位置
    int i = 1, j = 1;
    while(i <= S.length && j <= T.length) {
        if(j == 0 || S.ch[i] == T.ch[j]) { //继续比较后继字符
            ++i;
            ++j;
        } else { //模式串向右移动
            j = next[j];
        }
    }
    if(j > T.length) {
        return i - T.length;//匹配成功
    } else {
        return 0;
    }
}
void test04() {
    HString S;
    InitString(S);
    StrAssign(S, "sdbdnhfvfnjgoogooglegoogoogle");
    showString(S);
    HString T;
    InitString(T);
    StrAssign(T, "google");
    showString(T);
    int nextval[10];
    getNextVal(T, nextval);
    cout << Index_KMP(S, T, nextval) << endl;
}

3-1 代码运行结果

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我这么好看

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值