c语言 数据结构实现之字符串

c语言 数据结构实现之字符串

串采用定长顺序存储结构(由c4-1.h定义)的基本操作(13个),包括算法4.2,4.3,4.5  

实现效果图:


#include <stdio.h>
#include <string.h>
#include <malloc.h>
// SString是数组,故不需引用类型
#define OK 1
#define TRUE 1
#define FALSE 0
#define ERROR 0
#define INFEASIBLE -1  

#define DestroyString ClearString // DestroyString()与ClearString()作用相同
#define MAX_STR_LEN 40 // 用户可在255(1个字节)以内定义最大串长
typedef char SString[MAX_STR_LEN+1]; // 0号单元存放串的长度
typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等  

Status StrAssign(SString T,char *chars)
{ // 生成一个其值等于chars的串T
  int i;
  if(strlen(chars)>MAX_STR_LEN)
    return ERROR;
  else
  {
    T[0]=strlen(chars);
    for(i=1;i<=T[0];i++)
      T[i]=*(chars+i-1);
    return OK;
  }
} 

void StrCopy(SString T,SString S)
{ // 由串S复制得串T
  int i;
  for(i=0;i<=S[0];i++)
    T[i]=S[i];
} 

Status StrEmpty(SString S)
{ // 若S为空串,则返回TRUE,否则返回FALSE
  if(S[0]==0)
    return TRUE;
  else
    return FALSE;
} 

int StrCompare(SString S,SString T)
{// 初始条件:串S和T存在。操作结果:若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0
  int i;
  for(i=1;i<=S[0]&&i<=T[0];++i)
    if(S[i]!=T[i])
      return S[i]-T[i];
  return S[0]-T[0];
} 

int StrLength(SString S)
{ // 返回串S的元素个数
  return S[0];
} 

void ClearString(SString S)
{ // 初始条件:串S存在。操作结果:将S清为空串
  S[0]=0; // 令串长为零
} 

