第四章 串

  • 193 views
Uploaded on

严蔚敏 - 数据结构

严蔚敏 - 数据结构

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
193
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
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)))