数据结构C语言版第四章 串

合集下载

算法与数据结构c语言版第4章串

算法与数据结构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++语言版)》第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章 串(C#)
将当前链串的所有结点?nstr将q结点插入到尾部将q结点插入到尾部将链串t的所有结点?nstr将q结点插入到尾部尾结点的next置为null返回新建的链串5求子串substrij返回当前串中从第i个字符开始的连续j个字符组成的子串ຫໍສະໝຸດ 第4章 串4.1 串的基本概念
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章

《数据结构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章串

数据结构(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语言版第四章串

数据结构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

数据结构(c语言)第四章  串(String )2
14
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; } /*回溯*/
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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]);
}// 算法结束。

相关文档
最新文档