4.3串的链式存储与串的应用举例

本文探讨了串的链式存储方式,包括块链串的定义与实现,以及串在文本编辑器中的应用。通过堆存储结构和页、行、字符指针,实现了文本的高效编辑与管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

4.3串的链式存储与串的应用举例

1、块链串

由于串也是一种线性表,因而也可以采用链式存储。因为串是一个特殊的线性表(表中每个元素就是一个字符)。在具体实现时,一个链表存放一个串值,每个结点既可以存放一个字符, 也可以存放多个字符。每个结点称为块,整个链表称为块链结构,为便于操作,再增加一个尾指针。

块链结构可定义如下:

#define  BLOCK_SIZE  4 
/*每结点存放字符个数 4*/ 
typedef struct Block
{ 
	char  ch[BLOCK_SIZE]; 
	struct Block   *next; 
}Block; 
 
typedef struct 
{ 
	Block   *head; 
	Block   *tail;
	int     len; 
}BLString; 

结点大小:链表中的结点分成两个域data和link,其中结点大小是指data域中存放字符的个数,链域大小是指 link 域中占用字符的个数。

如果一个结点大小为 4 ,链域大小为 2 ,根据存 储密度=串值占用的存储位/实际为串分配存储位,故该字符串的存储密度为 2 /3 。

显然,串的存储密度越小,运算处理就越方便,但存储占用的量较大。应根据具体情况来确定使用串的何种存储结构。

结点大小等于 1 :当 BLOCK_SIZE 等于 1 时,每个结点存放 1 个字符,结构同线性链表,存储结构可定义如下,插入、删除的处理方法和线性链表一样,参见本章典型题解部分串的链式 模式匹配,算法处理简单,但存储密度较低。

结点大于 1 :当 BLOCK_SIZE 大于 1 时,每个结点存放多个字符,当最后一个结点未存满 时,不足处可用特定字符(如#)补齐。虽然存储密度相对结点大小等于 1 的存储方法来说,存储 密度较高,但此时插入、删除的处理方法比较复杂,需要考虑结点的分拆和合并。

2、串的应用举例:简单的行编辑器

可将文本看成为一个大的字符串,文本编辑就相当对字符串的处理。

文本编辑程序用于源程序的输入和修改,公文书信、报刊和书籍的编辑排版等。常用的文本编辑程序有 Edit,WPS,Word 等。

文本编辑的实质是修改字符数据的形式和格式,虽然各个文本编辑程序的 功能不同,但基本操作是一样的,都包括串的查找、插入和删除等。

为了编辑方便,可以用分页符和换行符将文本分为若干页,每页有若干行。

可以把文本当作一个字符串,称为文本串,页是文本串的子串,行是页的子串。

这里采用堆存储结构来存储文本,同时设立页指针、行指针和字符指针,分别指向当前操作的页、行和字符,同时建立页表和行表存储每一页、每一行的起始位置和长度。

假设有如下 Pascal 源程序:

FUNC max(x,y:integer): integer; 
VAR z; integer; 
BEGIN   
	IF x>y THEN z:=x;    
	ELSE z:=y;    
	RETURN(z); 
END;

该程序输入内存后放到一个堆中,如图 4.3 所示。
其中↙为换行符。表 4-1 和表 4-2 分别为下图所示文本串的页表和行表。
在这里插入图片描述
由表 4 -1 、表 4 -2 可以看出,当在某行内插入字符时,就要修改行表中该行的长度,若该 行的长度超出了分配给它的存储空间,则要重新给它分配存储空间,同时修改它的起始位置和长度。如果要插入或删除一行,就要进行行表的插入和删除,当行的插入和删除涉及页的变化是时要对页表进行修改。

3、总结与提高

1、 主要知识点

( 1 )字符串是一种特定的线性表,其特殊性就在于组成线性表的每个元素就是一个单字 符。

( 2 )字符串常用的存储方式有三种:定长顺序串、堆串和块链串。

( 3 )定长顺序串以一维数组作为静态存储结构,运算实现类同顺序表。堆串以动态分配的 方式产生一组地址连续的存储单元顺序存放串中的字符,运算实现类同顺序串。块链串以链表作为存储结构,运算实现类同链表。

( 4 )串的模式匹配算法是本章的重点,简单的模式匹配算法处理思路简单,由于进行了带回溯的处理,时间复杂度较高。改进的 KMP 模式匹配算法计算滑动位置,因而失配后无回溯, 匹配速度较高。

2、 典型题例

要求编写一个用带头结点的单链表实现串的模式匹配算法,每个结点存放一个字符(结点大小为 1 )。 借助于前面的结点大小为 1 定义链串类型
LKString。

问题分析
该算法类同顺序串的简单模式匹配,实现匹配过程需考虑链表的特征(从头 比较的技术,指针保留的技术)。

算法思想
从主串 s 的第一个字符和模式串 t 的第一个字符开始比较,如果相等,就继 续比较后续字符,如果不等,则从主串 s 的下一个字符开始重新和模式串 t 比较。一直到模式串 t 中的每一个字符依次和主串 s 中的对应字符相等,则匹配成功,返回主串的当前起始位置 指针。如果主串中没有和模式串相同的子串,则称匹配不成功,返回空指针 NULL。

算法描述

Link *StrIndex(LKString *s, LKString *t) 
/* 求模式串 t 在主串 s 中第一次出现的位置指针 */ 
{  
	Link *sp, *tp, *start; 
	if (t->len == 0) return s->head->next;  /* 空串是任意串的子串 */  
		start = s->head->next;                  /* 记录主串的起始比较位置 */  
		sp = start;                             /* 主串从 start 开始 */  
		tp = t->head->next;                     /* 模式串从第一个结点开始 */ 
	while(sp != NULL && tp != NULL)   
	{   
		if (sp->ch == tp->ch)           /* 若当前对应字符相同,则继续比较 */ 
		{    
			sp = sp->next;    
			tp = tp->next;      
		}   
		else   /* 发现失配字符,则返回到主串当前起始位置的下一个结点继续比较*/     
		{    
			start = start->next;       /* 更新主串的起始位置 */    
			sp = start;    
			tp = t->head->next;        /* 模式串从第一个结点重新开始 */     
		}   
	}  
	if ( tp == NULL)  
		return  start;   /* 匹配成功,返回主串当前起始位置指针 */  
	else  
		return  NULL;                /* 匹配不成功,返回空指针 */ }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值