串和广义表知识点总结


(1) 串是由零个或多个字符组成的有限序列,又叫字符串。串的值可以是数字、字母或其他字符。

一般记为 s=“a1a2...an”(n>=0)

其中s 是串的名,用双引号括起来的字符序列是串的值;
(2) 串中字符的数目称为串的长度,零个字符的串称为空串,长度为0
(3) 串中任意个连续的字符组成的子序列称为该串的子串,包含该字串的串称为主串
(4) 字串在主串中的位置以子串的第一个字符在主串中的位置来表示
(5) 当且仅当两个串的值相等,那么这两个串相等
(6) 特殊的,由一个或多个空格组成的串称为空格串

串的逻辑结构和线性表很相似的,不同的是串针对是是字符集,所以在操作上与线性表还是有很大区别的。线性表更关注的是单个元素的操作,串则是更关注查找子串的位置,替换等操作。例如查找字串,求取一个字串,插入删除字串等

串的存储结构
串的顺序存储结构
定长顺序存储结构可以简单地理解为采用 "固定长度的顺序存储结构" 来存储字符串
 

#define MAXSIZE 100
typedef struct {
	char ch[MAXSIZE+1];
	int length;
}SString;

在串的定长顺序存储结构中,按照预定义的大小,为每个定义的串变量分配一个固定长度的存储区。

串的堆式顺序存储结构

在C语言中 ,提供一个称之为“堆”的共享空间,可以在程序运行过程中,系统利用函数malloc( )和free( )动态地申请或释放一块连续空间。

typedef struct{
	char &ch;
	int length;
}HString;

在这种存储结构下,由于串仍然是以数组存储的字符序列表示,因此此类串的操作是先为新生成的串分配一个存储空间,然后进行“字符序列的复制”。

串的链式存储结构

#define CHUNKSIZE 80
typedef struct Chunk{
	char ch[CHUNKSIZE];
	struct Chunk *next;
}Chunk;
typedef struct{
	Chunk *head,*tail;
	int length;
}LString;

顺序串的插入和删除操作不方便,需要移动大量的字符,因此,可以采用单链表方式存储。

链式存储中,结点大小的选择直接影响着串处理的效率。
链式结构不如顺序存储结构灵活,它占用存储量大且较复杂。

串的模式匹配算法
字串的定位运算通常称为串的串匹配或者模式匹配。通常使用最多的算法有BF算法和MKP算法。

BF算法
基本思想:

从目标串s 的第一个字符起和模式串t的第一个字符进行比较,若相等,则继续逐个比较后续字符,否则从串s 的第二个字符起再重新和串t进行比较。

依此类推,直至串t 中的每个字符依次和串s的一个连续的字符序列相等,则称模式匹配成功,此时串t的第一个字符在串s 中的位置就是t 在s中的位置,否则模式匹配不成功
 

BF算法最大的问题就在于有一个回溯的过程,会增加时间复杂度

该算法最坏情况下要进行M*(N-M+1)次比较。时间复杂度为O(M*N)。   
最好情况下时间复杂度为O(m+n)

来个示例:

#BF算法
#include<cstring>
#include<iostream>
using namespace std;
 
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
#define MAXSTRLEN 255   		//用户可在255以内定义最长串长
typedef char SString[MAXSTRLEN+1];		//0号单元存放串的长度
 
Status StrAssign(SString T, char *chars) { //生成一个其值等于chars的串T
	int i;
	if (strlen(chars) > MAXSTRLEN)
		return ERROR;
	else {
		T[0] = strlen(chars);
		for (i = 1; i <= T[0]; i++)
			T[i] = *(chars + i - 1);
		return OK;
	}
}
 
int Index(SString S, SString T, int pos)
{
	//返回模式T在主串S中第pos个字符之后第s一次出现的位置。若不存在,则返回值为0
	//其中,T非空,1≤pos≤StrLength(S)
	int i = pos;
	int j = 1;
	while(i <= S[0]&&j <= T[0])
	{
		if(S[i]==T[j])
		{
			++i;
			++j;
		} //继续比较后继字符
		else
		{
			i=i-j+2;
			j=1;
		} //指针后退重新开始匹配
	}
	if (j > T[0])
		return i - T[0];
	else
		return 0;
	return 0;
}//Index
 
int main()
{
	SString S;
	StrAssign(S,"bbaaabbaba") ;
	SString T;
	StrAssign(T,"abb") ;
	cout<<"主串和子串在第"<<Index(S,T,1)<<"个字符处首次匹配\n";
	return 0;
}

广义表
广义表也称为列表。属于是线性表的推广。

其中:ls 是广义表的名称,n 是它的长度每个ai(1≤i≤n)是ls 的成员:它可以是单个元素(“广义表ls 的单元素”),也可以是一个广义表(“广义表ls 的子表”)。
当广义表ls 非空时,称第一个元素a1 为ls 的表头(head),称其余元素组成的表(a2,ai,…,an)为ls 的表尾(tail)。

广义表的性质:
 ⑴广义表是一种多层次的数据结构。广义表的元素可以是单元素,也可以是子表,而子表的元素还可以是子表

 ⑵广义表可以是递归的表,即广义表也可以是其自身的子表

 (3)广义表可以为其他广义表所共享。例如,表A、表B、表C 是表D 的共享子表。在D中可以不必列出子表的值,而用子表的名称来引用

广义表结点:
广义表中结点有两种形式:元素结点和表结点

 1. 表结点中包括一个指向表头的指针hp和指向表尾的指针tp; 
2. 元素结点中应该包括所表示单元素的元素值。 
3. 为了区分这两类结点,在结点中还要设置一个标志域tag:如果标志为1,则表示该结点为表结点;如果标志为0,则表示该结点为元素结点。

头尾链表的存储结构

typedef enum(ATOM,LIST) ElemTag;
typedef struct GLNode
{
	ElemTag tag;
	union
	{
		AtomType atom;
		struct(struct GLNode *hp,*tp;)ptr;
	};
 } *GList;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值