数据结构《第4章 串存储与基本操作的实现》
数据结构串的基本操作及应用实验报告
实验日期2010.5.10 教师签字成绩实验报告【实验名称】第四章串的基本操作及应用【实验目的】1、熟悉将算法转换成程序代码的过程。
2、了解串的逻辑结构特性,熟练掌握串顺序存储结构的C 语言描述方法。
3、熟练掌握串的基本操作:求长度、串的连接、插入、删除等,掌握串的存取特性。
【实验原理】1.串可以可以有三种存储方式,分别为顺序存储、堆分配存储、链式存储,串的基本操作在这三种存储方式下操作。
2.串的模式匹配KMP算法在每一趟匹配过程中出现字符不等时,不需回溯指针,而是利用已经得到的部分匹配结果的结果将模式向右滑动尽可能远的一段距离,继续进行比较。
【实验内容】1.串的顺序存储表示及基本操作(插入、删除、求串长、合并连接串、求子串、串比较等)#include<stdio.h>#include<iostream.h>#include<malloc.h>#include<string.h>#define SIZE 20struct HString{char ch[SIZE];int length;};void StrInsert(HString &s,int pos,HString t){int i,j;if(pos<1||pos>s.length+1)cout<<"ERROR!";if(t.length){for(i=s.length-1;i>=pos-1;--i)s.ch[i+t.length]=s.ch[i];for(j=0;j<=t.length-1;j++)s.ch[pos-1+j]=t.ch[j];s.length+=t.length;}}void StrDelete(HString &s,int pos,int len){int i;int v=pos-1;if(pos<1||pos>s.length||len<0||len>s.length-pos+1)cout<<"ERROR!";for(i=pos+len-1;i<=s.length-1;i++)s.ch[v++]=s.ch[i];s.length-=len;}void StrAssign(HString &t,char chars[]){int i;char *c;for(i=0,c=chars;*c;++i,++c);if(!i){t.length=0;}else{for(int j=0;j<i;j++)t.ch[j]=chars[j];t.length=i;}}int StrLen(HString &s){return s.length;}int StrCompare(HString &s,HString t){for(int i=0;i<s.length&&i<t.length;i++){if(s.ch[i]!=t.ch[i])return (int)(t.ch[i]-s.ch[i]);}return s.length-t.length;}void Concat(HString &t,HString s1,HString s2){int i=s1.length+s2.length;for(i=0;i<s1.length;i++)t.ch[i]=s1.ch[i];t.length=s1.length+s2.length;for(i=s1.length;i<t.length;i++)t.ch[i]=s2.ch[i-s1.length];}int SubString(HString &sub,HString s,int pos,int len) {if(pos<1||pos>s.length||len<0||len>s.length-pos+1) {cout<<"ERROR!"<<endl;return 0;}if(!len){sub.length=0;}else{int i=len;for(i=0;i<len;i++)sub.ch[i]=s.ch[pos+i-1];sub.length=len;}}void Display(HString &t){for(int i=0;i<=t.length-1;i++)cout<<t.ch[i];cout<<endl;}void main(){int i;char s[20];do{cout<<"选择您要进行的串的基本操作:"<<endl;cout<<"1.插入"<<endl<<"2.删除"<<endl<<"3.串连结"<<endl<<"4.取子串"<<endl<<"5.串比较"<<endl<<"6.求串长"<<endl<<"7.结束"<<endl;cin>>i;switch(i){case 1:{HString s,t;int pos;cout<<"请输入串s:";cin>>s.ch;StrAssign(s,s.ch);cout<<endl;cout<<"请输入要插入的串t:";cin>>t.ch;StrAssign(t,t.ch);cout<<endl;cout<<"请输入你所要插入的位置:";cin>>pos;StrInsert(s,pos,t);cout<<"插入之后串变为:";Display(s);break;}case 2:{HString s;int pos,len;cout<<"请输入串s:";cin>>s.ch;StrAssign(s,s.ch);cout<<"请输入你所要删除串的首位置为:";cin>>pos;cout<<"请输入你需要删除的串的长度:";cin>>len;StrDelete(s,pos,len);cout<<"删除之后串变为:";Display(s);break;}case 3:{HString s1,s2,t;cout<<"请输入串s1:";cin>>s1.ch;StrAssign(s1,s1.ch);cout<<"请输入串s2:";cin>>s2.ch;StrAssign(s2,s2.ch);Concat(t,s1,s2);cout<<"s1与s2合并后的串为:";Display(t);break;}case 4:{HString sub,s;int pos,len;cout<<"请输入主串s:";cin>>s.ch;StrAssign(s,s.ch);cout<<"请输入所取原串的起始位置pos:";cin>>pos;cout<<"请输入子串的长度len:";cin>>len;SubString(sub,s,pos,len);cout<<"取出的子串为:";Display(sub);break;}case 5:{HString s,t;int value;cout<<"请输入串s:";cin>>s.ch;StrAssign(s,s.ch);cout<<"请输入串t:";cin>>t.ch;StrAssign(t,t.ch);value=StrCompare(s,t);if(value>0) cout<<"串s大于串t"<<endl;else if(value==0) cout<<"串s等于串t"<<endl;else cout<<"串s小于串t"<<endl;cout<<endl;break;}case 6:HString s;char *chars;int val;cout<<"请输入串s:";cin>>s.ch;StrAssign(s,s.ch);val=StrLen(s);cout<<"串的长度为:"<<val<<endl;break;case 7:cout<<"操作结束!"<<endl;break;default:cout<<"输入错误!请重新输入!"<<endl;break;}}while(i!=7);}2.串的堆分配存储表示及基本操作(插入、删除、求串长、合并连接串、求子串、串比较等)#include<stdio.h>#include<iostream.h>#include<malloc.h>#include<string.h>struct HString{char *ch;int length;};void StrInsert(HString &s,int pos,HString t){int i,j;if(pos<1||pos>s.length+1)cout<<"ERROR!";if(t.length){s.ch=(char*)realloc(s.ch,(s.length+t.length)*sizeof(char));for(i=s.length-1;i>=pos-1;--i)s.ch[i+t.length]=s.ch[i];for(j=0;j<=t.length-1;j++)s.ch[pos-1+j]=t.ch[j];s.length+=t.length;}}void StrDelete(HString &s,int pos,int len){int i;int v=pos-1;if(pos<1||pos>s.length||len<0||len>s.length-pos+1)cout<<"ERROR!";for(i=pos+len-1;i<=s.length-1;i++)s.ch[v++]=s.ch[i];s.length-=len;}void StrAssign(HString &t,char *chars){int i;char *c;for(i=0,c=chars;*c;++i,++c);if(!i){t.ch=NULL;t.length=0;}else{t.ch=(char *)malloc(i*sizeof(char));for(int j=0;j<i;j++)t.ch[j]=chars[j];t.length=i;}}int StrLen(HString &s){return s.length;}int StrCompare(HString &s,HString t){for(int i=0;i<s.length&&i<t.length;i++){if(s.ch[i]!=t.ch[i])return (int)(t.ch[i]-s.ch[i]);}return s.length-t.length;}void Concat(HString &t,HString s1,HString s2){int i=s1.length+s2.length;t.ch=(char *)malloc(i*sizeof(char));for(i=0;i<s1.length;i++)t.ch[i]=s1.ch[i];t.length=s1.length+s2.length;for(i=s1.length;i<t.length;i++)t.ch[i]=s2.ch[i-s1.length];}int SubString(HString &sub,HString s,int pos,int len){if(pos<1||pos>s.length||len<0||len>s.length-pos+1){cout<<"ERROR!"<<endl;return 0;}if(!len){sub.ch=NULL;sub.length=0;}else{int i=len;sub.ch=(char *)malloc(i*sizeof(char));for(i=0;i<len;i++)sub.ch[i]=s.ch[pos+i-1];sub.length=len;}}void Display(HString &t){for(int i=0;i<=t.length-1;i++)cout<<t.ch[i];cout<<endl;}void main(){int i;char s[20];cout<<"选择您要进行的串的基本操作:"<<endl;do{cout<<"1.插入"<<endl<<"2.删除"<<endl<<"3.串连结"<<endl<<"4.取子串"<<endl<<"5.串比较"<<endl<<"6.求串长"<<endl<<"7.结束"<<endl;cin>>i;switch(i){case 1:{HString s,t;char a[20],b[20];char *sa,*sb;int pos;cout<<"请输入串s:";cin>>a;sa=a;StrAssign(s,sa);cout<<endl;cout<<"请输入要插入的串t:";cin>>b;sb=b;StrAssign(t,sb);cout<<endl;cout<<"请输入你所要插入的位置:";cin>>pos;StrInsert(s,pos,t);cout<<"插入之后串变为:";Display(s);break;}case 2:{HString s;char str[20];char *chars;int pos,len;cout<<"请输入串s:";cin>>str;chars=str;StrAssign(s,chars);cout<<"请输入你所要删除串的首位置为:";cin>>pos;cout<<endl;cout<<"请输入你需要删除的串的长度:";cin>>len;cout<<endl;StrDelete(s,pos,len);cout<<"删除之后串变为:";Display(s);break;}case 3:{HString s1,s2,t;char a[20],b[20];char *sa,*sb;cout<<"请输入串s1:";cin>>a;sa=a;StrAssign(s1,sa);cout<<"请输入串s2:";cin>>b;sb=b;StrAssign(s2,sb);Concat(t,s1,s2);cout<<"s1与s2合并后:";Display(t);break;}case 4:{HString sub,s;char a[20];char *sa;int pos,len;cout<<"请输入主串s:";cin>>a;sa=a;StrAssign(s,sa);cout<<"请输入所取原串的起始位置pos:";cin>>pos;cout<<"请输入子串的长度len:";cin>>len;SubString(sub,s,pos,len);cout<<"该子串为:";Display(sub);break;}case 5:{HString s,t;int value;char a[20],b[20];char *sa,*sb;cout<<"请输入串s:";cin>>a;sa=a;StrAssign(s,sa);cout<<"请输入串t:";cin>>b;sb=b;StrAssign(t,sb);value=StrCompare(s,t);if(value>0) cout<<"串s大于串t"<<endl;else if(value==0) cout<<"串s等于串t"<<endl;else cout<<"串s小于串t"<<endl;cout<<endl;break;}case 6:HString s;char str[20];char *chars;int val;cout<<"请输入串s:";cin>>str;chars=str;StrAssign(s,chars);val=StrLen(s);cout<<"串的长度为:"<<val<<endl;break;case 7:cout<<"操作结束!"<<endl;break;default:cout<<"输入错误!请重新输入!"<<endl;break;}}while(i!=7);3.KMP算法的C实现#include<iostream.h>#include<malloc.h>#include<string.h>struct HString{char *ch;int length;};void StrAssign(HString &t,char *chars){int i;char *c;for(i=0,c=chars;*c;++i,++c);if(!i){t.ch=NULL;t.length=0;}else{t.ch=(char *)malloc(i*sizeof(char));for(int j=0;j<i;j++)t.ch[j]=chars[j];t.length=i;}}void get_next(HString s,int next[]){int i,j;i=1;j=0;next[1]=0;while(i<s.length){if(j==0||s.ch[i-1]==s.ch[j-1]){i++;j++;next[i]=j;}else j=next[j];}for(i=1;next[i]!='\0';i++)cout<<next[i]<<" ";}int Index(HString s,HString t,int pos){int i=pos;int j=1;int next[20];get_next(t,next);while(i<=s.length&&j<=t.length){if(s.ch[i-1]==t.ch[j-1]||j==0){ ++i;++j;}else{j=next[j];}}if(j>t.length)return i-t.length;else return 0;}void Display(HString t){for(int i=0;i<t.length;i++)cout<<t.ch[i];cout<<endl;}void main(){ HString s,t;int pos,k;char a[20],b[20];char *sa,*sb;cout<<"请输入主串s:";cin>>a;sa=a;StrAssign(s,sa);cout<<"请输入模式串t:";cin>>b;sb=b;StrAssign(t,sb);cout<<"请输入起始位置pos:";cin>>pos;k=Index(s,t,pos);if(k==0)cout<<"匹配失败!"<<endl<<endl;else{cout<<"从第"<<k<<"个位置开始匹配"<<endl;Display(s);for(int i=1;i<k;i++)cout<<" ";Display(t);}}【小结讨论】1. 此程序关键在于位置查询,由于对C语言函数的陌生导致问题变的繁琐,自己的C语言水平有待提高。
数据结构《第4章 串存储与基本操作的实现》
第四章串存储与基本操作的实现本章学习要点◆熟悉串的相关概念以及串与线性表的关系◆重点掌握串的定长存储、堆分配存储的表示方法与基本操作的实现◆了解串的各种存储结构,能根据需要合理选用串的存储结构解决实际问题“串”(string),是字符串的简称,它是一种特殊的线性表,其特殊性在于组成线性表的数据元素是单个字符。
字符串在计算机处理实际问题中使用非常广泛,比如人名、地名、商品名、设备名等均为字符串。
同样在文字编辑、自然语言理解和翻译、源程序的编辑和修改等方面,都离不开对字符串的处理。
4.1串的基本概念4.1.1串的概念1.串的定义串(string)是由n个字符组成的有限序列,记为:S=”a0a1a2…a n-1” (n≥0)。
其中,S是串的名字,字符序列a0a1a2…a n-1是串的值,a i(0≤i≤n-1)可以是字母、数字或其他字符元素;由于在C语言系统中数组元素的下标是从0开始的,所以串中所含元素的序号等于该元素的下标值加1;串中所含字符的个数n称为该串的长度,长度为0的字符串称为空串(null string)。
从串的定义可以看出,串实际上是数据元素为字符的特殊的线性表。
例如:(1)A=“X123” (长度为4的串)(2)B=“12345654321” (长度为11的串)(3)C=“Bei Jing” (长度为8的串)(4)D=“” (长度为0的空串)(5)E=“This is a string” (长度为16的串)(6)F=“ is a ” (长度为6的串)2.子串、主串和位置串中任意连续的字符组成的子序列称为该串的子串;相应地,包含子串的串称为主串。
串中的字符在串序列中的序号称为该字符在该串中的位置;子串的第一个字符在主串中的位置称为子串在主串中的位置。
显然,串为其自身的子串,并规定空串为任何串的子串。
显然,在不考虑空子串的情况下,一个长度为n的字符串具有n(n+1)/2个子串。
例如:在上例的(6)中串F就是(5)中串E的子串,且子串F在主串E中的位置是5。
数据结构第四章 串
数据结构第四章串在数据结构的世界里,串是一种非常基础且重要的结构。
它看似简单,却在很多实际的程序设计和应用中发挥着关键作用。
串,简单来说,就是由零个或多个字符组成的有限序列。
这就好比我们日常生活中的一句话、一段文字或者一个密码。
从存储方式上来看,串可以采用顺序存储和链式存储两种方式。
顺序存储就像是把一串珠子穿在一根线上,珠子依次排列,位置固定。
在计算机中,我们可以用一个连续的数组来存储串中的字符。
这种方式简单直观,访问速度快,但存在着一些局限性。
比如说,如果我们事先不知道串的长度,可能会造成存储空间的浪费或者不足。
相比之下,链式存储则更加灵活。
它就像把珠子用链条串起来,每个珠子(也就是字符)都有一个指针指向下一个珠子。
这样,即使在插入或删除字符时,也不需要像顺序存储那样进行大量的数据移动。
但是,链式存储的缺点是访问速度相对较慢,因为需要通过指针依次查找。
接下来,让我们看看串的一些基本操作。
串的比较是经常会用到的操作。
比较两个串的大小,不能像比较数字那样简单地直接比较,而是要从串的第一个字符开始,逐个字符进行比较。
如果在某个位置上的字符不同,那么 ASCII 码值大的那个串就更大;如果前面的字符都相同,但是一个串先结束了,那么长度短的串就更小。
串的连接也是常见的操作。
想象一下把两段绳子接在一起,就形成了一个更长的绳子。
串的连接也是类似的道理,把两个串首尾相连,形成一个新的串。
但在实际操作中,要注意存储空间的分配,确保有足够的空间来容纳连接后的串。
还有串的子串操作。
比如说,从一篇文章中截取一段文字,这就是获取一个子串。
在程序中,我们需要明确指定子串的起始位置和长度,才能准确地获取到所需的部分。
串的模式匹配更是一个重要的应用。
这就像是在一篇长篇小说中寻找特定的关键词或者短语。
最常见的模式匹配算法有朴素模式匹配算法和 KMP 算法。
朴素模式匹配算法比较直接,就是从主串的开头逐个字符与模式串进行匹配。
而 KMP 算法则通过对模式串进行预处理,利用已经匹配的部分信息,减少不必要的比较,从而提高匹配的效率。
数据结构第4章 串
/*若串s和t相等则返回0;若s>t则返回正数;若s<t则返 回负数*/
{ int i;
for (i=0;i<s.len&&i<t.len;i++)
if (s.ch[i]!=t.ch[i]) return(s.ch[i] - t.ch[i]);
初 始 条 件 : 串 S 存 在 ,1≤pos≤StrLength(S) 且 1≤len≤StrLength(S)-pos+1
操作结果:用Sub返回串S的第pos个字符起长度为len的子串
返回主目录
(11)StrIndex(S,T,pos)
初始条件: 串S和T存在,T是非空串, 1≤pos≤StrLength(S)
return(s.len); }
返回主目录
(7)清空函数
StrClear(SString *s) /*将串s置为空串*/ {
s->len=0; }
返回主目录
(8)连接函数
(1) 连接后串长≤MAXLEN,则直接将B加在A的 后面。 (2) 连接后串长>MAXLEN且LA<MAXLEN,则B 会有部分字符被舍弃。 (3) 连接后串长>MAXLEN且LA=MAXLEN,则B 的全部字符被舍弃(不需连接)。
for (i=s->len + t.len-1;i>=t.len + pos;i--)
s->ch[i]=s->ch[i-t.len];
for (i=0;i<t.len;i++) s->ch[i+pos]=t.ch[i];
s->len=s->len+t.len;
数据结构--第四章 串
则:串s3是s1的子串, s1是s3的主串;
串s2不是s1的子串
5
串的概念
串的位置:字符在序列中的序号为 该字符在串中的位置。子串在主 串中的位置则以子串的第一个字 符在主串中的位置来表示。特别 地,空串是任意串的子串,任意 串是其自身的子串。 例如: s1=’I have a dog’; s3=’dog’ 则:子串s3在s1中的位置为匹配(求子串位置) 第一趟:
i=1
a b a b c a b c a c b a b
J=1
a b c
31
串基本操作的实现 —— 串的模式匹配(求子串位置) 第一趟:
i=3
a b a b c a b c a c b a b
J=3
a b c
32
串基本操作的实现 —— 串的模式匹配(求子串位置) 第二趟:
D A T A S T R U C T U R E
D U R
A S C E
T T T
A R U
19
串的存储结构——动态存储结构
串的动态存储方式采用链式存储结构 和堆存储结构两种形式: (一) (二) 块链存储 堆结构
20
串的动态存储结构 ——块链存储的引入
用单链表存放串,每个结点仅存储一个字符, 每个结点的指针域所占空间比字符域所占空间 要大得多。定义如下: typedef struct node{ char ch; struct node *next;
9
串的基本操作定义
⑵ 判等函数:Equal(s,t)
若s和t相等, 则返回函数值(即运算结 果)1, 否则返回函数值 0。s和t可以是 非空串,也可以是空串。 例如, 执行Equal (a,b) 后, 值为0。 执行Equal (‘abc’,‘abc’) 后, 值为1。
数据结构第四章串ppt
昌
顺序存储结构
大
链接存储结构
学
索引存储结构
科
技 学
不讲
院
6
4.2.1 串的顺序存储结构
南• 1.顺序存储的类型定义
昌• 顺序串的类型定义与顺序表的定义相似,可以用一个字符
大 型数组和一个整型变量表示,其中字符数组存储串,整型
学 变量表示串的长度。
科 技•
如串S=“Beijing”,字符串从S.ch[0]单元开始存放,用‘\0’
{ p=(linkstring *)malloc(LEN); p->data=t[k++];
y->next=p; y=p;}
y->next=NULL; return(s);
}/* L_STRASSIGN */
26
(2)求链串长度函数L_strlen(head):求带头结点 链串head的长度。
南 昌
图4-2
十分浪费。
8
4.2.1 串的顺序存储结构
• (2)紧凑存储。同样存
南 昌
储S="Hello boy",用紧
大 凑格式一个地址能存四
学 个字符,如图5-3所示。 科 技 紧凑存储的优点是空间
学 利用率高,缺点是对串
院 中字符处理的效率低。
存储地址 1000 1001 1002 1003
字长为4
}/* S_STRLEN */
22
(3)顺序串的比较函数S_strcmp(s1, s2):比较两个顺序串的 大小。若s1=s2,则函数返回0;若s1>s2,则函数返回正数; 若s1<s2,则函数返回负数。
/* 两个顺序串比较函数,函数返回值为0、正数或负数 */
数据结构第四章 串
//把串S中符合T的子串替换
StrInsert (&S, pos, T)
//插入子串
StrDelete (&S, pos, len) //删除子串
9
第4章 串
4.1 串类型的定义 4.2 串的表示和实现 4.3 串的模式匹配算法
10
4.2 串的表示和实现
4.2.1 定长顺序存储表示 4.2.2 堆分配存储表示 4.2.3 串的块链存储表示
串的连接算法
Status Concat(SString S1, SString S2, SString &T) { // 用T返回由S1和S2联接而成的新串。若未截断, 则返回 TRUE,否则FALSE if (S1[0]+S2[0] <= MAXSTRLEN) { //空间大,不用截断
T[1...S1[0]] = S1[1...S1[0]]; T[S1[0]+1…S1[0]+S2[0]] = S2[1…S2[0]]; T[0] = S1[0]+S2[0]; uncut = TRUE; }
Concat (&T, S1, S2) //连接串
StrEmpty (S)
//判断串是否空
8
4.1 串类型的定义
基本操作
SubString (&Sub, S, pos, len) //求子串
ClearString (&S)
//清空串S
Index (S, T, pos)
//子串定位
Replace (&S, T, V)
return OK; }
16
4.2 串的表示和实现
4.2.1 定长顺序存储表示 4.2.2 堆分配存储表示 4.2.3 串的块链存储表示
06《数据结构》第四章串
06《数据结构》第四章串数据结构北京邮电大学信息安全中心武斌母版副本12上章内容上一章(栈和队列)内容:.掌握栈和队列这两种抽象数据类型的特点.熟练掌握栈类型的两种实现方法.熟练掌握循环队列和链队列的基本操作实现算法.理解递归算法执行过程中栈的状态变化过程母版副本13本次课程学习目标.理解“串”类型定义中各基本操作的特点.能正确利用这些特点进行串的其它操作.理解串类型的各种存储表示方法.理解串匹配的各种算法学习完本次课程,您应该能够:母版副本14本章课程内容(第四章串)4.1 串类型的定义4.2 串的表示和实现4.3 串的模式匹配算法4.4 串操作应用举例dian3dian3dian3dian3母版副本15第四章串.串即字符串,是计算机非数值处理的主要对象之一。
在早期的程序设计语言中,串仅作为输入和输出的常量出现。
.随着计算机应用的扩展,需要在程序中进行对“串”的操作,从而使众多编程语言增加了串类型,以便程序员可以在程序中对“串变量”进行操作。
.现今使用的计算机的硬件结构主要是面向数值计算的需要,基本上没有提供对串进行操作的指令。
.因此需要用软件来实现串数据类型。
而且,在不同的应用中,所处理的串具有不同的特点,为有效地实现串的操作,需要根据具体情况使用合适的存储结构。
母版副本16串的类型定义4.1 串的类型定义4.2 串的表示和实现4.3 串的模式匹配算法4.4 串操作应用举例diandian3dian3dian3母版副本17串的类型定义.串(String)是零个或多个字符组成的有限序列。
一般记作S=“a1a2a3…an”,其中S是串名,双引号括起来的字符序列是串值;ai(1≦i≦n)可以是字母、数字或其它字符;串中所包含的字符个数称为该串的长度。
长度为零的串称为空串(EmptyString),它不包含任何字符。
.通常将仅由一个或多个空格组成的串称为空格串(BlankString)。
.注意:空串和空白串的不同,例如“”和“”分别表示长度为1的空格串和长度为0的空串。
第4章 串
数
据
结
构
与
算
法
(4)串比较(compare) int strcmp(char *s1,char *s2); 该函数比较串s1和串s2的大小,当返回值小于0,等于0 或大于0时分别表示s1<s2、s1=s2或s1>s2 例如:result=strcmp(“baker”,”Baker”) result>0 result=strcmp(“12”,”12”); result=0 result=strcmp(“Joe”,”Joseph”); result<0 (5)字符定位(index) char strchr(char *s,char c); 该函数是找字符c在字符串中第一次出现的位置,若找到 则返回该位置,否则返回NULL。 例如:p=strchr(s2,’.’); p 指向“file”之后的位置 s2=“file.cpp”
}
沈阳工业大学
数
据
结
构
与
算
法
2堆分配存储表示
这种存储表示的特点是,仍以一组地址连续的存储单元 存放串值字符序列,但它们的存储空间是在程序执行过程中 动态分配而得。所以也称为动态存储分配的顺序表。在C语 言中,利用动态存储管理函数,来根据实际需要动态分配和 释放字符数组空间。 typedef char *string; //c中的串库相当于此类型定义
沈阳工业大学
数
据
结
构
与
算
法
串中任意个连续字符组成的子序列称为该串的子串 ,包含子串的串相应地称为主串。通常将子串在主串中 首次出现时的该子串的首字符对应的主串中的序号,定 义为子串在主串中的序号(或位置)。例如,设A和B分 别为 A=“This is a string” B=“is” 则B是A的子串,A为主串。B在A中出现了两次,其中首 次出现所对应的主串位置是3。因此,称B在A中的序号 (或位置)为3。 特别地,空串是任意串的子串,任意串是其自身的 子串。 通常在程序中使用的串可分为两种:串变量和串常 量。
数据结构(C++) 第4章 串
NCU-ZQP
11
4.2 串的存储表示
串的存储表示主要指串值的存储。 串的存储表示主要指串值的存储。 串值的存储 一个字符序列还可赋给串变量, 一个字符序列还可赋给串变量 , 作为变量的内容 串值) 需通过变量名进行访问。 (串值),需通过变量名进行访问。 串被看成由单个字符组成的特殊的线性表, 因此, 串被看成由单个字符组成的特殊的线性表 , 因此 , 线性表所用的存储结构基本上都可以应用到串上, 线性表所用的存储结构基本上都可以应用到串上 , 这里 所说的串是指串值。主要介绍: 所说的串是指串值。主要介绍: 串的定长顺序存储表示; 串的定长顺序存储表示; 串的堆分配存储表; 串的堆分配存储表; 串的块链存储表示; 串的块链存储表示;
NCU-ZQP 5
串的术语
当两个串的长度相等, 当两个串的长度相等,且对应位置的字符相 两个串相等。 同时,称这两个串相等 同时,称这两个串相等。 有两种串量可供使用,一种是串常量,另一 有两种串量可供使用,一种是串常量, 种是串变量。串常量具有固定串值 具有固定串值。 串变量的 种是串变量。串常量具有固定串值。而串变量的 内容串值是可以改变的,须用标识符对其命名。 内容串值是可以改变的,须用标识符对其命名。 例如: 例如: char *ch1, ch2[20]; ; ch1="Hello! "; strcpy (ch2, "Good! " ); ch1 和ch2 就是串变量名,它们的串值(内 就是串变量名,它们的串值( 分别是: 容)分别是:Hello!和Good!。 和 。
NCU-ZQP
char *s1="It is a car"; char *s2="jeep"; char *s3="car"; char *s4; int result;
数据结构第四章
T 插入串
S pos
T 插入后
A
A串部分被舍弃
MAXLEN
(3) 插入后串长(st+st+st≥MAXLEN且pos+st>MAXLEN,则A全部 字符被舍弃(不需后移),并且T在插入时也有部分字符被舍弃
S pos
A 插入前
S pos
T 插入后
MAXLEN 舍弃
T 插入串
S.ch 0 1 2 3 4 5 6 7 8 9 10 … abcde fgh i j k
st
MAXLEN-1 …
串的长度st+1
省级精品课程配套教材 高等学校计算机类“十二五” 规划2教. 在材串尾存储一个特殊字符作为串的终结符
比如C语言中用’\0’来表示串的结束。 char s[MAXLEN];
5 { /*连接后串长小于MAXLEN */
6 for(i=S->last; i<=S->last+st; i++)
7
S->ch[i+1]=T.ch[i-S->last];
8 S->last=S->last+st+1;
省级精品课程配套教材
高等学校计算机类“十二五”
规划教材
第四章 串
1.教学目的:
掌握串的定义、基本运算的实现及基本串匹配算法。
2.教学要求:
①理解串的七种基本运算的定义。 ②掌握利用这些基本运算来实现串的其它各种运算的方法。 ③掌握在顺序存储结构上实现串的各种操作的方法。 ④理解KMP算法,了解NEXT函数和改进NEXT函数的定义和计算。 ⑤理解串名的存储映象和在堆存储结构实现串操作的方法。
数据结构-第四章串
数据结构-第四章串串也叫字符串,它是由零个或多个字符组成的字符序列。
基本内容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相同的⼦串的⾸字母在主串中的位置。
《数据结构》--第四章 串
4.3 串的基本运算
4、插入子串: insert(s,s1,i) 在串s的第i个位置插入串s1。 5、删除子串: delete(s,i,j) 从串s的第i个位置开始,连续删除j个 字符。 6、子串定位: match(s,s1) 返回子串s1在串s中第一次出现的位置。 7、子串替换: replace(s,s1,i,j) 将串s中从第i个位置开始的长度 为j的子串用串s1来替换。
1. 串连接
串连接就是把两个串连接在一起,其中一个 串接在另一个串的末尾,生成一个新串。 如给出两个串s1和s2,把s2连接到s1之后, 生成一个新串s。
1. 串连接
例如,有两个串分别为s1 = ″Good ″, s2 = ″morning!″,则调用函数connect(s1, s2) 后,生成一个新串s = ″Good morning!″
4.2 串的存储结构
4.2.1 串的静态存储结构
串的静态存储结构采用顺序存储结构,简称为顺 序串。在计算机中,一个字符只占一个字节,所以串 中的字符是顺序存放在相邻字节中的。 串的顺序存储可用一个字符型数组和一个整型变 量来表示,其中字符型数组存放串值,整型变量存放 串的长度。
4.2 串的存储结构
4.2.2 串的链式存储结构
串的链式存储结构也称为链串,结构与链表类似,链串 中每个结点有两个域,一个是值域(data),用于存放字符 串中的字符,另一个是指针域(next),用于存放后继结点 的地址。 一个链串一般是由头指针唯一确定的。
优点:插入、删除运算很方便。
4.2 串的存储结构
存储密度 = 串值所占的存储位 / 实际分配的存储位 为了提高存储密度,可让每个结点的值域存放多个字符。 这种结构也叫做大结点结构。 如串s = “good morning!”的存储结构如下图所示。
数据结构04
2.基本运算在顺序存储结构上的实现
在顺序存储结构中,串的类型定义描述如下:
#define MaxLen <最大串长>; //定义能处理的最大的串长度
typedef struct {
char str[MaxLen];
//定义可容纳MaxLen个字符的字符数组
int curlen;
//定义当前实际串长度
char data[4]; struct node *next; } lstring;
采用链式存储结构(结点大小为1),实现串的联接、求子串
以及串的置换基本运算见教科书 P83 。
2019/8/31
19
4.2.3 串的堆分配存储结构及其基本运算的实现
1.堆分配存储结构
堆存储结构的特点是,仍以一组空间足够大的、地址连续的 存储单元存放串值字符序列,但它们的存储空间是在程序执行过 程中动态分配的。所以也称为动态存储分配的顺序表。每当产生 一个新串时,系统就从剩余空间的起始处为串值分配一个长度和 串值长度相等的存储空间。
typedef struct Chunk {
//结点结构
char str[CHUNKSIZE];
struct Chunk *next;
} Lstring;
一个链串由头指针唯一确定。
这种结构便于进行插入和删除运算,但存储空间利用率太低。
为了提高存储密度,可使每个结点存放多个字符。通常将结
点数据域存放的字符个数定义为结点的大小,显然,当结点大小
}
}
return(0);
}2019/8/31
10
4.2 串的存储结构
串是一种特殊的线性表,其存储结构与线性表的存储结构 类似,只不过组成串的结点是单个字符。串的存储结构表示
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第四章串存储与基本操作的实现本章学习要点◆熟悉串的相关概念以及串与线性表的关系◆重点掌握串的定长存储、堆分配存储的表示方法与基本操作的实现◆了解串的各种存储结构,能根据需要合理选用串的存储结构解决实际问题“串”(string),是字符串的简称,它是一种特殊的线性表,其特殊性在于组成线性表的数据元素是单个字符。
字符串在计算机处理实际问题中使用非常广泛,比如人名、地名、商品名、设备名等均为字符串。
同样在文字编辑、自然语言理解和翻译、源程序的编辑和修改等方面,都离不开对字符串的处理。
4.1串的基本概念4.1.1串的概念1.串的定义串(string)是由n个字符组成的有限序列,记为:S=”a0a1a2…a n-1” (n≥0)。
其中,S是串的名字,字符序列a0a1a2…a n-1是串的值,a i(0≤i≤n-1)可以是字母、数字或其他字符元素;由于在C语言系统中数组元素的下标是从0开始的,所以串中所含元素的序号等于该元素的下标值加1;串中所含字符的个数n称为该串的长度,长度为0的字符串称为空串(null string)。
从串的定义可以看出,串实际上是数据元素为字符的特殊的线性表。
例如:(1)A=“X123” (长度为4的串)(2)B=“12345654321” (长度为11的串)(3)C=“Bei Jing” (长度为8的串)(4)D=“” (长度为0的空串)(5)E=“This is a string” (长度为16的串)(6)F=“ is a ” (长度为6的串)2.子串、主串和位置串中任意连续的字符组成的子序列称为该串的子串;相应地,包含子串的串称为主串。
串中的字符在串序列中的序号称为该字符在该串中的位置;子串的第一个字符在主串中的位置称为子串在主串中的位置。
显然,串为其自身的子串,并规定空串为任何串的子串。
显然,在不考虑空子串的情况下,一个长度为n的字符串具有n(n+1)/2个子串。
例如:在上例的(6)中串F就是(5)中串E的子串,且子串F在主串E中的位置是5。
由于空格符也是一个字符,所以在串G=“abc defghne”中包含有子串“c def”,而串“cdef”不是串G的子串。
串G中第一个字符…e‟的位置是6,第二个字符…e‟的位置是11。
3.串的比较如果两个串的长度相等且对应位置上的字符相同,则称这两个串相等。
两个串A、B的比较过程是:从前往后逐个比较对应位置上的字符的ASCII码值,直到不相等或有一个字符串结束为止,此时的情况有以下几种:(1)两个串同时结束,表示A等于B;(2)A中字符的ASCII码值大于B中相应位置上字符的ASCII码值或B串结束,表示A大于B;(3)B中字符的ASCII码值大于A中相应位置上字符的ASCII码值或A串结束,表示A小于B。
例如:“abc”=“abc”,“abc”<“abcd”,“abxy”>“abcdefg”,“132”>“123456”“ABab”<“abAB”,“3+2”>“2+3”。
4.空格串由一个或多个空格字符组成的串称为空格串,空格串的长度为串中所含空格字符的个数。
在串操作中不要将空格串和空串混淆。
4.1.2串的基本操作尽管串的定义和线性表极为相似,但是串的基本操作和线性表有很大差别。
在线性表的基本操作中,大多以单个元素作为操作对象,比如对线性表的查找、访问、插入、删除和排序等;而在串的基本操作中,通常以串整体或串的一部分(子串)作为操作对象,比如子串的查找、截取子串、删除一个子串、插入子串和子串替换等操作。
串的基本操作主要有:(1)StrAssign(&T,chars)—由字符串常量chars生成字符串T的操作。
(2)StrCopy(&T,S)—由串S复制生成串T的操作。
(3)StrCompare(S,T)—若S=T返回0,S>T返回正数,S<T返回负数。
(4)StrLength(S)—返回串S的长度。
(5)Concat(&T,S1,S2)—将串S1和S2连接起来生成串T的操作。
(6)SubString(&Sub,S,pos,len)—以串S中pos位置开始的len个字符生成子串Sub的操作。
(7)Index(S,T,pos)—返回子串T在S中pos个字符以后出现的位置。
(8)Replace(&S,T,V)—将串S中所有不重叠子串T替换为串V的操作。
(9)StrInsert(&S,pos,T)—在串S中第pos个字符前插入串T的操作。
(10)StrDelete(&S,pos,len)—删除串S中第pos个字符开始的len个字符的操作。
4.2串的存储表示与实现既然串是线性表的特例,所以线性表的两种存储结构对于串也是适用的。
在应用中具体选用何种存储结构与串的操作有关,比如对串进行插入和删除操作运算时选用链存储结构较好,对串进行查找和求子串运算时选用顺序存储结构较好。
本章主要介绍串的3种存储表示方法:(1)串的定长顺序存储表示法(2)串的堆分配存储表示法(3)串的块链式存储表示法4.2.1串的定长顺序存储表示串的定长顺序存储表示是用一组地址连续的存储单元来存储串中的字符序列。
在串的定长顺序存储表示中,按照预定义的大小,为每个定长的串变量分配一个固定长度的存储区,所以可以用定长字符数组来表示。
1.定长顺序存储结构在C++运行环境中,定长顺序结构定义为:#include"iostream.h"#include"stdio.h"#define MAXLEN 255 //定义串的最大长度为255typedef char SString[MAXLEN+1]; //定义定长顺序存储类型SString2.基本操作的C++程序实现(1)求串长度操作int Length_SS(SString S)操作返回串S中所含字符的个数,即串的长度;如果S为空串则返回0。
int Length_SS(SString S){int i=0;while(S[i])i++;return i;}(2)串连接操作int Concat_SS(SString &T,SString S1,SString S2)该操作将串S1、S2连接生成串T,如果在连接过程中产生了截断(即S1的长度加上S2的长度大于MAXLEN)则返回0,否则返回1。
int Concat_SS(SString &T,SString S1,SString S2){int i,j,k;i=j=k=0;while(T[i++]=S1[j++]);i--;while(i<MAXLEN&&(T[i]=S2[k])){ i++;k++; }T[i]=0;if((i==MAXLEN)&&S2[k]) /*判断是否产生截断*/return(0);elsereturn(1);}(3)求子串操作int SubString_SS(SString &Sub,SString S,int pos,int len)该操作截取串S中从第pos个字符开始的连续的len个字符生成子串Sub,如果位置pos和长度len合理则返回1,否则返回0.int SubString_SS(SString &Sub,SString S,int pos,int len){int i=0;if(pos<1||len<0||pos+len>Length_SS(S)+1) /*判断位置和长度是否合理*/ return 0;while(i<len){Sub[i]=S[i+pos-1]; i++; }Sub[i]='\0';return 1;}(4)初始化串操作int StrAssign_SS(SString &T,char *s)该操作用字符数组s,初始化定长顺序串T。
如果不产生截断(长度合理)返回1,否则返回0。
int StrAssign_SS(SString &T,char *s){int i=0;while(i<MAXLEN&&(T[i]=s[i]))i++;T[i]=0;if((i==MAXLEN)&&s[i]) /*判断是否产生截断*/return 0;else return 1;}(5)串复制操作void StrCopy_SS(SString &T,SString S)该操作将定长顺序串S,复制到定长顺序串T。
void StrCopy_SS(SString &T,SString S){int i=0;while(T[i]=s[i])i++;}(6)串比较操作int StrCompare_SS(SString S,SString T)该操作比较顺序串S、T的大小,如果S>T则返回正数,如果S=T则返回0,否则返回负数。
int StrCompare_SS(SString S,SString T){int i=0;while(S[i]&&T[i]&&(S[i]==T[i]))i++;return (int)(S[i]-T[i]);}(7)串的替换操作int Replace_SS(SString &S,int n,int m,SString T)该操作将串S中从第n个字符开始的连续的m个字符替换成串T中的字符,如果n和m的选取合理则返回1,否则返回0。
int Replace_SS(SString &S,int n,int m,SString T){SString S1;int len=Length_SS(T);int i=n-1,j=0,k=n+m-1; /*i为开始替换位置,j指向第一个替换字符,k为剩余字符的开始位置*/if(n<1||m<0||n+m>Length_SS(S)+1||Length_SS(S)+len-m>MAXLEN) /*判断位置是否合理*/ return(0);StrCopy_SS(S1,S); /*将剩余部分复制到S1中*/while(S[i++]=T[j++]); /*替换S中指定部分的字符*/i--;while(S[i++]=S1[k++]); /*将剩余部分复制到S中*/return(1);}(8)主函数演示程序main()void main_SS(){SString s1,s2,s3,sub,T;char str1[100],str2[100];int l1,l2,l3,pos,len,n;while(1){cout<<"(1)串初始化操作:\n输入两个字符串:\n";cin.getline(str1,sizeof(str1));//表示从键盘输入一个可以含有空格字符的长度小于100的字符串到str1中,//语句“cin>>str1”不能输入空格字符(空格符表示输入结束)且对串的长度不做检查。