第四章 串.

Slides:



Advertisements
Similar presentations
数据结构的引入. 通讯录管理 社团机构管理 校园导航管理 通讯录管理 社团机构管理 校园导航管理.
Advertisements

阻塞操作. 在 linux 里,一个等待队列由一个 wait_queue_head_t 类型的结构来描述 等待队列的初始化: static wait_queue_head_t testqueue; init_waitqueue_head(&testqueue);
单元二:面向对象程序设计 任务二:借书卡程序设计.
AI人工智慧報告 黑白棋 班級:資工四乙 學號:498G0009 姓名:盧冠妤.
数据结构——树和二叉树 1/96.
第8章 字串與陣列 8-1 字串處理 8-2 一維陣列的處理 8-3 建立多維陣列 8-4 不規則陣列與參數傳遞 8-5 陣列排序與搜尋.
C++中的声音处理 在传统Turbo C环境中,如果想用C语言控制电脑发声,可以用Sound函数。在VC6.6环境中如果想控制电脑发声则采用Beep函数。原型为: Beep(频率,持续时间) , 单位毫秒 暂停程序执行使用Sleep函数 Sleep(持续时间), 单位毫秒 引用这两个函数时,必须包含头文件
第九章 字符串.
第四章 串 2018/11/13.
第4章 串 串的基本概念和C语言的串函数 串的存储结构 动态数组实现的顺序串 串的模式匹配算法——BF算法 主要知识点.
数据结构 Data Structure 主讲人:王国军,郑瑾 中南大学 中南大学信息院计科系
第4章 串、数组和广义表 丽水学院工学院.
C语言高级编程(第四部分) 字符串 北京大学 信息科学技术学院.
2.5 字符串.
·线性表的定义及ADT ·线性表的顺序存储结构 ·线性表的链接存储结构 · 单向循环链表 · 双链表、双向循环链表 · 一元多项式的加法
数据结构 第4章 串.
线性表小结 元素之间的线性关系 顺序表 顺序表:元素相邻存储 单链表:后继指针链接 一维数组 给定下标随机存取
数据结构——串 1/15.
第四章 串和数组(一) 1/.
串和数组.
第4章 串 4.1 串的基本概念及其抽象数据 4.2 串的存储结构 4.3 串类 4.4 串的模式匹配算法.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
第 3 讲 线性表(一).
第三章 栈和队列.
数 据 结 构 Ch.4 串 计 算 机 学 院 肖明军
陈海明 副教授 信息学院 计算机系 电子信息类非计算机专业选修课 程序设计实践 陈海明 副教授 信息学院 计算机系
4.1 串的抽象数据类型的定义 4.2 串的表示和实现 4.3 串的模式匹配算法.
第4章 串 4.1 串的基本概念 4.2 串的存储结构 4.3 串的模式匹配.
动态规划(Dynamic Programming)
数据结构概论 第4章 串 董黎刚 浙江工商大学信电学院 2019年1月18日.
第三章 栈和队列.
第四章串 4.1 串类型定义 4.2 串的表示和实现 4.3 串的模式匹配算法 4.4 串操作应用举例.
第四章 串.
第七章 操作符重载 胡昊 南京大学计算机系软件所.
第4章 串和数组 本章主要介绍下列内容: 串的定义、存储结构和基本运算 数组的定义、基本运算和存储结构 特殊矩阵的压缩存储.
从zval看PHP变量
第五章 串和数组 5.1 串的定义和操作 5.2 串的表示和实现 5.3 字符串应用 5.4 字符串匹配算法 5.5 数组
7.1 广义表的概念 广义表是n(n≥0)个数据元素组成的序列,其中每个数据元素或是单个数据元素(简称原子),或仍然是一个广义表 。
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
1.3 C语言的语句和关键字 一、C语言的语句 与其它高级语言一样,C语言也是利用函数体中的可执行 语句,向计算机系统发出操作命令。按照语句功能或构成的不 同,可将C语言的语句分为五类。 goto, return.
顺序表的删除.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第五章 串和数组 5.1 串的定义和操作 5.2 串的表示和实现 5.3 字符串应用 5.4 字符串匹配算法 5.5 数组
5.1 串的基本概念 5.2 串的存储结构 5.3 串的基本运算 5.4 模式匹配 5.5 串在文本编辑中的应用
数 据 结 构 刘家芬 Sept 2012.
第四章 串和数组 4.1 串的定义* 4.2 串的表示和实现* 4.3 数组 4.4 数组的压缩.
第 四 讲 线性表(二).
Select模型 本节内容 视频提供:昆山爱达人信息技术有限公司 视频录制:yang 官网地址:
字符串 (String) 字符串是 n (  0 ) 个字符的有限序列, 记作 S = “c1c2c3…cn” 其中,S 是串名字
第4章 Excel电子表格制作软件 4.4 函数(一).
<编程达人入门课程> 本节内容 为什么要使用变量? 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ:
第九节 赋值运算符和赋值表达式.
3.16 枚举算法及其程序实现 ——数组的作用.
第 六 讲 栈和队列(一).
1. 志明打算就客戶服務開發一個語音互動(IVR)系統, 顧客可透過電話鍵盤與系統進行互動。
第四章 串 £4.1 串的定义 £4.2 串的顺序存储结构 £4.3 串的链式存储结构 £4.4 串的应用—文本编辑
1.2 子集、补集、全集习题课.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
#include <iostream.h>
字符串模式匹配- KMP 主讲:朱佳 博士 华南师范大学计算机学院.
第五章 串和数组 5.1 串的定义和操作 5.2 串的表示和实现 5.3 正文匹配模式 5.4 正文编辑 5.5 数组 5.6 数组的压缩.
_03宽字符与Unicode编程 本节课讲师——void* 视频提供:昆山爱达人信息技术有限公司 官网地址:
第四章 串 String
基于列存储的RDF数据管理 朱敏
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
Chapter 2 Entity-Relationship Model
本节内容 1.二叉排序树的定义 2.二叉排序树的查找操作 3.二叉排序树的插入操作 4.二叉排序树的删除操作 5.二叉排序树的总结
第六章 复合数据类型 指针的声明与使用 数组的声明与使用 指针与数组的相互引用 字符串及相关库函数 new与delete
第5章 其他线性数据结构.
Presentation transcript:

