【数据结构】串(一)—— 串的基础知识
【数据结构】串(一)—— 串的基础知识
- 前言
- 一、串类型的定义
- 二、串的三种存储结构存
- (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)定长顺序存储
定长顺序存储的结构体:
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
【数据结构】串(一)—— 串的基础知识相关推荐
- 【超全汇总】学习数据结构与算法,计算机基础知识,看这篇就够了【ZT帅地】2020-3-7
https://blog.csdn.net/m0_37907797/article/details/104029002 由于文章有点多,并且发的文章也不是一个系列一个系列发的,不过我的文章大部分都是围 ...
- 计算机基础知识数据结构与算法,(计算机基础知识)[数据结构与算法] 图
第六章 图 6.1 图的定义和基本术语 图: G=(V,E) Graph = (Vertex, Edge) V: 顶点(数据元素)的有穷非空集合 E: 边的有穷集合 完全图: 任意两个点都有一条边相连 ...
- 计算机二级基础知识教材,国家计算机二级考试公共基础知识教材
国家计算机二级测试公共基础知识教材 公共基础知识总结之第一章数据结构和算法 (1) 公共基础知识总结之第二章程序设计基础 (4) 公共基础知识总结之第三章软件工程基础 (5) 公共基础知识总结之第四章 ...
- 计算机公共基础知识教材,国家计算机二级考试公共基础知识教材
国家计算机二级考试公共基础知识教材 国家计算机二级考试公共基础知识教材 国家计算机二级考试公共基础知识教材 公共基础知识总结之第一章数据结构与算法 .......................... ...
- 【软考】《希赛教育·软件设计师考前冲刺与考点分析》计算机硬件基础知识——学习笔记
Content 第1章 计算机硬件基础知识 第2章 操作系统基础知识 第3章 程序语言和语言处理程序基础知识 第4章 数据结构 第5章 数据库系统基础知识 第6章 网络基础知识 第7章 软件工程基础知 ...
- 计算机二级公共基础知识教材,《国家计算机二级考试【公共基础知识教材】》.pdf...
<国家计算机二级考试[公共基础知识教材]>.pdf 国家计算机二级考试公共基础知识教材 国家计算机二级考试公共基础知识教材 国家计算机二级考试公共基础知识教材 国国家家计计算算机机二二级级 ...
- 考研数据结构之串的基础知识
提示:君子藏器于身,待时而动 文章目录 前言 考纲要求 一.关于C中字符串 二.数据结构中的String 2.1 基本概念: 2.2 串的存储结构 1. 定长顺序存储表示 2.变长分配存储表示(堆分配 ...
- 数字电路基础知识——乘法器的设计(二)( 串行、流水线、有符号数八位乘法器)
数字电路基础知识--乘法器的设计(二)( 串行.流水线.有符号数八位乘法器) 前面一节关于乘法器的具体实现方式有很多种方法,均有各自的优缺点. 本节将再介绍一下两种乘法器的设计,分别用Verilog语 ...
- 串行RapidIO(Serial RapidIO,SRIO):IP核基础知识
目录 前言:SRIO .RapidIO.GT 有什么关系? 一.SRIO IP核概述 1.1. 概述 1.2 SRIO核架构 二.接口介绍 2.1. 逻辑层接口LOG(重点) 2.1.1 ...
- 计算机专业知识串讲,计算机基础知识串讲
计算机文化基础复习课 第一章 计算机与信息社会 1.第一台电子计算机的诞生: 2.计算机发展阶段:按基本逻辑元器件划分: 3.计算机的基本特征:主要特征是运算速度快. 4.计算机的应用:实际的应用范围 ...
最新文章
- OpenAPI使用(swagger3),Kotlin使用swagger3,Java使用swagger3,gradle、Maven使用swagger3
- sql 使用视图的好处
- 电脑常见问题_电脑知识,每日一课,计算机常用维修小技巧
- 推送:腾迅信鸽 VS Bmob
- 仿简书、淘宝等等App的View弹出效果
- 使用Select.HtmlToPdf 把html内容生成pdf文件
- Kogito,ergo规则:从知识到服务,轻松自如
- 【转载保存】什么是线程阻塞?为什么会出现线程阻塞?
- 流量限制器(Flux Limiter)
- 遥感影像数据下载网址
- springboot做梦网云科技短信业务
- python读取tiff文件_怎么用python读取和写入TIFF文件1
- oracle手动删除dbf文件,oracle删除DBF文件
- python实现模拟按键down_Python如何实现键盘鼠标按键模拟 Python实现键盘鼠标按键模拟代码...
- Qpid 安装问题之qpid.messaging
- python怎么写excel数据透视自动报表_使用Python生成自动报表(E
- 剑指Offer——编程题的Java实现
- 生态系统名词解释笔记
- 苹果手机不进post方法
- 迎接2016,一个程序员的总结