【数据结构】串(一)—— 串的基础知识

  • 前言
  • 一、串类型的定义
  • 二、串的三种存储结构存
    • (1)定长顺序存储
    • (2)变长分配存储表示(堆分配)
    • (3)块链存储
      • 三种存储结构的总结
  • 三、串的操作
    • 串的初始化(以下基于顺序表):
    • 串的操作(代码):

前言

C语言字符串与数据结构中的串的区别:

C语言中有个字符串,数据结构中有个串,联系是二者都是存储字符的,区别在于前者我们直接定义数组存储,以 “ \0 ”结尾,如

char str[size];

而后者我们是把字符串看成一个线性表,定义成结构体形式,可以用链表,也可以是顺序表(结尾用length控制),以下是定义:如

typedef struct Str
{char elem[MAXSIZE+1];//elem数组用来存放串的元素int length;//定义一个串长度
}Str;

一、串类型的定义

串(string)(或字符串)是由零个或多个字符组成的有序序列,一般记为

 S=”a1a2…an”   (n>=0)

子串:串中任意连续的字符组成的子序列

串的逻辑结构:与线性表相类似,是限定了元素为字符的线性表。

线性表与串的操作的不同:线性表的操作主要针对表内的某一个元素;串的操作主要针对串内的一个子串;

char str[] = "abcdef";

注:数组str的长度为7;串的长度为6(不包含“\0”);

主串:包含子串的串相应的称为主串。
串的表示:
串有两种表示形式:顺序存储表示和链式存储表示。
顺序存储表示:串的顺序存储结构简称为顺序串,顺序串中的字符序列被顺序地存放在一组连续的存储单元中,主要有三种实现顺序串的方式。

二、串的三种存储结构存

储串的结构有三种:

  1. 定长顺序存储
  2. 堆分配存储
  3. 块链存储

(1)定长顺序存储

定长顺序存储的结构体:

typedef struct Str
{char elem[MAXSIZE+1];//elem数组用来存放串的元素int length;//定义一个串长度
}Str;

采用固定长度的数组(即静态数组)存储串。
例如:char a[7] = “abcdfg”;
此方式存储串时,需要预估串的长度提前申请足够的存储空间。目标串如果超过了数组申请的长度,超出部分会被自动舍弃(称为“截断”)。
例如:char a[3] = “abcdfg”;//实际上数组中只存储了 “abc” ,后边的被截断。

(2)变长分配存储表示(堆分配)

结构体定义:

typedef struct
{char *ch;          // 指向动态分配存储区首地址的字符指针int length;     // 串长度
}Str;

采用动态数组存储串。

在C语言中,存在着一个被称之为“堆”的自由存储区,用 malloc 函数和 free 函数管理,malloc 函数负责申请空间,free 函数负责释放空间。

例如:

char * a = (char*)malloc(5*sizeof(char));//创建 a 数组,动态申请5个 char 类型数据的存储空间

使用堆分配存储的优势在于:当发现申请的空间不够用时,可以通过 realloc() 函数重新申请更大的存储空间。

例如:

a = (char*)realloc(a, 10*sizeof(char));//前一个参数指申请空间的对象;第二个参数,重新申请空间的大小

使用 malloc 函数申请的存储空间,不会自动释放,需要程序员调用 free() 函数手动释放。如果不手动释放,当程序执行彻底结束,由操作系统进行回收。

例如:

free(a);//释放动态数组a申请的空间

(3)块链存储

块链存储,其实就是借用链表的存储结构来存储串。一般情况下使用单链表就足够了,而且不需要增设头结点。

在构建链表时,每个结点可以存放一个字符,也可以存放多个字符。

链表中最后一个结点的数据域不一定全被串值占满,通常会补上 “#” 或者其他特殊的字符和字符串中的字符区分开。

每个结点设置字符数量的多少和存储的串的长度、可以占用的存储空间以及程序实现的功能相关。

//块链存储
typedef struct Chunk{char ch[CHUNKSIZE];struct Chunk *next;
}Chunk;
typedef struct{Chunk *head,*tail;       //串的头尾指针 int curlen;                //串的当前长度
}LString;

