数据结构笔记——第三章 串

4.1 串

基本概念

串:由n个字符组成的有序序列(特殊的线性表)。记作:s=”s0,s1,…s(n-1)”,其中s为串名,n为串的长度,双引号括起来的字符序列为串的值,每个字符s(i)(0<i<n-1)可以是任意的ASCII码字符,一般为字母(需要注意大小写),数字,标点符号等可显字符。

 

子串:一个串中任意个连续的字符组成的子序列。包含子串的串称为该子串的主串。

 

与线性表的差别:
(1)线性表的数据元素可以是任意数据类型,串的数据元素只能是字符类型;

(2)线性表一次操作一个数据元素,串一次操作若干个数据元素,即一个子串。

 

字符在串中的位置:串中每个字符的顺序编号(为大于等于0的整数)

 

串的抽象数据类型

数据集合:可以表示为字符序列s0,s1,…s(n-1),每个数据元素的类型为字符类型。例如:

S1=”I am a student”,S2=”student”

操作集合:

  1. 初始化Initiate(S)
  2. 赋值Assign(S,T)  把串T的值赋给串S
  3. 求长度Length(S):如:Length(S1)=14
  4. 比较Compare(S4,S1)
  5. 插入Insert(S,pos,T): 在串S的第pos个字符前插入串T,如:Insert(S1,4,”not”)操作后,串S1=”I am not a student”
  6. 删除Delete(S,pos,len):若满足条件0<pos<Length(S)-1,len>=1和pos+len<=Length(S)-1,则删除串S中从第pos个字符开始、长度为len个的子串,如:Delete(S1,6,7)操作后,串S1=”I am a”
  7. 取子串SubString(S,pos,len)
  8. 查找子串Search(S1,0,S2)
  9. 替换子串Replace(S,start,T)

 

 

C语言的串函数

 

 

 

 

4.2 串的存储结构

分类:顺序存储结构和链式存储结构

 

顺序存储结构又分为静态数组结构和动态数组结构

  1. 静态数组结构(静态分配内存方法定义数组)

 结构体定义如下:

typedef  struct

{

char str[MaxSize];

int Length;

}String;

MaxSize表示数组元素的个数,str表示数组名,length表示串的长度,String为结构体名

  1. 动态数组结构(动态分配内存方法定义数组)

结构体定义如下:

typedef sstruct

{                        

char *str;

int MaxLength;

int Length;

}DString;

动态数组的数组名和元素个数是分开定义的char *str; int MaxLength;

 

串的链式存储结构有单字符结点链和块链

  1. 单字符结点链(空间利用率低)

结构体定义如下:

typedef struct Node

{

char str;

struct Node *next;

}SCharNode;

 

  1. 块链

结构体定义如下:

typedef struct Node

{

char str[Number];

struct Node *next;

}NCharNode;

 

Number为每个结点数据域的字符数。当数值较大时,块链的空间利用率比单字符结点链高很多。当数值较大时,块链的空间利用率和串的顺序存储结构的空间利用率接近。

 

4.3 串基本操作的实现算法

1、静态数组下串基本操作的实现算法

串的静态数组结构体定义:

typedef struct

{

    char str[MaxSize];

    int length;

}String;

 

静态数组下串基本操作:

//初始化

void Initiate(String *S)

{

    S->length=0;

}



//插入子串

int Insert(String *S,int pos,String *T)       //在串S的pos位置插入子串T

{

    int i;

    if(pos<0||pos>S->length)

    {

        printf("pos参数错误!\n");

        return 0;

    }

    else if(S->length+T->length>MaxSize)

    {

        printf("数组空间不足无法插入!\n");

        return 0;

    }

    else

    {

        for(i=S->length-1;i>=pos;i--)

            S->str[i+T->length]=S->str[i];     //依次后移数据元素

        for(i=0;i<T->length;i++)

            S->str[pos+i]=T->str[i];           //插入

            S->length =S->length+T->length;    //产生新的串长度

            return 1;

    }

}



//删除子串

int Delete(String *S,int pos,int len)

{

    int i;

    if(S->length<=0)

    {

        printf("数组中无数据元素可删!\n");

        return 0;

    }

    else if(pos<0||len<0||pos+len>S->length)

    {

        printf("参数pos和len不合法!\n");

        return 0;

    }

    else

    {

        for(i=pos+len;i<=S->length;i++)

        {

            S->str[i-len]=S->str[i];            //依次前移数据元素

            S->length =S->length-len;           //产生新的串长度值

        }

    }

}





//取子串

int SubString(String S,int pos,int len,String *T)        //取串S中从pos位置开始长度为len的子串赋值给串T

{

    int i;

    if(pos<0||len<0||pos+len>S->length)

    {

        printf("参数pos和len不合法!\n");

        return 0;

    }

    else

    {

        for(i=0;i<len;i++)

            T->str[i]=S.str[pos+i];         //给子串T赋值

        T->length=len;

        return 1;                           //给子串的长度赋值

    }



}

 

2、动态数组下串的基本操作实现算法

串的动态数组结构体定义:

typedef struct

{

    char *str;

    int maxLength;

    int length;

}DString;

动态数组下串的操作:

//初始化

void Initiate(DString *S,int max,char *string)

{

    int i;

    S->str=(char *)malloc(sizeof(char)*max);    //申请动态数组空间

    S->maxLength=max;                        //置动态数组最大值

    S->length=strlen(string);                //置串的当前长度值

    for(i=0;i<S->length;i++)

        S->str[i]=string[i];                 //赋串值

}





//插入子串

int Insert(DString *S,int pos,DString T)

{

    int i;

    char *p;

    if(pos<0||pos>S->length)

    {

        printf("参数pos出错!\n");

        return 0;

    }

    else

    {

        if(S->length+T.length>S->maxLength)

        {

            p=(char *)realloc(S->str,(S->length+T.length)*sizeof(char));    //重新申请数组空间,原数组元素存放在新数组的前面

            if(p=NULL)

            {

                printf("内存空间不足!");

                return 0;

            }

        }



        for(i=S->length-1;i>=pos;i--)

            S->str[i+T.length]=S->str[i];             //依次后移数据元素



        for(i=0;i<T.length;i++)

            S->str[pos+i]=T.str[i];                   //插入



            S->length=S->length+T.length;             //产生新的串长度值

        return 1;

    }

}





//删除子串

int Delete(DString *S,int pos,int len)

{

    int i;



    if(S->length<=0)

    {

        printf("数组中未存放字符,无元素可删!\n");

        return 0;

    }

    else if(pos<0||len<0||pos+len>S->length)

    {

        printf("参数pos和len不合法!");

        return 0;

    }

    else

    {

        for(i=pos+len;i<=S->length-1;i++)

            S->str[i-len]=S->str[i];

        S->length=S->length-len;

        return 1;

    }

}





//取子串

int SubString(DString *S,int pos,int len,DString *T)

{

    int i;

    if(pos<0||len<0||pos+len>S->length)

    {

        printf("参数pos和len出错!");

        return 0;

    }

    else

    {

        for(i=0;i<len;i++)

            T->str[i]=S->str[pos+i];

        T->length=len;

        return 1;

    }

}





//撤销操作

void Destory(DString *S)           //释放动态数组内存空间

{

    free(S->str);

    S->maxLength=0;

    S->length=0;

}

4.4 串的模式匹配算法(查找)

常用顺序结构下串的模式匹配算法:Brute-Force算法KMP算法

Brute-Force算法(重要)

KMP算法

猜你喜欢

转载自blog.csdn.net/qq_40270579/article/details/81099528