Status Concat(SString T,SString S1,SString S2) // 算法4.2改
{ // 用T返回S1和S2联接而成的新串。若未截断,则返回TRUE,否则FALSE
  int i;
  if(S1[0]+S2[0]<=MAX_STR_LEN)
  { // 未截断
    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
  { // 截断S2
    for(i=1;i<=S1[0];i++)
      T[i]=S1[i];
    for(i=1;i<=MAX_STR_LEN-S1[0];i++)
      T[S1[0]+i]=S2[i];
    T[0]=MAX_STR_LEN;
    return FALSE;
  }
} 

Status SubString(SString Sub,SString S,int pos,int len)
{ // 用Sub返回串S的第pos个字符起长度为len的子串。算法4.3
  int i;
  if(pos<1||pos>S[0]||len<0||len>S[0]-pos+1)
    return ERROR;
  for(i=1;i<=len;i++)
    Sub[i]=S[pos+i-1];
  Sub[0]=len;
  return OK;
} 

int Index(SString S,SString T,int pos)
{ // 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数值为0。
  // 其中,T非空,1≤pos≤StrLength(S)。算法4.5
  int i,j;
  if(1<=pos&&pos<=S[0])
  {
    i=pos;
    j=1;
    while(i<=S[0]&&j<=T[0])
      if(S[i]==T[j]) // 继续比较后继字符
      {
        ++i;
        ++j;
      }
      else // 指针后退重新开始匹配
      {
        i=i-j+2;
        j=1;
      }
      if(j>T[0])
        return i-T[0];
      else
        return 0;
  }
  else
    return 0;
} 

Status StrInsert(SString S,int pos,SString T)
{ // 初始条件:串S和T存在,1≤pos≤StrLength(S)+1
  // 操作结果:在串S的第pos个字符之前插入串T。完全插入返回TRUE,部分插入返回FALSE
  int i;
  if(pos<1||pos>S[0]+1)
    return ERROR;
  if(S[0]+T[0]<=MAX_STR_LEN)
  { // 完全插入
    for(i=S[0];i>=pos;i--)
      S[i+T[0]]=S[i];
    for(i=pos;i<pos+T[0];i++)
      S[i]=T[i-pos+1];
    S[0]+=T[0];
    return TRUE;
  }
  else
  { // 部分插入
    for(i=MAX_STR_LEN;i>=pos+T[0];i--)
      S[i]=S[i-T[0]];
    for(i=pos;i<pos+T[0]&&i<=MAX_STR_LEN;i++)
      S[i]=T[i-pos+1];
    S[0]=MAX_STR_LEN;
    return FALSE;
  }
} 

Status StrDelete(SString S,int pos,int len)
{ // 初始条件:串S存在,1≤pos≤StrLength(S)-len+1
  // 操作结果:从串S中删除第pos个字符起长度为len的子串
  int i;
  if(pos<1||pos>S[0]-len+1||len<0)
    return ERROR;
  for(i=pos+len;i<=S[0];i++)
    S[i-len]=S[i];
  S[0]-=len;
  return OK;
} 

Status Replace(SString S,SString T,SString V) // 此函数与串的存储结构无关
{ // 初始条件:串S,T和V存在,T是非空串
  // 操作结果:用V替换主串S中出现的所有与T相等的不重叠的子串
  int i=1; // 从串S的第一个字符起查找串T
  Status k;
  if(StrEmpty(T)) // T是空串
    return ERROR;
  do
  {
    i=Index(S,T,i); // 结果i为从上一个i之后找到的子串T的位置
    if(i) // 串S中存在串T
    {
      StrDelete(S,i,StrLength(T)); // 删除该串T
      k=StrInsert(S,i,V); // 在原串T的位置插入串V
      if(!k) // 不能完全插入
        return ERROR;
      i+=StrLength(V); // 在插入的串V后面继续查找串T
    }
  }while(i);
  return OK;
} 

void StrPrint(SString T)
{ // 输出字符串T。另加
  int i;
  for(i=1;i<=T[0];i++)
    printf("%c",T[i]);
  printf("\n");
}
void get_next(SString T,int next[])
{ // 求模式串T的next函数值并存入数组next。算法4.7
  int i=1,j=0;
  next[1]=0;
  while(i<T[0])
    if(j==0||T[i]==T[j])
    {
      ++i;
      ++j;
      next[i]=j;
    }
    else
      j=next[j];
} 

void get_nextval(SString T,int nextval[])
{ // 求模式串T的next函数修正值并存入数组nextval。算法4.8
  int i=1,j=0;
  nextval[1]=0;
  while(i<T[0])
    if(j==0||T[i]==T[j])
    {
      ++i;
      ++j;
      if(T[i]!=T[j])
        nextval[i]=j;
      else
        nextval[i]=nextval[j];
    }
    else
      j=nextval[j];
} 

int Index_KMP(SString S,SString T,int pos,int next[])
{ // 利用模式串T的next函数求T在主串S中第pos个字符之后的位置的KMP算法。
  // 其中,T非空,1≤pos≤StrLength(S)。算法4.6
  int i=pos,j=1;
  while(i<=S[0]&&j<=T[0])
    if(j==0||S[i]==T[j]) // 继续比较后继字符
    {
      ++i;
      ++j;
    }
    else // 模式串向右移动
      j=next[j];
  if(j>T[0]) // 匹配成功
    return i-T[0];
  else
    return 0;
} 

void main()
{
  int i,*p;
  SString s1,s2; // 以教科书算法4.8之上的数据为例
  StrAssign(s1,"aaabaaaab");
  printf("主串为: ");
  StrPrint(s1);
  StrAssign(s2,"aaaab");
  printf("子串为: ");
  StrPrint(s2);
  p=(int*)malloc((StrLength(s2)+1)*sizeof(int)); // 生成s2的next数组空间
  get_next(s2,p); // 利用算法4.7,求得next数组,存于p中
  printf("子串的next数组为: ");
  for(i=1;i<=StrLength(s2);i++)
    printf("%d ",*(p+i));
  printf("\n");
  i=Index_KMP(s1,s2,1,p); // 利用算法4.6求得串s2在s1中首次匹配的位置i
  if(i)
    printf("主串和子串在第%d个字符处首次匹配\n",i);
  else
    printf("主串和子串匹配不成功\n");
  get_nextval(s2,p); // 利用算法4.8,求得next数组,存于p中
  printf("子串的nextval数组为: ");
  for(i=1;i<=StrLength(s2);i++)
    printf("%d ",*(p+i));
  printf("\n");
  printf("主串和子串在第%d个字符处首次匹配\n",Index_KMP(s1,s2,1,p));
  getchar();
} 

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • C语言数据结构实现字符串分割的实例

    C语言数据结构实现字符串分割的实例 以下为"字符串分割"的简单示例: 1. 用c语言实现的版本 #include<stdio.h> /* 根据空格分隔字符串 */ int partition(char *src, char *par, int pos) { int i,j; i = pos; //取到第一个非空格字符 while(src[i] == ' ') { ++i; } if(src[i] != '\0') { j = 0; while((src[i] != '\0'

  • C语言数据结构之模式匹配字符串定位问题

    C语言数据结构之模式匹配字符串定位问题 主要实现了三种字符串的模式匹配,主要包括字符串子操作的集合,字符串指针回溯,和KMP算法 头文件  #ifndef INDEXHEAD_H_INCLUDED #define INDEXHEAD_H_INCLUDED #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXLEN 255 typedef char Sstring[MAXLEN + 1

  • c语言 数据结构实现之字符串

    c语言 数据结构实现之字符串 串采用定长顺序存储结构(由c4-1.h定义)的基本操作(13个),包括算法4.2,4.3,4.5   实现效果图: #include <stdio.h> #include <string.h> #include <malloc.h> // SString是数组,故不需引用类型 #define OK 1 #define TRUE 1 #define FALSE 0 #define ERROR 0 #define INFEASIBLE -1 #

  • C语言 数据结构与算法之字符串详解

    目录 串的定义 串的比较 串的抽象数据类型 串的初始化 相关定义初始化 定长类初始化 串的堆式顺序存储结构(Heap) 初始化堆字符串 赋值操作 比较两个堆字符串的大小 串的定义 零个或多个字符组成的有限序列 串的比较 串的比较实际上是在比较串中字符的编码 存在某个k < min(n,m),使得ai = bi (i = 1,2,3,4..k) 如果 ak < bk  -->  那么srt1 < srt2 (反之也成立) 除去相等的字符,在第一个不相等的字符位置以Ascii码进行比较

  • C++语言数据结构 串的基本操作实例代码

    C语言数据结构 串的基本操作实例代码 输出结果: 实现代码: #include<iostream> using namespace std; typedef int Status; #define Max 20 #define OK 1 #define ERROR 0 #define OVERLOE -2 typedef struct//堆分配表示串 { char *ch; int length; }HString; //====================================

  • C语言数据结构之动态分配实现串

    C语言数据结构之动态分配实现串 说明:堆分配存储实现串时,串并不是以'\0', 而是用数据项int length来表示的,所以和传统的c语言操作字符串有所不同. 头文件 #ifndef PILEHEAD_H_INCLUDED #define PILEHEAD_H_INCLUDED #include <stdio.h> #include <stdlib.h> typedef struct { char* ch ; int len ; }HString ; int StrAssign(

  • C语言数据结构之中缀树转后缀树的实例

    C语言数据结构之中缀树转后缀树的实例 对于一个中缀表达式 a+b*c*(d-e/f) 转换成后缀是这样的形式 abc*def/-+ 后缀表达式是相当有用处的,转换成后缀表达式后求值会简单很多.那么该如何转换呢? 网上关于这方面的资料一搜一大把,每本数据结构的书中都会提及这个算法,在这个算法中,用到 栈 这个数据结构. 1,关键是比较运算符的优先级,谁的优先级高,谁就出现在前面上面的表达式中,有括号的时候括号优先级最高,*/次之,+-最后. 在上面的表达式中+的优先级不如*的高,因此,在后缀表达式

  • Golang语言如何高效拼接字符串详解

    目录 01.介绍 02.操作符 + 03.strings.Join 方法 04.fmt.Sprint 方法 05.bytes.Buffer 类型 06.strings.Builder 类型 07.总结 01.介绍 在编程语言中,字符串是一种重要的数据结构.在 Golang 语言中,因为字符串只能被访问,不能被修改,所以,如果我们在 Golang 语言中进行字符串拼接操作,Golang 需要进行内存拷贝. 如果读者朋友们了解过 Golang 语言内存管理的相关知识,就会知道内存拷贝会带来性能消耗.

  • C语言 数据结构之数组模拟实现顺序表流程详解

    目录 线性表和顺序表 线性表 顺序表 静态顺序表 动态顺序表 代码已经放在Gitee上,需要可以小伙伴可以去看看 用C语言数组模拟实现顺序表 Gitee 线性表和顺序表 线性表 线性表(linear list)是n个具有相同特性的数据元素的有限序列,这是我们广泛使用的数据结构. 线性表在逻辑上是线性结构,也就说是连续的一条直线.但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储. 常见的线性表:顺序表.链表.栈.队列.字符串- 顺序表 顺序表是用一段物理地址连

  • C语言数据结构线性表教程示例详解

    目录 线性表 顺序表 线性表 数据结构里我们时常看到什么什么表,线性表是最基本.最简单.也是最常用的一种数据结构,其他各种表的万恶之源就是这个线性表,他是个啥其实顾名思义: 一个线性表是n个具有相同特性的数据元素的有限序列.数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意,这句话只适用大部分线性表,而不是全部.比如,循环链表逻辑层次上也是一种线性表(存储层次上属于链式存储,但是把最后一个数据元素的尾指针指向了首位结点). 说的这么复杂其实就是

随机推荐