三种存储结构的总结

在平时编写程序,经常会用到例如:char *a = ”abcd”;这种方式表示字符串,和上面三种存储方式最主要的区别是:这种方式用于表示常量字符串,只能使用,不能对字符串内容做修改(否则程序运行出错);而以上三种方式都可以对字符串进行删改的操作。

例如:

#include <stdio.h>
int main() {char* a="abcd";a[1]='b';return 0;
}

程序编译可以通过,运行失败,改成下面堆分配存储的方式就对了:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {char * a=(char*)malloc(4*sizeof(char));strcpy(a, "abcd");a[1]='e';printf("%s",a);return 0;
}

三种存储表示方式中,最常用的是堆分配存储,因为它在定长存储的基础上通过使用动态数组,避免了在操作串时可能因为申请存储空间的不足而丢失字符数据;和块链存储方式相比,结构相对简单,更容易操作。

三、串的操作

字符串可以有丰富的操作,在日常非数值运算大量的都是字符串的操作。归纳总结可以大致分为以下操作

(1)赋值 strassign()

(2)判空 strlen() strcmp()

(3)字符串比较 strcmp

(4)求字符串长度 strlen

(5)字符串拷贝 strcpy(数组名、字符串);

(6)字符串连接 strcat

(7)求字符串子串(截取字符串)

串的初始化(以下基于顺序表):

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define SIZE 20
typedef struct Str
{char elem[SIZE];//elem数组用来存放串的元素int length;//定义一个串长度
}Str;
//为串分配空间、赋值
int StrAssign(HString &T,char *chars){int i;
//  if(T.ch)free(T.ch);                 //释放T原有空间 【1】 char *c=chars;for(i=0;*c!='\0';++i,++c);     //求chars的长度iif(!i){T.ch=NULL;T.length=0;}else{if(!(T.ch=(char*)malloc(i*sizeof(char))))return 0; //分配空间的同时判断是否成功分配 for(int j=0;j<i;j++)T.ch[j]=chars[j];T.length=i;}return 1;
}

串的操作(代码):

