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

前面两篇文章,分别介绍了字符串的概念、抽象数据类型、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;
}

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

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

时间: 2024-10-10 20:21:28

数据结构与算法---字符串(下)的相关文章

【转】数据结构与算法(下)

这篇文章是常见数据结构与算法整理总结的下篇,上一篇主要是对常见的数据结构进行集中总结,这篇主要是总结一些常见的算法相关内容,文章中如有错误,欢迎指出. 一.概述 二.查找算法 三.排序算法 四.其它算法 五.常见算法题 六.总结 一.概述 以前看到这样一句话,语言只是工具,算法才是程序设计的灵魂.的确,算法在计算机科学中的地位真的很重要,在很多大公司的笔试面试中,算法掌握程度的考察都占据了很大一部分.不管是为了面试还是自身编程能力的提升,花时间去研究常见的算法还是很有必要的.下面是自己对于算法这

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

   hey,you guys. 好久没有继续我们的数据结构学习了,今天让我们一起来学习,开发中非常重要的一种数据类型--字符串.关于字符串,大家应该不会陌生.例如,我们做web开发,需要校验用户输入的注册信息是否合法,或者判断用户输入的账户.密码.是否正确等等.我们通过调用字符串的相关函数,就可以解决我们的需求.古语有云:"知其然,知其所以然".我们要做的,不仅仅是会调用字符串的方法,更要明白这些方法的原理.例如,在没有学习字符串之前,我认为要比较两个字符串是否相等,只需这样: st

MySQL索引背后的数据结构及算法原理(下)

为了讨论索引策略,需要一个数据量不算小的数据库作为示例.本文选用MySQL官方文档中提供的示例数据库之一:employees.这个数据库关系复杂度适中,且数据量较大.下图是这个数据库的E-R关系图(引用自MySQL官方手册): 下载文件后使用下面的语句将数据库导入: tar -xjf $HOME/Downloads/employees_db-full-1.0.4.tar.bz2 //解压缩,进入目录 cd employees_db/ //导入数据库root为用户名 mysql -t -u roo

数据结构与算法----树(下)

  大家好,今天继续学习树的数据结构.在上一章,我们讲树的孩子兄弟表示法时,提到了二叉树.今天,我们就来学习二叉树的相关性质.  一.二叉树定义: 二叉树(Binary Tree):n(n≥0)个结点的有限集合,该集合或者为空集(为空时,称为空树),或者由一个根结点.两棵互不相交.称为根结点的左子树.右子树的二叉树组成.(Note:大家注意了,我们在给出二叉树定义时,我们利用了递归概念.就是先给出二叉树概念,再用二叉树概念去解释二叉树.递归是一种很重要的方法,在数据结构中是很重要的,我们会在后面

C#数据结构和算法-字符串、String 类和StringBuilder类

*本文为摘抄笔记* Preface当程序需要对String对象进行许多改变时会用到StringBuilder类.因为字符串和String对象都是不可改变的,而StringBuilder对象则是易变的.String类不可变,就意味着每次对象进行改变时都需要创建一个新的对象副本.如果在创建长的字符串,或者是对相同对象进行许多改变,那么就应该用StringBuilder类来代替.StringBuilder对象是可变的,性能会更好. 字符串是字符的序列,可以包含字母.数字和其他符号.C#语言中,用双引号

数据结构与算法-字符串写出一个strlen函数

写出一个strlen函数 int strlen( const char *str ) //输入参数const { assert( str != NULL ); //断言字符串地址非0 int len=0; while( (*str++) != '' ) { len++; } return len; }

数据结构与算法-字符串是否为回文

判断一个字符串是否为回文 bool CheckStr(const char* str) { int Len = strlen(str); for (int i = 0; i < Len; ++i) { if (*(str + i) != (*(str + (Len - i - 1)))) return false; } return true; } int SymmetricString( const char *ch) { int len=strlen(ch); int i=0,j=len-1

数据结构与算法 - 字符串

题型1:如何统计字符中有多少个单词? 方法1:使用空格作为分隔.如果测出某一个字符为非空格,而它前面的单词是空格,则表示"新的单词开始了"此时单词数count累加1.如果当前字符为非空格而其前面的字符也是非空格,则意味着仍然是原来那个单词的继续,count不应再累加1. 方法2:使用sstream中的isstreamstring实现单词的分隔,将字符串赋值给isstreamstring,以空格将单词分开. 1 2 3 4 5 6 7 8 9 10 11 12 13 char strin

数据结构与算法-字符串输出数组中的最大值

输出数组a中的最大值及其下标 #include<stdio.h> #define N 5 int main() { int a[N],i,max,t; for(i=0;i<N;i++) scanf("%d",&a[i]); max=a[0]; //把数组的第一个数赋值给max,此时对应的下标为0 t=0; for(i=1;i<N;i++) //从数组的第二个数开始判断,max是否是最大值 if(max<a[i]){ //不是最大值,就把该值赋值给m