第四章 串

串即字符串 是计算机非数值处理的主要对象之一

第一节 串的类型定义 串(string,或称字符串)是 n 个字符的有限序列。通常记作 s = “a1,a2 … an " (n≥0) 含零个字符的串称为空串(null string) 由一个或多个空格组成的串称为空格串(blank string) ,用符号"Φ"表示"空格串"。

串的抽象数据类型 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 是串常量。    操作结果:赋于串T的值为 chars。   StrCopy (&T, S)    初始条件:串 S 存在。    操作结果:由串 S 复制得串 T。

DestroyString (&S)    初始条件:串 S 存在。    操作结果:串 S 被销毁。 StrEmpty (S)    初始条件:串 S 存在。    操作结果:若 S 为空串,则返回 TRUE,否则返回 FALSE。   StrCompare (S, T)    初始条件:串 S 和 T 存在。    操作结果:若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0。

StrLength (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+1。    操作结果:用 Sub 返回串S的第 pos 个字符起长度为 len 的子串。 Index (S, T, pos)    初始条件:串S和T存在,T 是非空串,1≤pos≤StrLength(S)。    操作结果:若主串S中存在和串T值相同的子串,则返回它在主串S中第pos个字符之后第一次出现的位置;否则函数值为0。

Replace (&S, T, V)    初始条件:串 S,T 和 V 存在,T 是非空串。    操作结果:用V替换主串S中出现的所有与T相等的不重叠的子串。 StrInsert (&S, pos, T)    初始条件:串 S 和 T 存在,1≤pos≤StrLength(S)+1。    操作结果:在串 S 的第 pos 个字符之前插入串 T。

StrDelete (&S, pos, len)    初始条件:串 S 存在,1≤pos≤StrLength(S)-len+1。    操作结果:从串 S 中删除第 pos 个字符起长度为 len 的子串。 } ADT String 串赋值StrAssign、串复制StrCopy、串比较StrCompare、求串长StrLength、串联接Concat以及求子串SubString等6种操作构成串类型的最小操作子集。

