数据结构之串

串的定义和实现(了解即可)

在这里插入图片描述

code
#include <iostream>
#include <cstring>
using namespace std;
#define MAXLEN 255 // 预定义最大串长为255
// 定长数组实现(定长顺序存储 )
typedef struct
{
    char ch[MAXLEN]; // 每个分量存储一个字符
    int length;      // 串的实际长度
} SString;

// 动态数组实现(堆分配)
    typedef struct
    {
        char *ch;   // 按串长分配存储区,ch指向串的基地址
        int length; // 串的长度
    } HString;
//串的基本操作:
    // StrAssign(&T, chars)//赋值操作。把串T赋值为 chars
    // Strcopy(&T, S)// 复制操作。由串S复制得到串T。
    // StrEmpty(S)// 判空操作。若S为空串,则返回TRUE,否则返回 FALSE
    // StrCompare(S,T)// 比较操作。若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0。
    // StrEngth(S)// 求串长。返回串S的元素个数
    // Substring(&Sub,S,pos,1en)//求子串。用Sub返回串S的第pos个字符起长度为len的子串。
    // Concat(&T,S1,S2)//串联接。用T返回由S1和S2联接而成的新串。
    // Index(S,T)// 定位操作。若主串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的位置;否则函数值为0
    // Clearstring(&S)// 清空操作。将S清为空串
    // Destroystring(&S)//销毁串。将串S销毁

// 赋值操作。把串T赋值为 chars
void StrAssign(SString *T, char* chars)
{
    int len = strlen(chars);
    if (len > MAXLEN)
        len = MAXLEN; // 确保长度不超过最大值
    for (int i = 0; i < len; i++)
    {
        T->ch[i] = chars[i];
    }
    T->length = len;
}

// 复制操作。由串S复制得到串T。
void Strcopy(SString *T, SString S)
{
    int len = S.length;
    if (len > MAXLEN)
        len = MAXLEN; // 确保长度不超过最大值
    for (int i = 0; i < len; i++)
    {
        T->ch[i] = S.ch[i];
    }
    T->length = len;
}

// 判空操作。若S为空串,则返回TRUE,否则返回 FALSE
int  StrEmpty(SString S)
{
    return S.length == 0;
}

// 比较操作。若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0。
int StrCompare(SString S, SString T)
{
    int len1 = S.length, len2 = T.length;
    int min_len = (len1 < len2) ? len1 : len2; // 取较小的长度进行比较
    for (int i = 0; i < min_len; i++)
    {
        if (S.ch[i] > T.ch[i])
            return 1; // S>T,返回1
        if (S.ch[i] < T.ch[i])
            return -1; // S<T,返回-1
    }
    return (len1 - len2); // 若相等,则比较长度差值,正表示S>T,负表示S<T,0表示S=T
}

// 求串长。返回串S的元素个数。
int StrEngth(SString S)
{
    return S.length;
}

// 求子串。用Sub返回串S的第pos个字符起长度为len的子串。
void Substring(SString *Sub, SString S, int pos, int len)
{
    if (pos < 1 || pos > S.length || len < 1 || pos + len > S.length)
    {                    // 边界检查很重要
        Sub->length = 0; // 子串越界,置为空串
        return;
    }

    for (int i = 0; i < len; i++)
    {                                   // 取子串字符到Sub中
        Sub->ch[i] = S.ch[pos + i - 1]; // 注意数组下标从0开始,但子串的位置从1开始,所以减1。
    }
    Sub->length = len; // 设置子串长度为len。
}

// 串联接。用T返回由S1和S2联接而成的新串。
void Concat(SString *T, SString S1, SString S2)
{
    int len1 = S1.length, len2 = S2.length; // 取两个串的长度总和(不包括结束符'\0')
    if (len1 + len2 <MAXLEN)
    { // 确保总长度不超过最大值,并进行边界检查和越界处理。注意这里需要为新串添加结束符'\0'。
        for (int i = 0; i < len1 + len2; i++) 
        { // 把新串的字符复制到T中(不包括结束符'\0')
            if (i < len1)
                T->ch[i] = S1.ch[i]; // 先复制S1的字符
            else
                T->ch[i] = S2.ch[i - len1]; // 然后复制S2的字符
        }
        T->ch[len1 + len2] = '\0'; // 在新串的末尾添加结束符'\0'
    }
    T->length = len1 + len2; // 设置新串的长度为两个串的长度总和。
}

// 定位操作。若主串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的位置;否则函数值为0。
int Index(SString S, SString T)
{
    int len1 = S.length, len2 = T.length;
    if (len2 == 0)
        return 0; // 子串为空串,返回0
    if (len1 < len2)
        return -1; // 主串长度小于子串长度,返回-1
    
    //使用strncmp函数比较从当前位置i开始的子串(长度为len2)与子串T
    for (int i = 0; i <= len1 - len2; i++)
    { // 从主串的开始位置到结束位置依次比较
        if (strncmp(S.ch + i, T.ch, len2) == 0)
            return i+1; // 若找到相同的子串,返回子串在主串中的位置
    }

    return -1; // 若未找到相同的子串,返回-1
}

// 清空操作。将S清为空串。
void Clearstring(SString *S)
{
    S->length = 0; // 将串的长度置为0
}

// 销毁串。将串S销毁。
void Destroystring(SString *S)
{   //注意这里只是做了标记,真正的内存并没有被释放。如果要释放内存,需要使用其他方法。
    S->length = -1; // 将串的长度置为-1,表示该串已销毁。
}

