数据结构C语言版第四章 串
算法与数据结构c语言版第4章串
详细描述
在C语言中,可以使用str_replace()函数来替换字符串 中的子串。该函数接受三个参数,第一个参数是源字 符串,第二个参数是要被替换的子串,第三个参数是 替换后的子串。str_replace()函数将源字符串中所有 出现的指定子串替换为新的子串,并返回替换后的新 字符串。需要注意的是,该函数不是标准C库中的函 数,需要引入额外的头文件或使用第三方库来实现。
char *tmp; // 临时变量,用 于临时存储替换过程中的字符串
片段
int len_rep; // 要被替换的子 串的长度
字符串的替换
int len_with; // 替换后的子串的长度
int count; // 替换次数(用于循环)
int len_front; // 前面的字符串长度 (每次替换前需要保留的部分)
字符串的连接
示例代码 ```c
char source1[] = "Hello, ";
字符串的连接
char source2[] = "world!"; char destination[20]; strcat(destination, source1);
字符串的连接
strcat(destination, source2); ```
字符串的比较
01
示例代码
02
```c
char str1[] = "Hello";
03
字符串的比较
1
char str2[] = "World";
2
int result = strcmp(str1, str2);
```
3
字符串的替换
《数据结构与算法(C++语言版)》第4章_串
串函数与串的类定义
• 常用的 常用的C++串函数 串函数 • C++的串库(string.h)中提供了许多字符串的操作函数,几 个常用的C++字符串函数及其使用方法如下。 •假设已有以下定义语句:
串函数与串的类定义
• (1)串拷贝函数 • char *strcpy(char *s1, const char *s2),将字符串s2复制到字 符串数组s1中,返回s1的值。 • char *strncpy(char *s1, const char *s2, size_tn)将字符串s2中最 多n个字符复制到字符串数组s1中,返回s1的值。 • 例如:
串函数与串的类定义
• (3)串比较函数 • int strcmp(const char *s1, const char *s2),比较字符串s1和字 符串s2。函数在s1等于、小于或大于s2时,分别返回0、小 于0或者大于0的值。 • int strncmp(const char *s1, const char *s2, size_tn)比较字符串 s1中的n个字符和字符串s2。函数在s1等于、小于或大于s2 时,分别返回0、小于0或者大于0的值。 • 例如:
串模式匹配
• 无回溯的匹配算法 • 在上面介绍的匹配算法中,某趟匹配失败时,下一趟的匹 配相当于将子串P后移1位再从头与主串中对应字符进行比 较,即相当于i指示器回溯到上趟(最近失败的一趟)匹配 的起点的下一个位置,这样,主串中每个字符都要与子串 中的第1个字符对应一次,再向后比较。因此,主串中每个 字符参加比较的次数最多可达n次(n为子串长度),因此 时间复杂度为O(nm)。那么,能否使目标串中每个字符只参 加一次比较呢?也就是说,能否不回溯i指示器?回答是肯 定的。这个问题是由D.E.Knoth与V.R.Pratt和J.H.Morris同时 解决的,所以有的文献也称这种思想的串匹配算法为KMP 算法。
数据结构——第4章 串(C#)
4.1.1 什么是串 串(或字符串)是由零个或多个字符组成的有限序列。 记作str="a1a2…an"(n≥0),其中str是串名,用双引号括 起来的字符序列为串值,引号是界限符,ai(1≤i≤n)是一 个任意字符(字母、数字或其他字符),它称为串的元素, 是构成串的基本单位,串中所包含的字符个数n称为串的 长度,当n=0时,称为空串。
4.2 串的存储结构
4.2.1 串的顺序存储结构-顺序串
和顺序表一样,用一个data数组(大小为MaxSize)和 一个整型变量length来表示一个顺序串,length表示data数 组中实际字符的个数。 定义顺序串类SqStringClass如下:
class SqStringClass { const int MaxSize=100; public char[] data; //存放串中字符 public int length; //存放串长 public SqStringClass() //构造函数,用于顺序串的初始化 { data=new char[MaxSize]; length=0; } //顺序串的基本运算 }
(9)串输出DispStr() 将当前串s的所有字符构成一个字符串并输出。对应的算 法如下:
public string DispStr() { int i; string mystr=""; if (length==0) mystr = "空串"; else { for (i=0;i<length;i++) mystr+=data[i].ToString(); } return mystr; }
数据结构 第四章 串
4.1 4.2
串类型的定义 串的表示和实现
4.2.1 定长顺序存储表示 4.2.2 堆分配存储表示 4.2.3 串的块链存储表示
第四章 串
4.1 串类型的定义
一、串的基本概念 定义:字符串是 n ( 0 ) 个字符的有限序列
记作 S = “c1c2c3…cn”
其中:
S 是串名字 “c1c2c3…cn”是串值 ci 是串中字符 n 是串的长度
4.1 串类型的定义
一、串的基本概念
串中任意个连续字符组成的子序列称为该串的
子串,包含子串的串相应地称为主串。
子串在主串中首次出现时的该子串的首字符 对应的主串中的序号,定义为子串在主串中的
序号(或位置)
例如,设A和B分别为 A=“This is a string” B=“is”
4.1 串类型的定义
提取子串的算法示例
pos = 3, len = 3 infini ty
pos = 6, len = 4 infini ty
fin
len S[0]-pos+1
超出 len > S[0]-pos+1
合法参数条件: Pos>=0, Pos<=S[0], Len>=0
len <=S[0]-pos+1
求子串的过程即为复制字符序列的过程,将串S中的 第pos个字符开始长度为len的字符复制到串T中。
1、串的插入的动态实现过程 s.length+ t.length
SA
l o v el y
pos Tl o
t.length
vely
g irl!
t.length
1、串的插入的动态实现过程 s.length+ t.length
《数据结构C语言版》----第04章
S->str = (char *)malloc(sizeof(char)*m);
for(i = 0; i < S->length; i++) S->str[i] = string[i];
}
方法二:
typedef struct { char *str; int length; } DString; void Initiate(DString *S, char *string) {
{
else {
printf(―参数pos和len不合法”);
return 0; }
for(i = pos+len; i <= S->length-1; i++)
S->str[i-len] = S->str[i]; S->length = S->length - len; return 1; }
(4)取子串操作
而由于不同的内存分配方式定义的数组决定了串的顺 序存储结构也有两种: (1)静态数组结构:用静态内存分配方法定义的数组。由 于此时数组元素的个数是在编译是确定的,在运行时是不 可改变的,所以也称为定长数组结构。 其类成员变量包括:
typedef struct { char str[MaxSize]; int length; } String;
设计函数如下:
void ReverseName(char *name, char *newName) { char *p; p = strchr(name, ' '); //p指在空格' '位置
*p = NULL; //把空格换为NULL,因此name的长度只包括名 strcpy(newName, p+1); strcat(newName, ","); strcat(newName, name); //newName等于name的姓 //newName等于姓加逗号 // newName等于姓加逗号加名
数据结构(C语言版)第4章串
第4章串串:限定数据元素类型的线性表。
1 逻辑结构1.1 定义位串:数据元素属于{0,1}ASCII码串: 数据元素属于ASCII码字符集。
数字串:数据元素属于整数集合2 顺序串///////////////////////////////// // 项目路径:7动态顺序串/////////////////////////////////2.2 构造/析构(测试函数Test1)template <class T>String<T>:: String( ){ m_Data=NULL; m_Size=m_Length=0; }template <class T>String<T>::String(T a[], int n){ m_Size = m_Length = n;m_Data = new T[m_Size];if(!m_Data) throw "内存不够,上溢";for(int i=0; i<m_Length; i++)m_Data[i]=a[i];}template <class T>String<T>::String(String &s) // 拷贝构造函数{ m_Size = m_Length = s.m_Length;m_Data = new T[m_Size];if(!m_Data) throw "内存不够,上溢";for(int i=0; i<m_Length; i++)m_Data[i]=s.m_Data[i];}template <class T>String<T>:: ~String( ){ delete []m_Data; }2.3 比较(测试函数Test2)// 重载<template <class T>bool String<T>::operator<(String &s){ for(int i=0; i<m_Length && i<s.m_Length; i++) { if(m_Data[i]<s.m_Data[i]) return true;if(m_Data[i]>s.m_Data[i]) return false;}if(m_Length<s.m_Length) return true;return false;}// 重载==template <class T>bool String<T>::operator==(String &s){ for(int i=0; i<m_Length && i<s.m_Length; i++) if(m_Data[i]!=s.m_Data[i]) return false; if(m_Length==s.m_Length) return true;return false;}2.4 取子串、连接(测试函数Test3)// 取子串template <class T>String<T> String<T>::Substr(int pos,int len) { if(pos+len>m_Length) // 预防子串长度越界len=m_Length-pos;String<T> s;s.m_Length=s.m_Size=len;s.m_Data = new T[s.m_Size];if(!s.m_Data) throw "内存不够,上溢";for(int i=0; i<len; i++)s.m_Data[i]=m_Data[pos+i];return s;}// 连接stemplate <class T>void String<T>::Concat(String s){ if(m_Length+s.m_Length > m_Size) // 空间不够ReNew(m_Length+s.m_Length);for(int i=0; i<s.m_Length; i++)m_Data[m_Length+i] = s.m_Data[i];m_Length += s.m_Length;}// 重新分配串的存储空间template <class T>void String<T>::ReNew(int size){ T *p=new T[size]; // 重新申请空间 m_Size=size;for(int i=0; i<m_Length; i++) // 数据迁移p[i]=m_Data[i];delete []m_Data; // 释放原串空间 m_Data = p;}2.5 插入、删除(测试函数Test4)// 第i个位置上插入stemplate <class T>void String<T>::Insert(int pos, String s){ if(m_Length+s.m_Length > m_Size) // 空间不够 ReNew(m_Length+s.m_Length);for(int i=m_Length-1; i>=pos; i--) // 向后移位 m_Data[i+s.m_Length] = m_Data[i];for(i=0; i<s.m_Length; i++)m_Data[pos+i] = s.m_Data[i];m_Length += s.m_Length;}// 删除子串template <class T>void String<T>::Delete(int pos,int len){ for(int i=pos+len; i<m_Length; i++) // 向前移位 m_Data[i-len] = m_Data[i];m_Length -= len;}2.6 顺序串的评价优点:访问子串方便,缺点:空间大小不灵活,插入、删除费时。
数据结构c语言版第四章串
第四章串重点难点理解"串"类型定义中各基本操作的特点,并能正确利用它们进行串的其它操作;掌握串类型的各种存储表示方法;理解串的两种匹配算法。
典型例题1、简述下列每对术语的区别:空串和空白串;串常量和串变量;主串和子串;静态分配的顺序串和动态分配的顺序串;【解】(1)空串是指不包含任何字符的串,它的长度为零。
空白串是指包含一个或多个空格的串,空格也是字符。
(2)串常量是指在程序中只可引用但不可改变其值的串。
串变量是可以在运行中改变其值的。
(3)主串和子串是相对的,一个串中任意个连续字符组成的串就是这个串的子串,而包含子串的串就称为主串。
(4)静态分配的顺序串是指串的存储空间是确定的,即串值空间的大小是静态的,在编译时刻就被确定。
动态分配的顺序串是在编译时不分配串值空间,在运行过程中用malloc和free等函数根据需要动态地分配和释放字符数组的空间(这个空间长度由分配时确定,也是顺序存储空间)。
2、以HString为存储表示,写一个求子串的算法。
【解】HString 是指以动态分配顺序串为存储表示,其定义为:typedef struct {char *ch;int length;}HString;void *substr( HString *sub,HString *s,int pos,int len){//用sub返回串s的第pos个字符起长度为len的子串。
sub初始时为一空串//pos的合法位置为0<=pos<=s->length-1int i;if (pos<0||pos>s->length-1||len<=0)Error("parameter error!");//参数不合法,子串为空串if (s->length<pos+len)//s串中没有足够的元素sub->len=s->length-pos;//设置子串的串长else sub->length=len; //设置子串的串长sub->ch=(char *)malloc(len*sizeof(char));//为sub->ch申请结点空间for(i=0;i<sub->length;i++)//将s串中pos位置开始的共sub->length个字符复制到sub串中sub->ch[i]=s->ch[pos+i];}3、若S和T是用结点大小为1的单链表存储的两个串,试设计一个算法找出S中第一个不在T中出现的字符。
数据结构(c语言)第四章 串(String )2
1.简单的模式匹配算法
• 算法思想如下:
首先将s[1]与t[1]进行比较,若不同,就将 s[2]与t[1]进行比较,...,直到s的某一个字符s[i] 和t[1]相同,再将它们之后的字符进行比较,若 也相同,则如此继续往下比较,当s的某一个字 符s[i]与t的字符t[j]不同时,则s返回到本趟开始 字符的下一个字符,即s[i-j+2],t返回到t[1],继 续开始下一趟的比较,重复上述过程。
• 堆存储结构的基本思想是:在内存中开辟能存储 足够多的串、地址连续的存储空间作为应用程序 中所有串的可利用存储空间,称为堆空间,如设 store[SMAX+1];
• 根据每个串的长度,动态的为每个串在堆空间里 申请相应大小的存储区域,这个串顺序存储在所 申请的存储区域中,当操作过程中若原空间不够 了,可以根据串的实际长度重新申请,拷贝原串 值后再释放原空间。
{ ++k; ++j; }
if ( j == tLength ) return i;
else
++i; // 重新开始下一次的匹配
}
}
return 0; }
20
BF算法的另一种改进:KMP算法
• 首先求出模式串的各个字符next回退值; • 在主串中查找模式串的匹配过程中,若在
主串第i个位置与模式串第j个位置字符“失 配”,则将主串第i个位置上字符继续与模 式串第j个位置字符的回退值所对应位置上 的字符进行匹配比较。
while (i<=s[0] && j<=t[0] ) /*都没遇到结束符*/ if (s[i]==t[j]) { i++;j++; } /*继续*/ else {i=i-j+2; j=1; } /*回溯*/
Chapter04_串_数据结构(C语言版)_严蔚敏_配套课件
Replace (&S, T, V)
初始条件:串S, T和 V 均已存 在,
且 T 是非空串。 操作结果:用V替换主串S中出现
的所有与(模式串)T 相等的不重叠的子串。
例如:
假设 S = ′abcaabcaaabca′,T = ′bca′ 若 V = ′x′, 则经置换后得到
S = ′axaxaax′
• 空串是任意串的子串; • 任意串又是自己的子串
注意: ⑴串值必须用一对单引号括起来,但单引号本身不属
于串; ⑵空串与空白串截然不同,空Байду номын сангаас不包含任何字符。
二、串的抽象数据类型的定义如下:
ADT String { 数据对象: D={ ai |ai∈CharacterSet, i=1,2,...,n, n≥0 } 数据关系:
R1={ < ai-1, ai > | ai-1, ai ∈D, i=2,...,n }
基本操作:
StrAssign (&T, chars)
DestroyString(&S) StrCopy (&T, S) StrLength(S) StrCompare (S, T) Concat (&T, S1, S2) StrEmpty (S)
SubString (&Sub, S, pos, len)
初始条件:
串 S 存在,1≤pos≤StrLength(S) 且0≤len≤StrLength(S)-pos+1。
操作结果:
用 Sub 返回串 S 的第 pos 个字符起 长度为 len 的子串。
子串为“串”中的一个字符子序列
例如: SubString( sub, ′commander′, 4, 3)
《数据结构》(C语言版)第四章串
如:A= ‘BEIJING’, B= ‘JING’
串的抽象数据类型定义:
ADT String {
数据对象: D={ ai |ai∈CharacterSet, i=1,2,...,n, n≥0 } 数据关系: R1={ < ai-1, ai > | ai-1, ai ∈D, i=2,...,n } 基本操作: …… } ADT String
初始条件:串S和T存在, 1≤pos≤StrLength(S)+1。 操作结果:在串S的第pos个字符之前 插入串T。
例如:S=‘god’, StrInsert (&S, 2, ‘o’) S=‘good’
StrDelete (&S, pos, len)
初始条件:串S存在,
1≤pos≤StrLength(S)-len+1。
gets(str) 输入一个串; puts(str) 输出一个串; strcat(str1, str2) 串联接函数; strcpy(str1, str2, k) 串复制函数; strcmp(str1, str2) 串比较函数; strlen(str) 求串长函数;
StrLength (S) //求串长
初始条件:串S存在。 操作结果:返回S的元素个数。
串的长度:串中字符的数目n 。 空串:不含任何字符的串,串长度为0,
用“ ”或 ‘ ’表示。
空格串:仅由一个或多个空格组成的串,
长度为串中空格字符的个数。
StrCompare (S, T) //串比较
初始条件:串S和T存在。 操作结果:若S>T,则返回值 > 0; 若S=T,则返回值= 0; 若S<T,则返回值< 0。
操作结果:从串S中删除第pos个字符起
数据结构c语言版 (4)
8. 在具有n个单元的循环队列中,队满时共有 ____个元素。 9. 一个栈的输入序列是12345,则栈的输出序 列43512是____。 10.二维数组A[10..20][5..10]采用行序为主方式 存储,每个元素占4个存储单元,并且 A[10][5]的存储地址是1000,则A[18][9]的地 址是____。 四、设有一个顺序栈S,元素s1, s2, s3, s4 , s5, s6依次进栈,如果6个元素的出栈顺 序为s2, s3, s4, s6, s5, s1,则顺序栈 的容量至少应为多少?
子串的位置:子串在主串中第一次出现的第一个字 符的位置。 两个串相等:两个串的长度相等,并且各个对应的 字符也都相同。 a= “program” b= “Program” c= “pro” d= “program ”
串的基本操作:
(1) 创建串 StringAssign (s,string_constant)
a0 0 a0 1 ... a0 ,n 1
a1 0
a1 1
...
a1 ,n 1
...
...
a m1 ,0
a m1 ,1
...
a m-1 , n 1
第0行
a0 0 a1 0 ... a m1 ,0
第1行
a0 1 a1 1 ... a m-1 ,1 ... ... a 0 ,n -1
第m-1行
a 1 ,n -1 ... a m1 ,n -1
矩阵的压缩存储
为多个值相同的元素只分配一个存储空间,对0元 素不分配空间。
1.对称矩阵
aij=aji
K=
{
矩阵的压缩存储
2. 三角矩阵 b. 上三角矩阵
K=
{
数据结构(C语言版)第4章 串
19/57
一般可使用一个不会出现在串中的特殊字符在串值 的尾部来表示串的结束。例如,C语言中以字符 ‵\0′表示串值的终结,这就是为什么在上述定义中, 串空间最大值maxstrlen为256,但最多只能存放255 个字符的原因,因为必须留一个字节来存放‵\0′字 符。若不设终结符,可用一个整数来表示串的长度, 那么该长度减1的位置就是串值的最后一个字符的位 置。此时顺序串的类型定义和顺序表类似: typedef struct{
上述串的操作是最基本的,其中后四个还有变种形式: strncpy,strncat,strncmp,strnchr。串的其余操作 可由这些基本操作组合而成。n为字符个数。 例1、求子串 求子串的过程即为复制字符序列的过程,将串S中 的第pos个字符开始长度为len的字符复制到串T中。 void substr(string T, string s, int pos, int len) { if(pos<0 || pos>strlen(s)-1 || len<0) error(―parameter error‖) strncpy(T,&s[pos],len); }
6/57
定义和概念(总结)
• 串(String):由零个或多个字符组成的有限序列。记为: s=―a1a2…an ‖ (n≥0) • 概念: –s为串名 – ‚a1a2…an ‖ 为串值 –n为串的长度 –ai,字符 –n=0,空串(Null String),记为:Ф –若ai 都是 ‘ ’,则称为空格串(blank string) –子串:串中任意连续个字符组成的子序列被称为该串的子 串 ,包含子串的串又被称为该子串的主串 –子串在主串中的位置: –串的相等:两个串的串值相等(两个串的长度相等,并且 各个对应的字符也都相同 )
数据结构(C语言版)4 串与数组
15
a 01 a 00 a10 a11 Am n ... ... am 1,0 am 1,1
图 4-4
... a 0, n 1 ... a1, n 1 ... ... ... am 1, n 1
19
(2)返回给定位置的元素内容
int Value(ARRAY A,EntryType *item,int index1,int index2) { if (index1<0||index1>=MAX_ROW_INDEX||
index2<0||index2>=MAX_COL_INDEX) return FALSE;
9
(2)子串 int StrSub (char *t, char *s, int i, int len) /* 用t返回串s中第个i字符开始的长度为len 的子串1≤i≤串长*/ { int slen; slen=StrLength(s); if ( i<1 || i>slen || len<0 || len>slen-i+1) { printf("参数不对"); return 0; } for (j=0; j<len; j++) t[j]=s[i+j-1]; t[j]=’\0’; return 1; }
12
a 01 a 00 a10 a11 Am n ... ... am 1, 0 am 1,1
图 4-3
... a 0, n 1 ... a1, n 1 ... ... ... am 1, n 1
13
其中,A是数组结构的名称,整个数组元素可以 看成是由m个行向量和n个列向量组成,其元素总数为 m×n。在C语言中,二维数组中的数据元素可以表示 成a[表达式1][表达式2],表达式1和表达式2被称为下 标表达式,比如,a[i][j]。
数据结构c语言版 第4章 串
Sub[1..len]=S[pos..pos+len-1]; Sub[0]=len; return OK; }// SubString 由上可见,特点一:原操作为串复制,特点二:越界则“截取”。 时间复杂度取决于复制的字符序列的长度。
int strcmp(char * str1,char * str2) (6)substr(str1,str2,m,n) 求子串:在字符串str1中,从第 m个字符开始,取n个长度的子串str2;若m>strlen(str)或n≤0, 则返回空值NULL。自定义函数和形参说明如下:
int substr(char * str1,char *str2,int m,int n) (7)delstr(str,m,n) 字符串的删除:在字符串str中,删除 从第m个字符开始的n个长度的子串。自定义函数和形参说明如 下: Void delstr(char *str,int m,int n) (8)Insstr(str1,m,str2 ) 字符串的插入:在字符串str1第m 个位置之前开始,插入字符串str2。返回str1。 自定义函数和形参说明如下:
1)字符串的联接Concat(&T,S1,S2)
在这里S1、S2和T都是SString型的串变量,T为串S1与 S2的联接结果。其值有三种情况:
其一,S1[0] + S2[0]<=MAXSTRLEN,结果完全正确
其二,S1[0] <MAXSTRLEN而S1[0] + S2[0] > MAXSTRLEN, T的值S1的全部与S2的一部分。
数据结构-第四章串
数据结构-第四章串串也叫字符串,它是由零个或多个字符组成的字符序列。
基本内容1 串的有关概念串的基本操作2 串的定长顺序存储结构,堆分配存储结构;3 串的基本操作算法;4 串的模式匹配算法;5 串操作的应⽤。
学习要点1 了解串的基本操作,了解利⽤这些基本操作实现串的其它操作的⽅法;2 掌握在串的堆分配存储结构下,串的基本操作算法;3 掌握串的模式匹配算法;第四章串 4.1 串的基本概念4.2 串存储和实现4.3 串的匹配算法4.4 串操作应⽤举例第四章串 4.1 串的基本概念 4.2 串存储和实现 4.3 串的匹配算法 4.4 串操作应⽤举例第四章串4.1 串的基本概念 4.2 串存储和实现 4.3 串的匹配算法 4.4 串操作应⽤举例4. 1 串类型的定义⼀、串的定义1 什么是串串是⼀种特殊的线性表,它是由零个或多个字符组成的有,a2, a3, ... a n’限序列,⼀般记作s = ‘a1其中 s----串名, a1,a2, a3, ... a n----串值串的应⽤⾮常⼴泛,许多⾼级语⾔中都把串作为基本数据类型。
在事务处理程序中,顾客的姓名、地址;货物的名称、产地。
可作为字符串处理,⽂本⽂件中的每⼀⾏字符等也可作为字符串处理。
下⾯是⼀些串的例⼦:(1)a = ‘ LIMING’(2)b = ‘NANJING UNIVERSITY OF SCIENCE &TECHNOLOGY’(3)c = ‘ DATA STRUCTURE’(4)d = ‘’说明:1) 串中包含的字符个数,称为串的长度。
长度为0的串称为空串,它不包括任何字符,上⾯(4)中的串d 是空串,(5)中的e 是包含⼀个空格符的空格串;2)串中所包含的字符可以是字母、数字或其他字符,这依赖于具体计算机所允许的字符集。
2 串的有关术语1)⼦串串中任意连续的字符组成的⼦序列称为该串的⼦串例:c = ‘ DATA STRUCTURE’,f=‘DATA’ f是c的⼦串2)⼦串的位置⼦串T 在主串S中的位置是指主串S中第⼀个与T相同的⼦串的⾸字母在主串中的位置。
数据结构(C语言)_4
第四章串本章介绍了串的逻辑结构,存储结构及串上的基本运算,由于在高级语言中已经提供了较全面的串处理功能,因此本章的重点是掌握在串上实现的模式匹配算法,同时这也是本章的难点。
但是从全书来讲,这属于较简单的一章内容。
4.1 串类型的定义一、串定义:串(String)(或字符串):由零个或多个字符组成的有限序列。
一般记为: s='a1a2...an'(n>=0)其中:s是串的名,用单引号括起来的字符序列是串的值。
串的长度:串中字符的数目n。
空串:零个字符的串,它的长度为零。
子串:串中任意个连续的字符组成的子序列称为该串的子串。
主串:包含子串的串相应地称为主串。
位置:字符在序列中的序号称为该字符在串中的位置。
子串在主串中的位置:以子串的第一个字符在主串中的位置来表示。
例:a='BEI',b='JING',c='BEIJING',d='BEI JING'串长分别为3,4,7,8,且a,b都是c,d的子串。
称两个串是相等的,当且仅当这两个串的值相等。
特别地,空串是任意串的子串,任意串是其自身的子串。
二、串的抽象数据类型的定义:ADT String{数据对象:D={ai|ai(-CharacterSet,i=1,2,...,n,n>=0)数据关系:R1={<ai-1,ai>|ai-1,ai(-D,i=2,...,n)基本操作:StrAssign(&T,chars):chars是字符常量。
生成一个其值等于chars的串T。
StrCopy(&T,S):串S存在则由串S复制得串TStrEmpty(S):串S存在则若S为空串,返回真,否则返回假StrCompare(S,T):串S和T存在,若S>T,则返回值大于0,若S=T,则返回值=0,若S<T,则返回值<0StrLength(S):串S存在返回S的元素个数称为串的长度.ClearString(&S):串S存在将S清为空串Concat(&T,S1,S2):串S1和S2存在用T返回由S1和S2联接而成的新串SubString(&Sub,S,pos,len):串S存在,1<=pos<=StrLength(S)且0<=len<=StrLength(S)-pos+1Index(S,T,pos):串S和T存在,T是非空,1<=pos<=StrLength(S),若主串S中存在和串T值相同的子串,则返回它在主串S中第pos个字符之后第一次出现的位置,否则函数值为0Replace(&S,T,V):串S,T和V存在,T是非空串,用V替换主串S中出现的所有与T相等的不重叠的子串StrInsert(&S,pos,T):串S和T存在,1<=pos<=StrLength(S)+1,在串S的第pos个字符之前插入串TStrDelete(&S,pos,len):串S存在,1<=pos<=StrLength(S)-len+1从串中删除第pos个字符起长度为len的子串DestroyString(&S):串S存在,则串S被销毁}ADT String三、串的基本操作对于串的基本操作,许多高级语言均提供了相应的运算或标准库函数来实现。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第四章串
重点难点
理解"串"类型定义中各基本操作的特点,并能正确利用它们进行串的其它操作;掌握串类型的各种存储表示方法;理解串的两种匹配算法。
典型例题
1、简述下列每对术语的区别:
空串和空白串;串常量和串变量;主串和子串;静态分配的顺序串和动态分配的顺序串;【解】
(1)空串是指不包含任何字符的串,它的长度为零。
空白串是指包含一个或多个空格的串,空格也是字符。
(2)串常量是指在程序中只可引用但不可改变其值的串。
串变量是可以在运行中改变其值的。
(3)主串和子串是相对的,一个串中任意个连续字符组成的串就是这个串的子串,而包含子串的串就称为主串。
(4)静态分配的顺序串是指串的存储空间是确定的,即串值空间的大小是静态的,在编译时刻就被确定。
动态分配的顺序串是在编译时不分配串值空间,在运行过程中用malloc和free等函数根据需要动态地分配和释放字符数组的空间(这个空间长度由分配时确定,也是顺序存储空间)。
2、以HString为存储表示,写一个求子串的算法。
【解】HString 是指以动态分配顺序串为存储表示,其定义为:
typedef struct {
char *ch;
int length;
}HString;
void *substr( HString *sub,HString *s,int pos,int len)
{//用sub返回串s的第pos个字符起长度为len的子串。
sub初始时为一空串
//pos的合法位置为0<=pos<=s->length-1
int i;
if (pos<0||pos>s->length-1||len<=0)
Error("parameter error!");//参数不合法,子串为空串
if (s->length<pos+len)//s串中没有足够的元素
sub->len=s->length-pos;//设置子串的串长
else sub->length=len; //设置子串的串长
sub->ch=(char *)malloc(len*sizeof(char));//为sub->ch申请结点空间
for(i=0;i<sub->length;i++)//将s串中pos位置开始的共sub->length个字符复制到sub串中
sub->ch[i]=s->ch[pos+i];
}
3、若S和T是用结点大小为1的单链表存储的两个串,试设计一个算法找出S中第一个不在T中出现的字符。
【解】
查找过程是这样的,取S中的一个字符(结点),然后和T中所有的字符一一比较,直到比完仍没有相同的字符时,查找过程结束,否则再取S中下一个字符,重新进行上述过程。
算法如下:
链串的结构类型定义:
typedef struct node{
char data;
struct node *next;
}LinkStrNode; //结点类型
typedef LinkStrNode *LinkString; //LinkString为链串类型
LinkString S; //S是链串的头指针
char SearchNoin( LinkString S, LinkString T)
{//查找不在T中出现的字符
LinkStrNode *p,*q;
p=S;
q=T;
while (p)
{ //取S中结点字符
while(q&&p->data!=q->data)//进行字符比较
q=q->next;
if(q==NULL) return p->data;//找到并返回字符值
q=T; //指针恢复串T的开始结点
p=p->next;
}
printf("there's no such character.");
return NULL;}
习题精选
一、.单项选择题
1.串是一种特殊的线性表,其特殊性体现在()。
A.可以顺序存储B.数据元素是一个字符
C.可以链式存储D.数据元素可以是多个字符若
2.串下面关于串的的叙述中,()是不正确的?
A.串是字符的有限序列B.空串是由空格构成的串
C.模式匹配是串的一种重要运算D.串既可以采用顺序存储,也可以采用链式存
3.串的长度是指()。
A.串中所含不同字母的个数 B.串中所含字符的个数
C.串中所含不同字符的个数 D.串中所含非空格字符的个数
4.设串s1=’ABCDEFG’,s2=’PQRST’,函数con(x,y)返回x和y串的连接串,subs(s, i, j)返回串s的从序号i开始的j个字符组成的子串,len(s)返回串s的长度,则con(subs(s1, 2, len(s2)), subs(s1, len(s2), 2))的结果串是:
A.BCDEF B.BCDEFG C.BCPQRST D.BCDEFEF
二、算法设计
1.编写算法,实现下面函数的功能。
函数void insert(char*s,char*t,int pos)将字符串t插入到字符串s中,插入位置为pos。
假设分配给字符串s的空间足够让字符串t插入。
(说明:不得使用任何库函数)
[题目分析]本题是字符串的插入问题,要求在字符串s的pos位置,插入字符串t。
首先应查找字符串s的pos位置,将第pos个字符到字符串s尾的子串向后移动字符串t的长度,然后将字符串t复制到字符串s的第pos位置后。
对插入位置pos要验证其合法性,小于1或大于串s的长度均为非法,因题目假设给字符串s的空间足够大,故对插入不必判溢出。
void insert(char *s,char *t,int pos)
//将字符串t插入字符串s的第pos个位置。
{int i=1,x=0; char *p=s,*q=t; //p,q分别为字符串s和t的工作指针
if(pos<1) {printf(“pos参数位置非法\n”);exit(0);}
while(*p!=’\0’&&i<pos) {p++;i++;} //查pos位置
//若pos小于串s长度,则查到pos位置时,i=pos。
if(*p == '/0') {printf("%d位置大于字符串s的长度",pos);exit(0);}
else //查找字符串的尾
while(*p!= '/0') {p++; i++;} //查到尾时,i为字符‘\0’的下标,p也指向‘\0’。
while(*q!= '\0') {q++; x++; } //查找字符串t的长度x,循环结束时q指向'\0'。
for(j=i;j>=pos ;j--){*(p+x)=*p; p--;}//串s的pos后的子串右移,空出串t的位置。
q--; //指针q回退到串t的最后一个字符
for(j=1;j<=x;j++) *p--=*q--; //将t串插入到s的pos位置上
[算法讨论] 串s的结束标记('\0')也后移了,而串t的结尾标记不应插入到s中。
2.写一个递归算法来实现字符串逆序存储,要求不另设串存储空间。
[题目分析]实现字符串的逆置并不难,但本题“要求不另设串存储空间”来实现字符串逆序存储,即第一个输入的字符最后存储,最后输入的字符先存储,使用递归可容易做到。
void InvertStore(char A[])
//字符串逆序存储的递归算法。
{ char ch;
static int i = 0;//需要使用静态变量
scanf ("%c",&ch);
if (ch!= '.') //规定'.'是字符串输入结束标志
{InvertStore(A);
A[i++] = ch;//字符串逆序存储
}
A[i] = '\0'; //字符串结尾标记
}//结束算法InvertStore。
3.写一个算法统计在输入字符串中各个不同字符出现的频度并将结果存入文件(字符串中的合法字符为A-Z这26个字母和0-9这10个数字)。
void Count()
//统计输入字符串中数字字符和字母字符的个数。
{int i,num[36];
char ch;
for(i=0;i<36;i++)num[i]=0;// 初始化
while((ch=getchar())!=‘#’) //‘#’表示输入字符串结束。
if(‘0’<=ch<=‘9’){i=ch-48;num[i]++;} // 数字字符
else if(‘A’<=ch<=‘Z’){i=ch-65+10;num[i]++;}// 字母字符
for(i=0;i<10;i++) // 输出数字字符的个数
printf(“数字%d的个数=%d\n”,i,num[i]);
for(i=10;i<36;i++)// 求出字母字符的个数
printf(“字母字符%c的个数=%d\n”,i+55,num[i]);
}// 算法结束。