数据结构与算法---字符串(下)

  前面两篇文章,分别介绍了字符串的概念、抽象数据类型、KMP模式匹配算法。这篇文章,我们来学习字符串的一些常用算法。

字符串的相关操作算法

StrAssign:

/*
功能:生成一个其值等于Chars的串T
*/
Status StrAssign(String T, char *chars)
{
    int i;
    if (chars[0] > MAXSIZE)
        return ERROR;
    T[0] = chars[0];        //chars[0]存放的是字符chars的长度   T[0]存放着的是串T的长度
    for (i = 1; i <= chars[0]; i++)
        T[i] = *(chars + i - 1);    //将chars的字符依次存入T中
    return OK;
}

这个算法的功能是创建字符串,没什么复杂的地方。

StrCopy:

/*
功能:由串S复制得串T
*/
Status StrCopy(String S, String T)
{
    int i;
    for (i = 0; i <= S[0]; i++)
        T[i] = S[i];           //将S串的字符依次赋给T串
    return OK;
}

我们在C#中,需要复制某个字符串给另一个字符串,只需调用String类的Copy()方法即可。Copy()方法的具体算法,其实就是上面的代码所演示的。古语有云:”知其然,知其所以然”,编程需要锻炼,不仅仅是锻炼我们的编码速度,而是要从编程中领悟编程的思想。学习经典算法,就是领悟编程思想。

StrEmpty:

/*
功能:判断字符串是否为空串,是返回True,否则返回False
*/
Status StrEmpty(String S)
{
    if (S[0] == 0)   //字符长度为0,则为空串
        return TRUE;
    else
    return FALSE;
}

判断字符串是否为空的算法,是不是感觉算法其实也挺简单的?简单的需求就用简单的算法,其实算法还是有难度的,特别是一些经典的算法。但是不要气馁,人生的乐趣就是在不断克服苦难中得到的。只做简单的事情,人生多无趣?

StrCompare:

/*
功能:比较两个字符串
操作:如果两个串S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0
*/
int  StrCompare(String S, String T)
{
    int i;
    for (i = 1; i <= S[0] && i <= T[0]; ++i)
    {
        if (S[i != T[i]])         //判断两个字符串中的字符是否相等
            return S[i] - T[i];   //根据返回值是否大于零,来判断两个串的大小
        else
            return S[0] - T[0];   //如果两个字符串相等,返回0
    }
}

这个算法,是判断两个字符串是否相等。

ClearString:

/*
功能:将串S清空为空串
*/
Status ClearString(String S)
{
    S[0] = 0; //将字符长度设置为0,串变为空串。
    return OK;
}

这个算法,是清空字符串。

StrConcat:

/*
功能:用T返回S1和S2联接而成的新串。若未截断,返回True,否则返回FALSE
*/
Status Concat(String T, String S1, String S2)
{
    int i;

    if (S1[0] + S2[0] <= MAXSIZE)   //未截断
    {
        for (i = 1; i <= S1[0]; i++)
            T[i] = S1[i];
        for (i = 1; i <= S2[0]; i++)
            T[S1[0] + i] = S2[i];
        T[0] = S1[0] + S2[0];
        return TRUE;
    }
    else                         //截断
    {
        for (i = 1; i <= S1[0]; i++)
            T[i] = S1[i];
        for (i = 1; i <= MAXSIZE - S1[0]; i++)
            T[S1[0] + 1] = S2[i];
        S1[0] = MAXSIZE;
        return FALSE;
    }
}

这个算法的功能是实现,两个字符串的拼接。需要注意的是,拼接时可能出现空间不足,截断字符串的可能。所以,算法中要分情况来操作。

我们来看看SubString方法的实现,这个方法一定不陌生吧。

/*
功能:用Sub返回S串中Pos位置起len个长度的字串
初始条件:串S存在,1<=pos<=StrLength(S) 0<=len<=StrLength(S)-Pos+1
*/
Status SubString(String Sub, String S, int pos, int len)
{
    int i;
    if (pos<1 || pos>S[0] || len<0 || len>S[0] - pos + 1)
        return FALSE;
    for ( i = 1; i <= len; i++)
        Sub[i] = S[pos + i - 1];
    Sub[0] = len;
    return OK;
}

Index:

/*
功能:返回字串T在主串S的pos位置之后的位置,若不存在,返回值为0;
初始条件:串S、T存在,1<=Pos<=StrLength(S)
*/
int  Index(String S, String T, int pos)
{
    int i = pos; //i的当前位置
    int j = 1;  //子串T的当前位置
    while (i <= S[0])
    {
        if (S[i] == T[j])   //当前位置字符相等,继续匹配
        {
            ++i;
            ++j;
        }
        else               //当前位置匹配不相等
        {              
            j = 1;   //   j回溯到字串的第一个位置
            i = i - j + 2; //主串位置回溯到上次匹配成功位置的下个位置,
        }
    }
    if (j > T[0])
        return i - T[0];
    else
        return 0;
}

其实这个方法就是我在数据结构与算法---字符串(中)文章中,讲到的朴素模式匹配的算法。

我们再看一个通过调用其它字符串方法来完成匹配的算法:

/*
功能:返回子串T在主串S中pos位置之后出现的位置,如不存在返回0
初始条件:1<=pos<=StrLength(S) 
*/
int Index2(String S, String T, int pos)
{
    int i = pos;
    int n, m;   //n表示主串S的长度,m表示子串T的长度
    if (i > 0)
    {
        n = strLength(S); //通过调用Strlength()来获取主串S的长度
        m = strLength(T); //通过调用Strlength()来获取子串T的长度
        while (i <= n - m + 1)
        {
            SubString( sub,  S,  i,n); //通过调用SubString()来获取从i位置起n个长度的子串sub
            if (StrCompare(T, sub) == 0) //通过调用StrCompare方法,来判断获取的Sub子串是否已字串T相等
                return i;   //相等则返回i位
            else
                i++;    //不相等,则i回溯到下个位置
        }
    }
    return 0;
}

通过观察这个算法,调用了之前讲到的一些算法。其实,字符串的基本操作也就是那么几个算法。复杂的操作,就需要方法之间互相配合。

好了, 字符串这章已经讲完了。

原文地址:https://www.cnblogs.com/VitoCorleone/p/3945220.html