例如,可利用判等、求串长和求子串等操作实现串的定位函数 Index(S,T,pos) 和串的置换操作 Replace(S,T,V)。 int Index (String S, String T, int pos) {  if (pos > 0) {   n = StrLength(S); m = StrLength(T); // 求得串长   i = pos;   while ( i <= n-m+1) {    SubString (sub, S, i, m); // 取得从第 i 个字符起长度为 m 的子串    if (StrCompare(sub,T) != 0) ++i ;    else return i ;     // 找到和 T 相等的子串   }  }  return 0;    // S 中不存在满足条件的子串 }

void replace(String& S, String T, String V) {  n=StrLength(S); m=StrLength(T); pos = 1;  StrAssign(news, NullStr);   // 初始化 news 串为空串  i=1;  while ( pos <= n-m+1 && i )  {   i=Index(S, T, pos);   // 从pos指示位置起查找串T   if (i!=0) {    SubString(sub, S, pos, i-pos); // 不置换子串    Concat(news, news, sub); // 联接S串中不被置换部分    Concat(news,news, V);     // 联接V串    pos = i+m;     // pos 移至继续查询的起始位置   }  }  SubString(sub, S, pos, n-pos+1);  // 剩余串  Concat( S, news, sub ); // 联接剩余子串并将新的串赋给S } 4-1-2replace.swf

第二节 串的表示和实现 串的定长顺序存储表示 第二节 串的表示和实现 串的定长顺序存储表示 用一组地址连续的存储单元存储串值的字符序列 #defin MAXSTRLEN 255 Typedef unsigned char SString[MAXSTRLEN]

void Concat( char S1[ ], char S2[ ], char T[ ])  {   // 以T返回由S1和S2联接而成的新串   j=0; k=0;   while ( S1[j] != '\0') T[k++] = S1[j++];   // 复制串 S1   j = 0;   while ( S2[j] != '\0') T[k++] = S2[j++];   // 紧接着复制串 S2   T[k] = '\0';                // 置结果串T的结束标志  }

bool SubString ( char Sub[ ], char S, int pos, int len )  {   // 若参数合法(即1≤pos≤StrLength(S) 且0≤len≤StrLength(S)-pos+1),则以Sub带回串S中第pos个字符起长度为len的子串,并返回TRUE,否则返回FALSE   slen=StrLength(S);       // 求串S的长度   if (pos < 1 || pos > slen || len < 0 || len > slen-pos+1)    return FALSE;   for ( j = 0; j < len; j++ ) Sub[ j ] = S[ pos + j - 1 ];                           // 向子串Sub复制字符   Sub[len] = '\0';                // 置串Sub的结束标志   return TRUE;  }

串的堆分配存储表示 串的堆分配存储的特点是,程序中出现的所有串变量的存储空间都是在程序执行过程中动态分配而得的。 堆分配存储结构的串定义如下:   typedef struct{    char *ch;    int length;   } HString;

bool StrInsert (Hstring& S, int pos, Hstring T)  {   // 若1≤pos≤StrLength(S)+1,则改变串S,在串S的第pos个字符之前插入串T,并返回TRUE,否则串S不变,并返回FALSE   if (pos < 1 || pos > S.length+1)    return FALSE;      // 插入位置不合法   char S1[S.length] ; // S1 作为辅助串空间用于暂存 S.ch   if (T.length)   { // T 非空,则为S重新分配空间并插入 T    p=S.ch; i=0;    while (i < S.length)     S1[i++] = *(p+i);      // 暂存串S    S.ch = new char[S.length + T.length ];// 为S重新分配串值存储空间 

for ( i=0, k=0; i<pos-1; i++) S for ( i=0, k=0; i<pos-1; i++)  S.ch[k++] = S1[i]; // 保留插入位置之前的子串 j = 0; while (j<T.length)  S.ch[k++] = T.ch[j++];   // 插入 T while ( i<S.length)  S.ch[k++] = S1[i++]; // 复制插入位置之后的子串 S.length+=T.length;      // 置串 S 的长度 } // if return TRUE; }

typedef struct{ char *str; int length; }STRING;

(1) 串的赋值 int StringAssign(STRING*s,char *string_constant) { if (s->str) free(s->str); //若s已经存在,将它占据的空间释放掉 for (len=0,ch=string_constant;ch;len++,ch++); //求string_constant串的长度 if (!len) { s->str=(char*)malloc(sizeof(char));s->str[0]=’\0’; s->length=0; } //空串

else { s->str=(char*)malloc((len+1)*sizeof(char)); //分配空间 if (!s->str) return ERROR; s->str[0..len]=string_constant[0..len]; //对应的字符赋值 s->length=len; //赋予字符串长度 } return OK;

(2)判断串是否为空 int StringEmpty(STRING s) { if (!s.length) return TRUE; else return FALSE; }

(3)求串的长度 int Length(STRING s) { return s.length; }

(4)串连接 int Concat(STRING *s1,STRING s2) { STRING s; StringAssign(&s,s1->str); //将s1原来的内容保留在s中 len=Length(s1)+Length(s2); //计算s1和s2的长度之和 free(s1->str); //释放s1原来占据的空间 s1->str=(char*)malloc((len+1)*sizeof(char)); //重新为s1分配空间

if (!s1) return ERROR; else { //连接两个串的内容 s1->str[0..Length(s)-1] =s.str[0..Length(s)-1)]; s1->str[Length(s)..len+1] =s2.str[0..Length(s2)]; s1->length=len; free(s->str); //释放为临时串s分配的空间 return OK; }

(5)求子串 int SubStr(STRING *s1,STRING s2,int start,int len) { len2=Length(s2); //计算s2的长度 if (start<1||start>len2||len2<=0||len>len2-start+1) { //判断start和len的合理性 s1->str=(char*)malloc(sizoef(char)); s1->str[0]=’\0’ ;s1->length=0;return ERROR;} //if s1->str=(char*)malloc((len+1)*sizeof(char)); if (!s1.str) return ERROR; s1->str[0..len-1]=s2.str[start-1..start+len -2]; s1->str[len]=’\0’; s1->length=len; return OK; }

串的块链存储表示 const CHUNKSIZE = 80; //可由用户定义的块(结点)大小   typedef struct Chunk {   // 结点结构    char ch[CUNKSIZE];    struct Chunk *next;   } Chunk;   typedef struct {      // 串的链表结构    Chunk *head, *tail;  // 串的头指针和尾指针    int curlen;         // 串的当前长度   } LString;

s t r i n g ^ S S s t r i n g # # # # ^

第三节 模式匹配 若 S ="concatenation",T ="cat",   则称主串S中存在和模式串T相同的子串,起始位置为4,即 Index(S,T,1)=4 。

串的模式匹配的简单算法 int Index_BF ( char S [ ], char T [ ], int pos )  { // 若串 S 中从第pos(1≤pos≤StrLength(S))个字符起存在和串 T 相同的子串,则称匹配成功,返回第一个这样的子串在串 S 中的位置,否则返回 0   i = pos-1; j = 0;   while ( S[i+j] != ‘\0’&& T[j] != ‘\0’)    if ( S[i+j] == T[j] ) j ++; // 继续比较后一字符    else { i ++; j = 0; }  // 重新开始新的一轮匹配   if ( T[j] == '\0') return (i+1);     // 匹配成功    else return 0;  // 串S中(第pos个字符起)不存在和串T相同的子串  } 4-3-1.swf

串的模式匹配的改进算法 按此算法进行模式串 T = "abcac" 和主串 S ="ababcabcabcacabca" 在 pos=0 的情况

int Index_BF1 ( char S [ ], char T [ ], int pos )  { // 若串 S 中从第pos(1≤pos≤StrLength(S))个字符起存在和串 T 相同的子串,则称匹配成功,返回第一个这样的子串在串 S 中的位置,否则返回 0   i = pos-1; j = 0;   while ( S[i] != '\0'&& T[j] != '\0')    if ( S[i] == T[j] )     { i++; j ++; }     // 继续比较后一字符    else { i = i-j+1; j = 0; } // 重新开始新的一轮匹配   if ( T[j] == '\0') return (i-j);    // 匹配成功   else return 0;    // 串S中(第pos个字符起)不存在和串T相同的子串  } 4-3-2.swf 改进后的4-3-3.swf

KMP 算法 匹配过程中指针 i 没有回溯。 KMP算法的核心思想是利用已经得到的部分匹配信息来进行后面的匹配过程

s1s2...si-1 si…sn p1p2…pj-1pj…pm si≠pj 此时主串的i应该与模式串的第k个字符相比较,即 p1p2…pk-1= si-k+1si-k+2...si-1 而 pj-k+1pj-k+2…pj-1= si-k+1si-k+2...si-1 所以 p1p2…pk-1= pj-k+1pj-k+2…pj-1

0 当j=1 Next[j]= Max{k|1<k<j且p1p2…pk-1= pj-k+1pj-k+2…pj-1 } 当集合不空 1 其它情况 j 1 2 3 4 5 6 7 8 模式串 a b c Next[j]

int Index_KMP(char S[], char T[], int pos)  { // 利用模式串T的next函数求T在主串S中第pos个字符之后第一次出现的位置的KMP算法。其中1≤pos≤StrLength(S)   i = pos; j = 1;   while ( i<=S[0] && j<=T[0] )    if (j = = 0 || S[i] = = T[j])     { ++i; ++j; }   // 继续比较后继字符    else j = next[j];  // 模式串向右移动   }   if ( j>T[0]) return (i- T[0] );  // 匹配成功   else return 0;  }

求s的逆串 void String_Reverse(Stringtype s,Stringtype &r) {   StrAssign(r,''); //初始化r为空串   for(i=Strlen(s);i;i--)   {     StrAssign(c,SubString(s,i,1));     StrAssign(r,Concat(r,c)); //把s的字符从后往前添加到r中   } }

从串s中删除所有与t相同的子串,并返回删除次数 int Delete_SubString(Stringtype &s,Stringtype t) {   for(n=0,i=1;i<=Strlen(s)-Strlen(t)+1;i++)     if(!StrCompare(SubString(s,i,Strlen(t)),t))     {       StrAssign(head,SubString(S,1,i-1));       StrAssign(tail,SubString(S,i+Strlen(t),Strlen(s)-i-Strlen(t)+1));       StrAssign(S,Concat(head,tail)); //把head,tail连接为新串       n++;     }   return n, }

将串S中所有子串T替换为V,并返回置换次数 int Replace(Stringtype &S,Stringtype T,Stringtype V) {   for(n=0,i=1;i<=Strlen(S)-Strlen(T)+1;i++) //注意i的取值范围     if(!StrCompare(SubString(S,i,Strlen(T)),T))     { //分别把T的前面和后面部分保存为head和tail       StrAssign(head,SubString(S,1,i-1));       StrAssign(tail,SubString(S,i+Strlen(T),Strlen(S)-i-Strlen(T)+1));       StrAssign(S,Concat(head,V));       StrAssign(S,Concat(S,tail)); //把head,V,tail连接为新串       i+=Strlen(V); //当前指针跳到插入串以后       n++;     }   return n; }