数据结构学习【串 顺序结构 KMP和KMP改进实现 C++】

数据结构学习【串 顺序结构 KMP C++】

本次实现的是串的顺序存储结构。

串的实现方式

串的实现方式可以分为3种。
① 定长顺序存储表示(本文的实现方式)
即固定大小

typedef struct {
    
    
    char ch[MaxSize];
    int length;
}SString;

②堆分配存储表示
即动态分配

typedef struct {
    
    
    char *ch;
    int length;
}HString;

③块链存储表示

typedef struct StringNode{
    
    
    char ch[4];   	//每个结点多存几个字符,提高存储密度
    struct StringNode *next;
}StringNode,*String;

KMP理解

推荐一个KMP算法求next数组代码实现的讲解视频。
求next数组代码实现的讲解视频

code

#include <iostream>
using namespace std;
#define MaxSize 255

//采用定长顺序存储实现串

// ADT
//最小操作子集
// StrAssign(&T,chars) 赋值操作。把串T赋值为chars
// StrCompare(S,T) 比较操作。若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0。
// StrLength(S) 求串长。
// SubString(&Sub,S,pos,len) 求子串。用sub返回串S的第pos个字符起长度为len的子串
// Concat(&T,S1,S2) 串联接。用T返回由S1、S2连接而成的新串
//其他操作
// StrCopy(&T,S) 复制操作。由串S复制得到串T
// StrEmpty(S) 判空操作
// ClearString(S)清空操作。将串清为空串
// DestroyString(&S) 销毁串。将串S销毁
// Index(S,T) 定位操作。若子串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的位置;否则函数值为0
// Index_KMP(S,T) 用KMP算法实现定位操作

typedef struct {
    
    
    char ch[MaxSize];
    int length;
}SString;

//最小操作子集
// 赋值操作。把串T赋值为chars
bool StrAssign(SString &T,char* chars);
// 比较操作。若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0。
int StrCompare(SString S,SString T); 
// 求串长。
int StrLength(SString S); 
// 求子串。用sub返回串S的第pos个字符起长度为len的子串
bool SubString(SString &Sub,SString S,int pos,int len); 
// 串联接。用T返回由S1、S2连接而成的新串
bool Concat(SString &T,SString S1,SString S2);

//其他操作
// 求char*字符串长度
int CharsLength(char* chars);
// 输出串
void PrintString(SString S);
// 复制操作。由串S复制得到串T
bool StrCopy(SString &T,SString S); 
// 判空操作
bool StrEmpty(SString S); 
// 清空操作。将串清为空串
bool ClearString(SString S);
// 销毁串。将串S销毁
bool DestroyString(SString &S); 
// 定位操作。若子串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的位置;否则函数值为0
int Index(SString S,SString T);
// 用KMP算法实现定位操作
int IndexKMP(SString S,SString T); 
// 用改进的KMP算法实现定位操作
int IndexKMPPlus(SString S,SString T); 
// 求模式串T的next数组
void GetNext(SString T,int next[]); 
// 求模式串T的next数组(改进算法)
void GetNextVal(SString T,int nextVal[]); 


int main(){
    
    
    char tmp1[]="abcd";
    char tmp2[]="abce";
    SString S1;
    StrAssign(S1,tmp1);
    SString S2;
    StrAssign(S2,tmp2);
    printf("S1:");
    PrintString(S1);
    printf("\n");
    printf("S2:");
    PrintString(S2);
    printf("\n");
    //比较
    printf("比较结果:%d\n",StrCompare(S1,S2));
    // 截取子串
    SString sub;
    SubString(sub,S1,2,3);
    printf("sub:");
    PrintString(sub);
    printf("\n");
    // 联结两个串为新串
    SString concat;
    Concat(concat,S1,S2);
    printf("concat:");
    PrintString(concat);
    printf("\n");
    // 定位
    int idx=0;
    idx=Index(S1,sub);
    printf("定位结果:%d\n",idx);
    // KMP定位
    idx=IndexKMP(S1,sub);
    printf("KMP定位结果:%d\n",idx);
    idx=IndexKMPPlus(S1,sub);
    printf("改进的KMP定位结果:%d\n",idx);
    system("pause");
}