void StrAssign(Str *s, const char *chars);//初始化串
void StrCpy(Str*s, Str*t);//拷贝串
int Getlength(Str *s);//获取串的长度
void Clear(Str *s);//清空串s
bool Inset(Str *s,int pos,Str *t);//在串s的pos位置插入串t
void Show(Str *s) ;//打印串
int BF(Str *s,Str *sub,int pos);//在串s里找第一个串sub,并返回串sub的第一个元素的下标
bool DeletePos(Str* s,int pos,int len);//在串中的pos位置开始删除len长度个元素
bool Delete(Str *s,int pos,Str *t);//在串中的pos位置开始删除串t
bool Replace(Str *s,Str *t,Str *v,int pos);//用v替换从pos位置开始的第一个t
bool RepIaceAll(Str *s,Str *t,Str *v);//在串s中查找到串t并用串v替换void StrAssign(Str *s, const char *chars)//初始化串
{assert(s != NULL);int len = strlen(chars);/*if(s->length<len){return;}*/s->length = len;for(int i = 0;i<len;i++){s->elem[i] = chars[i];}
}void StrCpy(Str*s, Str*t)//拷贝串
{for(int i = 0;i<t->length;i++){s->elem[i] = t->elem[i];}s->length = t->length;
}int Getlength(Str *s)//获取串的长度
{return s->length ;
}void Clear(Str *s)//清空串s
{s->length = 0;
}bool SubStr(Str *sub,Str *s,int pos,int len)//空白字符不拷贝
{if(pos < 0 || len < 1||pos >=s->length||pos+len>s->length-1){return false;}for(int i = pos;i<pos+len;i++){sub->elem[i-pos] = s->elem[i];}sub->length = len;return true;
}bool Inset(Str *s,int pos,Str *t)//在串s的pos位置插入串t
{assert(s!=NULL);assert(t!=NULL);if(pos<0||pos>s->length||pos+t->length>SIZE){return false;}for(int i = s->length-1;i>=pos;i--){s->elem[i+t->length] = s->elem[i];  }for(int j = 0;j<t->length;j++){s->elem[j+pos] = t->elem[j];}s->length +=t->length;return true;
}
int BF(Str *s,Str *sub,int pos)//在串s里找第一个串sub,并返回串sub的第一个元素的下标
{if(pos<0||pos>s->length){return -1;}int i = pos;int j = 0;int lens = s->length;int lensub = sub->length;while (i < lens && j < lensub){if (s->elem[i] == sub->elem[j]){i++;j++;}else{i = i - j + 1;j = 0;}}if (j >= lensub){return i - j;}else return -1;
}bool DeletePos(Str* s,int pos,int len)//从pos位置开始删除len个长度
{assert(s!=NULL);if(pos<0||pos+len>s->length||len<0){return false;}//for(int i = pos;i<len+pos;i++)for(int i = pos;i<s->length-len;i++){s->elem[i] = s->elem[i+len];}s->length -= len;return true;
}bool Delete(Str *s,int pos,Str *t)//在串中的pos位置开始删除串t
{assert(s!=NULL);assert(t!=NULL);if(pos<0||pos>s->length||t->length>s->length){return false;}int index = BF(s,t,pos);if(index < 0){return false;}return DeletePos(s,index,t->length);
}
bool Replace(Str *s,Str *t,Str *v,int pos)//用v替换从pos位置开始的第一个t
{assert(s!=NULL);assert(t!=NULL);assert(v!=NULL);int index = BF(s,t,pos);if(index < 0){return false;}DeletePos(s,index,t->length);return Inset(s,index,v);
}
bool RepIaceAll(Str *s,Str *t,Str *v)//在串s中查找到串t并用串v替换
{assert(s!=NULL);assert(t!=NULL);assert(v!=NULL);while(Replace(s,t,v,0));return true;
}
void Show(Str *s) //打印
{for(int i=0;i<Getlength(s);i++){printf("%c",s->elem[i]); }printf("\n");
}  int main()
{Str s;char *s1 = "abcdecdfcd";StrAssign(&s, s1);Show(&s);Str t;char *t1 = "cd";StrAssign(&t, t1);Show(&t);/*Inset(&s, 2, &t);Show(&s);Inset(&s, 7, &t);Show(&s);*//*int index = BF(&s,&t,0);printf("index = %d\n",index);*//*DeletePos(&s,3,2);Show(&s);*//*Str v;char *v1 = "zkr";StrAssign(&v, v1);Show(&v);Replace(&s,&t,&v,0);Show(&s);*/Str v;char *v1 = "zkr";StrAssign(&v, v1);Show(&v);RepIaceAll(&s,&t,&v);Show(&s);system("pause");return 0;
}

参考博客:

https://www.jianshu.com/p/65534d21e097

https://www.cnblogs.com/TimVerion/p/11194268.html

https://blog.csdn.net/weixin_42034217/article/details/84891312

