Your SlideShare is downloading. ×
第四章 串
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

第四章 串

200
views

Published on

严蔚敏 - 数据结构

严蔚敏 - 数据结构

Published in: Technology

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
200
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
1
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. 第四章 串 4.1 串类型的定 义4.2 串的表示和实现
  • 2. 学习提要: 1. 熟悉串的基本操作的定义,并能利用这些基本操作来实现串的其它各种操作的方法。 2. 熟练掌握在串的定长顺序存储结构上实现串的各种操作的方法。 3. 掌握串的堆分配存储结构以及在其上实现串操作的基本方法。4. 了解串的块链存储结构。重难点内容: 串的存储结构
  • 3. §4.1 串类型的定义基本概念串( string ):由零个或多个字符组成的有限序列,也称字符串。记为: S = ‘a1a2a3……an’ (n≥0) 如: A= ‘BEIJING’ , B=‘JING’
  • 4. 空串:不含任何字符的串,串长度为0, 用“ ” 或 ‘ ’ 表示。空格串:仅由一个或多个空格组成的串, 长度为串中空格字符的个数。 如: ‘ ’ , C= ‘ BEI JING ’子串:由串中任意个连续的字符组成的
  • 5. 字符在串中的位置:字符在序列中的序号。子串在主串中的位置:以子串的第一个字符在主串中的位置来表示。 如: A= ‘ BEIJING ’ , B= ‘JING ’ , B 在 A 中的位置为 4 。 串相等:当且仅当两个串的值相等。也就是说,只有两个串的长度相等且各个对应位置的字符都相等时才相等。
  • 6. 串的抽象数据类型定义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
  • 7. StrAssign (&T, chars) // 串赋值 初始条件: chars 是字符串常量。 操作结果:把 chars 赋为 T 的值。StrCopy (&T, S) // 串复制 初始条件:串 S 存在。 操作结果:由串 S 复制得串 T 。DestroyString (&S) 初始条件:串 S 存在。 操作结果:串 S 被销毁。
  • 8. ClearString (&S) 初始条件:串 S 存在。 操作结果:将 S 清为空串。StrEmpty (S) 初始条件:串 S 存在。 操作结果:若 S 为空串,则返回 TRUE ,否则返回 FALSE 。
  • 9. StrCompare (S, T) // 串比较 初始条件:串 S 和 T 存在。 操作结果:若 S>T ,则返回值 >0 ; 若 S=T ,则返回值 =0 ; 若 S<T ,则返回值 <0 。 StrCompare(‘data’, ‘structure’) <0字符串的比较规则 : 对两个字符串自左至右逐个字符相比 ( 按 ASCII 码值大小 ), 直到出现不同字符或遇到结束符为止 . 如全部字符相同则认为相等 ; 若出现不相同的字符 , 则以第一个不相同的字符的比较结果为准 , 如上例 “ d”<“s”. 因此比较结果小于 0 。
  • 10. StrLength (S) // 求串长 初始条件:串 S 存在。 操作结果:返回 S 的元素个数,称为串的长度。
  • 11. Concat (&T, S1, S2) // 串联接 初始条件:串 S1 和 S2 存在。 操作结果:用 T 返回由 S1 和 S2 联接而成的新串。 Concat(&T,‘data’, ‘structure’) T=‘datastructure’
  • 12. SubString (&Sub, S, pos, len) // 求子串 初始条件:串 S 存 在, 1≤pos≤StrLength(S) 且 0≤len≤StrLength(S)-pos+1 。 操作结果:用 Sub 返回串 S 的第 pos 个 字符起长度为 len 的子串。SubString(&sub, ‘data structure’, 6, 9) Sub=‘structure’
  • 13. Index (S, T, pos) // 串定位 初始条件:串 S 和 T 存在, T 是非空串, 1≤pos≤StrLength(S) 。 操作结果:若主串 S 中存在和串 T 值相同 的子串 , 则返回它在主串 S 中第 pos 个字符之 后第一次出现的位置 ; 否则函数值为 0 。假设: S = ′abcaabcaaabc′, T = ′bca′ Index(S, T, 1) = 2 ; Index(S, T, 3) = 6 ; Index(S, T, 8) = 0 ;
  • 14. Replace (&S, T, V) // 串替换 初始条件:串 S,T 和 V 存在, T 是非空串。 操作结果:用 V 替换主串 S 中出现的所有与 T 相等的不重叠的子串。例如: S=‘abcaabc’, T=‘ab’, V=‘x’ S=‘xcaxc’ V=‘bc’ S=‘bccabcc’
  • 15. StrInsert (&S, pos, T) 初始条件:串 S 和 T 存在, 1≤pos≤StrLength(S) + 1 。 操作结果:在串 S 的第 pos 个字符之 前插例如: S =‘ god’ , T 。 入串 StrInsert ( & S,2, ‘o’) S=‘good’
  • 16. StrDelete (&S, pos, len) 初始条件:串 S 存在, 1≤pos≤StrLength(S)-len+1 。 操作结果:从串 S 中删除第 pos 个字符 起 长度为 len 的子串。 例如 : S= ‘structure’ , StrDelete( & S, 1, 5) S=‘ture’
  • 17. 对于串的基本操作集可以有不同的 定义方法,在使用高级程序设计语言中的 串类型时,应以该语言的参考手册为准。例如: C 语言函数库中提供下列串处理函数: K 的作用是将 s tr2 中前 gets(str) 输入一个串; k 个字符复制到 s rt1 中 puts(str) 输出一个串; 去,取代 s tr1 中最前面 k 个字符。 strcat(str1, str2) 串联接函数; strcpy(str1, str2, k) 串复制函数; strcmp(str1, str2) 串比较函数; strlen(str) 求串长函数;
  • 18. 在以上操作中,串赋值 StrAssign 、串复制 Strcopy 、串比较 StrCompare 、求串长StrLength 、串联接 Concat 、求子串SubString6 种操作构成串类型的最小操作子集,即:这些操作不可能利用其他串操作来实现,反之,其他串操作(除串清除ClearString 和串销毁 DestroyString 外)可在这个最小操作子集上实现。
  • 19. 例如,可利用串比较、求串长和求子串 等操作实现定位函数 Index(S, T,pos) 。 算法的基本思想为 :StrCompare(SubString(S, i, StrLength(T)), T) = = 0 i S 串 pos T 串 n-m+1 T 串 在主串 S 中取出从第 i 个字符起,长度和串 T 相等的子串和串 T进行比较,若相等,则求得函数值为 i ;否则 i 值增 1 直至串 S 中不存在和串 T 相等的子串为止。
  • 20. int Index (String S, String T, int pos) {// T 为非空串。若主串 S 中第 pos 个字符之后存在与 T 相等的子则返回第一个这样的子串在 S 中的位置,否则返回 0 if (pos > 0) { n = StrLength(S); m = StrLength(T); i = pos; while ( i <= n-m+1) { SubString (sub, S, i, m); // 从 S 中取子串置于 sub 中 if (StrCompare(sub,T) != 0) ++i ; else return i ; } // while } // if return 0; // S 中不存在与 T 相等的子串} // Index
  • 21. C++ 中的 String 类 C++ 标准类库将面向对象串的概念加入到 C+ + 语言中。串类封装了类的属性,并提供了一 系列允许访问这些属性的服务。例如: String 类的一些主要的成员函数有:string append(const char *s); // 将字符串 s 加在本串尾string assign(const char *s); // 赋值Int compare(const string& str); // 比较本串与 str 中串的大小 string insert(int p0, const *s); // 将 s 所指向的字符串插入本串位置 p0 之前
  • 22. 串的逻辑结构和线性表极为相似,区别仅在于串的数据对象约束为字符集。 串的基本操作和线性表有很大差别。 在线性表的基本操作中,大多以“单个元素 ” 作为操作对象; 在串的基本操作中,通常以“ 串的整体 ” 作为操作对象。
  • 23. §4.2 串的表示和实现4.2.1 串的定长顺序存储表示4.2.2 串的堆分配存储表示4.2.3 串的块链存储表示
  • 24. 4.2.1 定长顺序存储表示 用一组地址连续的存储单元存储串值的字符序列,类似于线性表的顺序存储结构。所谓定长顺序存储结构,是直接使用定长的字符数组来定义,数组的上界预先给出: #define MAXSTRLEN 255 // 用户可在 255 以内定义最大串 长 typedef unsigned char SString[MAXSTRLEN + 1];
  • 25. 特点 :串的实际长度可在这个予定义长度的范围内随意设定,超过予定义长度的串值则被舍去,称之为“ 截断” 。按这种串的表示方法实现的串的运算时,其基本操作为 “ 字符序列的复制 ” 。
  • 26. 1 .串联结Contcat ( &T,S1,S2 ) S1 [ 0 S2 [ 0 ] ]S1 S2T T[0] MAXSTRLEN S1[0]+S2[0] <= MAXSTRLEN
  • 27. S1 [ 0 S2 [ 0 ] ] S1 S2 S2 中被截去的 T 字符序列 T[0] MAXSTRLENS1[0] < MAXSTRSIZE 而 S1[0]+S2[0] > MAXSTRSIZE
  • 28. S1 [ 0 S2 [ 0 ] ]S1 S2T S2 串被全部截 去 T[0] MAXSTRLEN S1[0] = MAXSTRLEN
  • 29. Status Concat(SString S1, SString S2, SString &T) { 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;} else if (S1[0] < MAXSTRSIZE) { // 截断 T[1…S1[0]] = S1[1…S1[0]]; T[S1[0]+1…MAXSTRLEN]=S2[1…MAXSTRLEN - S1[0]]; T[0] = MAXSTRLEN; uncut = FALSE;} else { S1[0] = MAXSTRSIZE // 截断 ( 仅取 S1) T[0...MAXSTRLEN] = S1[0…MAXSTRLEN]; // T[0] == S1[0] == MAXSTRLEN uncut = FALSE; } return uncut;} // Concat
  • 30. 2 .求子串 SubString(&Sub, S, pos, len)Status SubString(SString&Sub, SString S, intpos,int len) {// 用 Sub 返回串 S 的第 pos 个字符起长度为 len 的子串。其中 1≤pos ≤StrLength(S) 且 0≤len≤StrLength(S)-pos+1 if (pos<1 ||pos>S[0] || len<0 || len>S[0]-pos+1) return ERROR; Sub[1……len]=S[pos…pos+len-1] ; Sub[0]=len ; return OK;} // SubString
  • 31. 定长顺序存储表示的特点与问题1 . 实现串操作的原操作为“ 字符序列的复制” ,操作的时间复杂度基于复制的字符序列的长度。2. 在操作中出现串值序列的长度超过 MaxS trLe n时,约定用截尾法处理,这种情况可能在联结串或插入 , 置换时发生。3. 克服这个问题惟有不限定串长的最大长度,即动态分配串值的存储空间。
  • 32. 4.2.2 堆分配存储表示 以一组地址连续的存储单元存储串值的字符序列,存储空间在程序执行过程中动态分配。 C 语言中提供的串类型就是以这种存储方式实现的。系统利用函数 m allo c () 和 fre e ( ) 进行串值空间的动态管理,为每一个新产生的串分配一个存储区,称串值共享的存储空间为“ 堆”。 C 语言中的串以一个空字符为结束符,串长是一个隐含值。
  • 33. typedef struct { char *ch; // 若是非空串,则按串长分 配存储区 , 否则ch 为 NULL int length; // 串长度} HString;这类串操作实现的算法为: 先为新生成的串分配一个存储空间,然后进行串值的复制。
  • 34. 1. 串赋值Status StrAssign(Hstring&T,char*chars){// 生成一个其值等于串常量 chars 的串 T If ( T.ch ) free (T.ch); // 释放 T 原有空间 for(i=0,c=chars; c; ++i,++c); // 求 chars 的长度i If ( !i ) {T.ch=NULL; T.length=0;} else{ if(!(T.ch=(char*)malloc(i*sizeof(char)))) exit(OVERFLOW); // 开辟空间再赋值 T.ch[0…i-1]=chars[0…i-1]; T.length=i; } return OK;
  • 35. 2. 串比较 ;Int StrCompare(Hstring S,Hstring T){ for(i=0; i<S.length && i<T.length; ++i) if ( S.ch[i] != T.ch[i] ) Return S.ch[i]-T.ch[i]; Return S.length - T.length // 若 S>T, 则返回值 >0; 若 S=T, 则返回值 =0 ; 若 S<T ,则返回值 =0} // StrCompare
  • 36. 3. 串联接Status Concat(Hstring&T,HStringS1,HstringS2){ // 用 T 返回由 S1 和 S2 联接而成的新串if(T.ch) free(T.ch); // 释放旧空间if(!(T.ch=(char*)malloc((S1.length+S2.length)*sizeof(char)))) exit(OVERFLOW);T.ch[0…S1.length - 1]= S1.ch[0…S1.length - 1];T.length= S1.length+ S2.length;T.ch[S1.length…T.length-1]=S2.ch[0…S2.length-1];return OK;} // Concat
  • 37. 4. 取子串Status SubString(HString&Sub,Hstring S,int pos,int len){ // 用 Sub 返回串 S 的第 pos 个字符起长度为 len 的子串。// 其中 1≤pos StrLength(S) 且 0≤ len≤ StrLength(S)-pos+1if (pos<1 ||pos>S.length || len<0||len>S.length-pos+1) return ERROR;if(Sub.ch) free(Sub.ch); // 释放旧空间if (!len){ Sub.ch=NULL; Sub.length=0; } // 空子串else { // 完整子串 Sub.ch= (char*) malloc (len*sizeof(char)); // 取长度 len 分配空间 Sub.ch[0…len-1]=S.ch[pos-1…pos+len-2] ; Sub.length=len ;return OK;
  • 38. 4.2.3 块链存储表示 以链表存储串值,除头指针外还可以附设一个尾指针指示链表中的最后一个结点,并给出当前串的长度。称如此定义的串存储结构为 块链结构。 结点大小 块链结构
  • 39. #define CHUNKSIZE 80 // 可由用户定义的块大小typedef struct Chunk { // 结点结构 char ch[CUNKSIZE]; struct Chunk *next; } Chunk;typedef struct { // 串的链表结构 Chunk *head, *tail; // 串的头和尾指针 int curlen; // 串的当前长度 } LString;
  • 40. 例如 : 在编辑系统中,整个文本编辑区可以看成是一个串,每一行是一个子串,构成一个结点。即 : 同一行的串用定长结构(80 个字符 ), 行和行之间用指针相联接。 数据元素所占存储位存储密度 = 实际分配的存储位
  • 41. 存储密度的大小直接影响着串处理的效 率.1. 存储密度小 , 运算处理方便 , 但存储占用 量大 .2. 存储密度小 , 在串处理过程中需要进行内 外存交换的话 , 会因为内外存交换操作过 多而影响处理的总效率 . 串值的链式存储结构对于某些串操作有一定方便处 , 但总的说来不如另外两种存储结构灵活 , 它占用存储量大且操作复杂 .
  • 42. 练习 : 设 s=‘I AM ASTUDENT’ , t=‘GOOD’ ,q=‘WORKER’ ,求:( 1 ) StrLength(s) , StrLength(t)( 2 ) SubString(s, 8, 7) , SubString(t, 2, 1)( 3 ) Index(s, ‘A’,1) , Index(s,t,3)( 4 ) Replace(s, ‘STUDENT’, q)( 5)Concat(SubString(s,6,2),Concat(t,SubString(s,7,8)))