void printf(SString S){
        for(int i=0;i<S.length;i++){
        cout<<S.ch[i];
    }
    cout<<endl;
    //cout<<endl<<S.length<<endl;
}
int main()

{
    SString S1,S2,sub,T1;
   char a[]="ktuh2agj";
   char b[]="2agj";
   char c[]="syw";
    //赋值
    //void StrAssign(SString *T, char* chars)
    StrAssign (&S1,a);//这里S1传递的是引用
    StrAssign (&sub,c);
    StrAssign (&T1,b);

    cout<<"主串是: ";
    printf(S1);

    //复制
     Strcopy(&S2,S1);
     cout<<"复制的串的是: ";
    printf(S2);

    //判空
    cout<<"是否空: "<<StrEmpty(S2)<<endl;

    //清空
    Clearstring(&S2);
    cout<<"Clearstring后是否空: "<<StrEmpty(S2)<<endl;

    //求字串
    Substring(&sub,S1,1,3);
    cout<<"前三位子串是: ";
    printf(sub);

    //比大小
    cout<<"主串和字串比较: "<<StrCompare(S1,sub)<<endl;

    //串连接
    SString T;
    Concat(&T,S1,sub);
     cout<<"连接主串和前三位子串后的字符串是: ";

    printf(T);
    //定位
    cout<<"2agj的位置是"<<Index(S1,T1)<<endl;
    

    return 0;
}

在这里插入图片描述

注意细节
1.下面是两种运算符的区别

在这里插入图片描述

2.下面是值传递、指针传递和引用传递
#include <iostream>
 
void changeValue(int num) {
    num = 5;
}

void changeValue1(int* numPtr) {
    *numPtr = 5;
}

void changeValue2(int& numRef) {
    numRef = 5;
}


int main() {
    int num = 10;
    changeValue(num);
    std::cout << "值传递不变: "<<num << std::endl; // 输出结果为10,原始值未被修改
    
    int num1 = 10;
    changeValue1(&num1);
    std::cout <<"指针传递可改变: "<<num1 << std::endl; // 输出结果为5,原始值被修改

    int num2 = 10;
    changeValue2(num2);
    std::cout <<"引用传递可改变: " <<num2 << std::endl; // 输出结果为5,原始值被修改

    
    return 0;
}
串的模式匹配
BF算法

在这里插入图片描述

#include<iostream>
using namespace std;
#define MAXLEN 255 // 预定义最大串长为255
// 定长数组实现(定长顺序存储 )
typedef struct
{
    char ch[MAXLEN]; // 每个分量存储一个字符
    int length;      // 串的实际长度
} String;

//这里直接使用string和length()函数
int Index_BF(string s, string t) {  
    int i = 0, j = 0;  
    int lens = s.length(); 
    int lent = t.length();  
    while (i <= lens - lent) { //这里比较次数为lens-lent+1次 
        j = 0; // 每次从头开始比较子串t 

        while (j < lent && s[i + j] == t[j]) {  //逐个比较s串和t串
            j++;  
        }  
        if (j == lent) {  
            return i; // 找到匹配,返回起始索引下标  
        }  

        i++; // 如果不匹配,i向前移动一位  
    }  
    return -1; // 未找到匹配  
}

int main(){
    string a="ktuh2agj";
    string b="2agj";    
    cout<<Index_BF(a,b)<<endl;//返回的是索引下标
    return 0;
}
KMP算法

在这里插入图片描述

#include<iostream>
#include<cstring>

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

//求模式串T的next数组:想一想自己怎么样实现这个求得过程?
//这里是指针传递
void get_next(SString T,int next[]){
    int i=1,j=0;
    next[1]=0;
    while (i<T.length){//第一个的next值已经确定
        if(j==0||T.ch[i]==T.ch[j])
        {
            ++i;++j;
            next[i]=j;
        }
        else{
            j=next[j];
        }
        
    }
}

//KMP算法是三个人提出的故而叫做KMP算法
int Index_KMP(SString S, SString T, int next[])
{
    int i = 1, j = 1;
    while (i <= S.length && j <= T.length)  //i永远不递减
    {
        if (j == 0 || S.ch[i] == T.ch[j]) //字符匹配成功,指针后移
        {
            ++i;
            ++j;
        }
        else  //字符匹配失败, 根据next跳过前面的一些字符
            j = next[j];
    }
    if (j > T.length)  // 匹配成功
        return i - T.length;
    else
        return 0;
}
void kmp(){
    SString S, T;  
    int next[MAXLEN];  
  
    // 初始化主串S  
    strcpy(S.ch, "ABABDABACDABABCABAB");  
    S.length = strlen(S.ch);  
  
    // 初始化模式串T  
    strcpy(T.ch, "ABABCABAB");  
    T.length = strlen(T.ch);  
  
    // 计算模式串T的next数组  
    get_next(T, next);  
  
    // 打印next数组(可选)  
    printf("Next array: ");  
    for (int i = 1; i <= T.length; i++) {  
        printf("%d ", next[i]);  
    }  
    printf("\n");  
  
    // 使用KMP算法查找模式串T在主串S中的位置  
    int index = Index_KMP(S, T, next);  
    if (index != 0) {  
        printf("Pattern found at index: %d\n", index);  
    } else {  
        printf("Pattern not found.\n");  
    }      
}

int main(){
    //KMP
    kmp();
    
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值