//最小操作子集
// 赋值操作。把串T赋值为chars
bool StrAssign(SString &T,char* chars){
    
    
    if(CharsLength(chars)>MaxSize-1)//如果char字符数组大于MaxSize-1,则返回错误
        return false;              //(这里采用王道书上的方法,第零位不放元素,所以最多存储MaxSize-1个元素)
    T.length=CharsLength(chars);
    for(int i=1;i<=T.length;i++){
    
    
        T.ch[i]=*(chars+i-1);
    }   
    return true;
}

// 比较操作。若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)
        return false;
    Sub.length=len;
    for(int i=1;i<=len;i++)
        Sub.ch[i]=S.ch[pos+i-1];
    return true;
}
// 串联接。用T返回由S1、S2连接而成的新串
bool Concat(SString &T,SString S1,SString S2){
    
    
    if(S1.length+S2.length>MaxSize-1)
        return false;
    T.length=S1.length+S2.length;
    for(int i=1;i<=S1.length;i++){
    
    
        T.ch[i]=S1.ch[i];
    }
    for(int i=1;i<=S2.length;i++){
    
    
        T.ch[S2.length+i]=S2.ch[i];
    }
    return true;
}

//其他操作
// 求char*字符串长度
int CharsLength(char* chars){
    
    
    int length=0;
    while(chars[length]) length++;
    return length;
}
// 输出串
void PrintString(SString S){
    
    
    for(int i=1;i<=S.length;i++){
    
    
        printf("%c",S.ch[i]);
    }
}
// 复制操作。由串S复制得到串T
bool StrCopy(SString &T,SString S){
    
    
    T.length=S.length;
    for(int  i=1;i<=S.length;i++){
    
    
        T.ch[i]=S.ch[i];
    }
    return true;
}
// 判空操作
bool StrEmpty(SString S){
    
    
    if(S.length==0) return true;
    else return false;
}
// 清空操作。将串清为空串
bool ClearString(SString S){
    
    
    S.length=0;
    return true;
}
// 定位操作。若子串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的位置;否则函数值为0
// 朴素算法
int Index(SString S,SString T){
    
    
    int i=1,sl=S.length,tl=T.length;
    SString sub;
    while(i<=sl-tl+1){
    
    
        SubString(sub,S,i,tl);
        if(StrCompare(sub,T)!=0) i++;
        else return i;
    }
    return 0;

}
// 用KMP算法实现定位操作
int IndexKMP(SString S,SString T){
    
    
    int i=1,j=1;
    int next[T.length+1];
    GetNext(T,next);
    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;//匹配失败
}
// 用改进的KMP算法实现定位操作
int IndexKMPPlus(SString S,SString T){
    
    
    int i=1,j=1;
    int nextVal[T.length+1];
    GetNextVal(T,nextVal);
    while(i<=S.length&&j<=T.length){
    
    
        if(j==0||S.ch[i]==T.ch[j]){
    
    
            i++;
            j++;//继续比较后继字符
        }else{
    
    
            j=nextVal[j];//模式串向右移动
        }
    }
    if(j>T.length)
        return i-T.length;//匹配成功
    else
        return 0;//匹配失败
}
// 求模式串T的next数组
void GetNext(SString 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;
        }else{
    
    
            j=next[j];
        }
    }
}
// 求模式串T的next数组(改进算法)
void GetNextVal(SString T,int nextVal[]){
    
    
    int next[T.length+1];
    GetNext(T,next);
    nextVal[1]=0;
    for(int i=2;i<=T.length;i++){
    
    
        if(T.ch[next[i]]==T.ch[i])
            nextVal[i]=nextVal[next[i]];
        else
            nextVal[i]=next[i];
    }
}

运行结果

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/toro180/article/details/122491783
今日推荐