【数据结构】串(一)—— 串的基础知识相关推荐

  1. 【超全汇总】学习数据结构与算法,计算机基础知识,看这篇就够了【ZT帅地】2020-3-7

    https://blog.csdn.net/m0_37907797/article/details/104029002 由于文章有点多,并且发的文章也不是一个系列一个系列发的,不过我的文章大部分都是围 ...

  2. 计算机基础知识数据结构与算法,(计算机基础知识)[数据结构与算法] 图

    第六章 图 6.1 图的定义和基本术语 图: G=(V,E) Graph = (Vertex, Edge) V: 顶点(数据元素)的有穷非空集合 E: 边的有穷集合 完全图: 任意两个点都有一条边相连 ...

  3. 计算机二级基础知识教材,国家计算机二级考试公共基础知识教材

    国家计算机二级测试公共基础知识教材 公共基础知识总结之第一章数据结构和算法 (1) 公共基础知识总结之第二章程序设计基础 (4) 公共基础知识总结之第三章软件工程基础 (5) 公共基础知识总结之第四章 ...

  4. 计算机公共基础知识教材,国家计算机二级考试公共基础知识教材

    国家计算机二级考试公共基础知识教材 国家计算机二级考试公共基础知识教材 国家计算机二级考试公共基础知识教材 公共基础知识总结之第一章数据结构与算法 .......................... ...

  5. 【软考】《希赛教育·软件设计师考前冲刺与考点分析》计算机硬件基础知识——学习笔记

    Content 第1章 计算机硬件基础知识 第2章 操作系统基础知识 第3章 程序语言和语言处理程序基础知识 第4章 数据结构 第5章 数据库系统基础知识 第6章 网络基础知识 第7章 软件工程基础知 ...

  6. 计算机二级公共基础知识教材,《国家计算机二级考试【公共基础知识教材】》.pdf...

    <国家计算机二级考试[公共基础知识教材]>.pdf 国家计算机二级考试公共基础知识教材 国家计算机二级考试公共基础知识教材 国家计算机二级考试公共基础知识教材 国国家家计计算算机机二二级级 ...

  7. 考研数据结构之串的基础知识

    提示:君子藏器于身,待时而动 文章目录 前言 考纲要求 一.关于C中字符串 二.数据结构中的String 2.1 基本概念: 2.2 串的存储结构 1. 定长顺序存储表示 2.变长分配存储表示(堆分配 ...

  8. 数字电路基础知识——乘法器的设计(二)( 串行、流水线、有符号数八位乘法器)

    数字电路基础知识--乘法器的设计(二)( 串行.流水线.有符号数八位乘法器) 前面一节关于乘法器的具体实现方式有很多种方法,均有各自的优缺点. 本节将再介绍一下两种乘法器的设计,分别用Verilog语 ...

  9. 串行RapidIO(Serial RapidIO,SRIO):IP核基础知识

    目录 前言:SRIO .RapidIO.GT 有什么关系? 一.SRIO IP核概述 1.1. 概述 ​​​​​​​1.2 SRIO核架构 二.接口介绍 2.1. 逻辑层接口LOG(重点) 2.1.1 ...

  10. 计算机专业知识串讲,计算机基础知识串讲

    计算机文化基础复习课 第一章 计算机与信息社会 1.第一台电子计算机的诞生: 2.计算机发展阶段:按基本逻辑元器件划分: 3.计算机的基本特征:主要特征是运算速度快. 4.计算机的应用:实际的应用范围 ...

最新文章

  1. OpenAPI使用(swagger3),Kotlin使用swagger3,Java使用swagger3,gradle、Maven使用swagger3
  2. sql 使用视图的好处
  3. 电脑常见问题_电脑知识,每日一课,计算机常用维修小技巧
  4. 推送:腾迅信鸽 VS Bmob
  5. 仿简书、淘宝等等App的View弹出效果
  6. 使用Select.HtmlToPdf 把html内容生成pdf文件
  7. Kogito,ergo规则:从知识到服务,轻松自如
  8. 【转载保存】什么是线程阻塞?为什么会出现线程阻塞?
  9. 流量限制器(Flux Limiter)
  10. 遥感影像数据下载网址
  11. springboot做梦网云科技短信业务
  12. python读取tiff文件_怎么用python读取和写入TIFF文件1
  13. oracle手动删除dbf文件,oracle删除DBF文件
  14. python实现模拟按键down_Python如何实现键盘鼠标按键模拟 Python实现键盘鼠标按键模拟代码...
  15. Qpid 安装问题之qpid.messaging
  16. python怎么写excel数据透视自动报表_使用Python生成自动报表(E
  17. 剑指Offer——编程题的Java实现
  18. 生态系统名词解释笔记
  19. 苹果手机不进post方法
  20. 迎接2016,一个程序员的总结

热门文章

  1. clang diagnostic的简单介绍
  2. Activiti7工作流引擎:进阶篇(八) 会签
  3. Objective-C小白入门:什么是Objective-C
  4. 计算机英语ppt答辩,急求英语答辩PPT范文
  5. html网页制作教程ppt,网页制作教程html篇.ppt
  6. 具有改善视力作用的食物
  7. ASP.NET MVC5中局部视图的更新
  8. Debian10安装部署DNS服务-正向解析篇
  9. vagrant学习笔记 - provision
  10. 单招学计算机好学吗,单招没被录取学什么,计算机行业