第三部分:串,数组和广义表(重点为字符匹配算法)

一,

  • 串的定义
    串(String)是由零个或多个字符组成的有限序列。一般记为S=a1a2…an(n≥0)。
    在这里插入图片描述

    • 子串:一个串中任意个连续的字符组成的子序列称为该串的子串(包含空串)。包含子串的串称为主串。子串在主串中的位置是由子串的第一个字符在主串中的位置决定的。
      真子串是不包含自身的子串。
    • 空格串是由一个或多个空格组成的串。空格串不是空串。
    • 串的长度:指该串中字符的个数(包括空格)。空串的长度为0。
  • 串的基本操作

    Strlen(T) 求串T的长度
    Concat(T1,T2) 串连接
    Substr(S,pos,len) 求子串
    Index(S,T) 求子串T在主串S中的位置
    Replace(S,T,V) 用V替换主串S中出现的所有子串T
    Strlength(S) 求串S的长度
    StrInsert(S,pos,T) 在主串S的第pos个字符位置插入串T
    StrDelete(S,pos,len) 从主串S中删除第pos个字符起长度为len的子串
    StrCopy(T,S) 复制串S到串T
    StrCompare(S,T) 比较串S和串T
    
  • 串的存储结构

    • 顺序存储
      • 串的顺序存储结构
        #define MAXLEN 255
        typedef struct{
            char ch[MAXLEN+1]; //存储串的字符数组,下表为0-255,0经常闲置不用
            int length; //串的当前长度
        }SString;//顺序字符串
    
    • 链式存储
      • 优点:操作方便
      • 缺点:存储密度低,每个结点要存储指针域和字符域,指针域占用的空间较多
      • 改进:将多个字符放在一个结点中,每个结点存储多个字符和指针域,指针域指向下一个结点
    • 块链存储
     #define MAXBLOCKSIZE 255
     typedef struct Block{
         char data[MAXBLOCKSIZE];
         struct Block *next;
     }Block;
     typedef struct{
         Block *head,*tail; //头指针和尾指针
         int curlen; //当前串的长度
     }LString;
    
  • 串的模式匹配算法

    • 目的:
      在主串中找到第一个与模式串匹配的子串(即模式匹配)

    • BF算法(简单匹配,穷举法)
      在这里插入图片描述
      在这里插入图片描述

      • 算法代码:
        #include<stdio.h>
        #include<string.h>
        int Index_BF(SString S,SString T){
            int i=1,j=1;
            while(i<=S.length&&j<=T.length){
                if(S.ch[i]==T.ch[j]){
                    ++i;
                    ++j;
                }else{
                    i=i-j+2;//回溯到下一匹配
                    j=1;
                }
            }
            if(j>T.length)
                return i-T.length;//返回第一个匹配字符的下标
            else
                return 0;
        }
        
        • 算法时间复杂度
          在这里插入图片描述
    • KMP算法(链接KMP算法)
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述

在这里插入图片描述

 上图解释:看门牌算法:如果不成立,比如j=6时不成立,则看4,,不成立则看2,,不成立则看1.

在这里插入图片描述

+ 算法理解:最长前缀部分移至后缀部分,找前后缀时不包含不匹配的那一项,移动时只研究模式串(子串),模式串从数组下标1开始。最大前后缀长度+1为比较的部分。
  + 算法代码:
    ```c
    int Index_KMP(SString S,SString T,int next[]){
        int i=1,j=1;
        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;
    }
    void get_next(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];
            }
        }
    }
    ```
  + 算法时间复杂度
    主串的指针不需要回溯,提速到O(m+n)
  + KMP算法的改进

在这里插入图片描述

二,数组

  • 声明格式:数据类型 变量名称[行数][列数]
    在这里插入图片描述
    在这里插入图片描述

  • 数组的抽象数组类型定义
    例:二维数组的抽象数据对象和数据关系n=2(维数为2,二维数组),b1为第一维长度(行数),b2为第二维长度(列数),a为二维数组,a[i][j]为二维数组中第i行第j列的元素

  • 基本操作

      InitArray(&A,n);//初始化数组A
      DestroyArray(&A);//销毁数组A
      LocateElem(A,e,&i,&j);//查找元素e在数组A中的位置
      GetElem(A,i,j,&e);//获取数组A中第i行第j列的元素
      PutElem(A,i,j,e);//将元素e放入数组A中第i行第j列
      IsFull(A);//判断数组A是否已满
      IsEmpty(A);//判断数组A是否为空
    

三,广义表

  • 广义表的定义:
    广义表是n>=0个元素的有限序列,其中每个元素都是原子或者子表。原子是单元素,子表是广义表。广义表记作:LS=(a1,a2,…,an).一般大写字母表示广义表,小写字母表示原子。表头:LS的原子a1,表尾:LS中除了表头以外的部分构成的子表。
    在这里插入图片描述

  • 广义表的长度为最外层元素的个数
    广义表的深度定义为:广义表中最大元素的层数(括号的层数)。例如:A=(a,(b,c,d)),A的长度为2,深度为2。原子的深度为0,空表的深度为1.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值