数据结构(C实现)------- 串

字符串(简称串),可以将其看作是种特殊的线性表,其特殊性在于线性表的数据元素的类型总是字符性,字符串的数据对象红豆为字符集。

    串是由0个或多个字符组成的有限序列。一般记作:s = "s1 s2 s3 .... sn",,其中,s是串名,用双引号括起来的字符序列称为串的值,si(1<=i <= n)称为串的元素,可以是字母,数字或其他字符,是构成串的基本单位,字符的个数n称为串的长度.

串中的几个术语:

    1. 空串: 由0个字符组成的串称为空串,空串不包含任何字符,其长度为0。

     2.  子串: 串中任意个连续的字符组成的子序列称为该串的子串,空串是任何串的子串。

     3.  主串: 包含子串的串相应的称为主串。

     4.  子串在主串的位置:通常称字符在序列中的序号为该字符在串的位置,子串在主串中的位置则以子串的第一个字符在主串中的位置来表示。      

     5.  两串相等:当且仅当两个串的长度相等,并且各个对应位置的字符都相等时才相等。

串的表示:

  1.  串的顺序存储表示:

    串的顺序存储结构简称为顺序串,顺序串中的字符序列被顺序地存放在一组连续的存储单元中,主要有三种实现顺序串的方式,分别如下:

   (1) 定长字符数组

   在串的顺序存储结构中,按照预定义的大小,为每个定义的串变量分配一个固定大小的存储区,描述如下:

//定长字符数组描述
#define MAXSIZE 100
typedef char SString[MAXSIZE];

    

   (2) 带串长的字符数组

//带串长的字符数组
#define MAXSIZE 100
typedef struct{
	char ch[MAXSIZE];
	int length;
}SqString;

   (3) 串的堆分配(即动态数组)存储描述 

//串的堆分配存储描述
typedef struct{
	char *ch; //若是非空串,则按串长分配存储区,否则,ch为NULL
	int length; //串长度
}HString;

  2.串的链式存储表示:

    和线性表的链式存储结构相类似,也可以采用链表方法存储串值,有以下两个方法:

    (1)串的链式结构类型描述:

//串的链式存储结构描述
typedef struct node{
	char str;
	struct node *next;
}CNode,*LinkString;

    (2)串的块链存储类型描述:

//串的块链结构类型描述
#define NODESIZE 3
typedef struct node{
	char ch[NODESIZE];
	struct node *next;
}SNode,*LinkStr;
LinkStr head;

 

  3.串的索引存储表示:

     串也可以用索引的方式来表示,有以下两种方法:

    (1)串的带长度的索引表:

//带长度的索引表
#define MAXSIZE 100
typedef struct{
	char name[MAXSIZE];
	int length;
	char *startadr;
}LSNode;

       (2) 串的带末指针的索引表:

//串的带末指针的索引表
#define MAXSIZE 100
typedef struct{
	char name[MAXSIZE];
	int length;
	char *startadr;
	char *endadr;
}ENode;

    

  以上介绍了三种存储结构来表示串,每一种存储结构又可以用几种不同的方式来描述串,那么,串的实现方法相应的也有多种,但不管有多少种,串的基本操作原理不变,变的只是处理的方式,所以也没有必要将所有方式都学会,只要会一种即可,这里就实现其中最常用动态数组来描述串,并以此种方式来实现口串的各种操作。

基本操作:

   这里所有的基本操作都是建立在上述的用动态数组,即堆结构来描述串的前提下的,直接给出代码,里面有注释。

//串的堆分配存储描述
typedef struct{
	char *ch; //若是非空串,则按串长分配存储区,否则,ch为NULL
	int length; //串长度
}HString;

//初始化一个空的顺序串
void Str_Init(HString *S){
	S->ch = NULL;
	S->length = 0;
}

//清空顺序串
void Str_Clear(HString *S){
	if(S->ch){
		free(S->ch);
		Str_Init(S);
	}
}

//判断顺序串是否为空
int Str_IsEmpty(HString *S){
	return S->length == 0;
}

//求取串的长度
int Str_GetLength(HString *S){
	return S->length;
}

//顺序串的赋值
void Str_Assign(HString *S,char *chars){
	int i = 0,j;
	char *c = chars;
	//先清空顺序串S
    Str_Clear(S);
	//求得赋值串的长度
	while(*c){
		i++;
		c++;
	}
	//如果赋值串的长度大于0,则进行赋值
	if(i > 0){
		S->ch = (char*)malloc(3*sizeof(char));
		for(j = 0;j < i;j++){
			S->ch[j] = chars[j];
		}
		S->length = i;
	}
}
//顺序串的复制,将T复制到S
void Str_Copy(HString *S,HString *T){
	int i;
	//先清空顺序串S
    Str_Clear(S);
    S->length = T->length;

    if(S->length){
		S->ch = (char *)malloc(sizeof(char)*S->length);
		for(i = 0;i < S->length;i++)
			S->ch[i] = T->ch[i];
	}
}

//顺序串的连接,将T连接到S后
void Str_Concat(HString *S,HString *T){
	//临时存放S串
	HString temp;
	int i,j;
	Str_Init(&temp);
	Str_Assign(&temp,S->ch);

	//清空S
	Str_Clear(S);
	//重新为S分配空间
	S->length = temp.length + T->length;
	S->ch = (char*)malloc(sizeof(char) * S->length);
	//分别将temp和T依次赋值给S
	for(i = 0;i < temp.length;i++)
		S->ch[i] = temp.ch[i];
	for(j = 0; j < T->length;j++)
		S->ch[i++] = T->ch[j];

	//将temp释放掉
	free(temp.ch);
}

//顺序串的比较,如果S>T,返回大于0的值,小于,则返回小于0的值
int Str_Compare(HString *S,HString *T){
	int i;
	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;
}

//求子串并用Sub返回
void Str_GetSub(HString *S,int pos,int len,HString *Sub){
	int i;
	//判断位置和长度的合法性
	if(pos < 1 || pos > S->length || len < 0 || len > S->length - pos + 1){
		printf("子串的位置或长度不合法!\n");
		exit(-1);
	}
	else{
		Str_Clear(Sub);
		if(len){
			Sub->ch = (char *)malloc(len * sizeof(char));
			for(i = 0;i < len;i++)
				Sub->ch[i] = S->ch[pos + i -1];
			Sub->length = len;
		}
	}
}

//在顺序串中找出给定子串给定位置后出现的第一个的位置
int Str_GetSubIndex(HString *S,HString *Sub,int pos){
	int i,j;
	//先判断位置的合法性
	if(pos < 1 || pos > S->length){
		printf("位置不合法!\n");
		exit(-1);
	}
	if(Str_IsEmpty(S)){
		printf("顺序串为空!\n");
		return -1;
	}
	if(Str_IsEmpty(Sub)){
		printf("给定子串为空,空串为任何串的子串!\n");
		return 0;
	}

	for(i = pos - 1; i < S->length - Sub->length + 1;i++){
		for(j = 0; j < Sub->length;j++)
			if(S->ch[i+j] != Sub->ch[j])
				break;
		// 如果找到子串,则j= sub->length
		if(j == Sub->length)
			return i + 1;
	}
	//如果找不对,则返回-1;
	return -1;
}

//顺序串中插入子串
void Str_Insert(HString *S,int pos,HString *T){
	int i;
	HString temp;
	if(pos < 1 || pos > S->length){
		printf("位置不合法!\n");
		exit(-1);
	}
	if(Str_IsEmpty(T)){
		printf("子串为空!\n");
		exit(0);
	}
	Str_Init(&temp);
	temp.length = S->length + T->length;
	printf("%d\n",temp.length);
	temp.ch = (char *)malloc(sizeof(char)*temp.length);
	for(i  = 0 ;i < pos ;i++)
		temp.ch[i] = S->ch[i];
	for(; i < pos + T->length;i++)
		temp.ch[i] = T->ch[i - pos];
	for(;i < temp.length;i++)
		temp.ch[i] = S->ch[i - T->length];
	//将串S 清空,并将串temp赋值给S
	Str_Clear(S);
	S->ch = temp.ch;
	S->length = temp.length;

}

//在顺序串删除子串
void Str_DeleteSub(HString *S,int pos,int len){
	int i;
	HString temp;
	//判断位置和长度的合法性
	if(pos < 1 || pos > S->length || len < 0 || len > S->length - pos + 1){
		printf("子串的位置或长度不合法!\n");
		exit(-1);
	}
	if(Str_IsEmpty(S)){
		printf("顺序串为空!\n");
		exit(0);
	}
	Str_Init(&temp);
	temp.length = S->length - len;
	temp.ch = (char *)malloc(sizeof(char)*temp.length);
	for(i = 0 ;i < pos - 1; i++)
		temp.ch[i] = S->ch[i];
	for(;i < temp.length;i++)
		temp.ch[i] = S->ch[i+len];
	//将串S清空,并将串temp赋值给S
	Str_Clear(S);
	S->ch = temp.ch;
	S->length = temp.length;

}
//打印顺序串
void Str_Print(HString *S){
	int i = 0;
	if(Str_IsEmpty(S)){
		printf("顺序串为空!\n");
		exit(0);
	}
	else
		printf("%s\n",S->ch);
}

时间: 2024-08-06 00:03:41

数据结构(C实现)------- 串的相关文章

SDUT 2772 数据结构实验之串一:KMP简单应用

数据结构实验之串一:KMP简单应用 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Description 给定两个字符串string1和string2,判断string2是否为string1的子串. Input 输入包含多组数据,每组测试数据包含两行,第一行代表string1(长度小于1000000),第二行代表string2(长度小于1000000),string1和string2中保证不出现空格. Outp

SDUT 3311 数据结构实验之串三:KMP应用

数据结构实验之串三:KMP应用 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Description 有n个小朋友,每个小朋友手里有一些糖块,现在这些小朋友排成一排,编号是由1到n.现在给出m个数,能不能唯一的确定一对值l和r(l <= r),使得这m个数刚好是第l个小朋友到第r个小朋友手里的糖块数? Input 首先输入一个整数n,代表有n个小朋友.下一行输入n个数,分别代表每个小朋友手里糖的数量. 之后再输

数据结构 【实验 串的基本操作】

一.实现主要功能为: 1.输入模式串.目标串 2.根据目标串生成next[]和nextval[]数组 3.根据next[]或者nextval[]进行匹配. 二.程序截图: 三.代码: 1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <stdlib.h> 5 using namespace std; 6 7 #define MAXSIZE 1000 //最大

SDUT-2772_数据结构实验之串一:KMP简单应用

数据结构实验之串一:KMP简单应用 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 给定两个字符串string1和string2,判断string2是否为string1的子串. Input 输入包含多组数据,每组测试数据包含两行,第一行代表string1(长度小于1000000),第二行代表string2(长度小于1000000),string1和string2中保证不出现空格. Output 对于每组输入数据,若s

数据结构实验之串三:KMP应用

C - 数据结构实验之串三:KMP应用 Description 有n个小朋友,每个小朋友手里有一些糖块,现在这些小朋友排成一排,编号是由1到n.现在给出m个数,能不能唯一的确定一对值l和r(l <= r),使得这m个数刚好是第l个小朋友到第r个小朋友手里的糖块数? Input 首先输入一个整数n,代表有n个小朋友.下一行输入n个数,分别代表每个小朋友手里糖的数量. 之后再输入一个整数m,代表下面有m个数.下一行输入这m个数. Output 如果能唯一的确定一对l,r的值,那么输出这两个值,否则输

数据结构实验之串三:KMP应用(KMP模板)

数据结构实验之串三:KMP应用(KMP模板) AC_Code: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <map> 6 #include <stack> 7 using namespace std; 8 typedef long long ll; 9 int Nex[1000000]; 10

数据结构实践——顺序串算法

本文针对数据结构基础系列网络课程(4):串实践项目. [项目 - 顺序串算法] 采用顺序存储方式存储串,实现下列算法并测试: (1)试编写算法实现将字符串S中所有值为c1的字符换成值为c2的字符: void Trans(SqString *&s, char c1, char c2); (2)试编写算法,实现将已知字符串所有字符倒过来重新排列.如ABCDEF改为FEDCBA. void Invert(SqString &s) (3)从串s中删除其值等于c的所有字符.如从message中删除'

数据结构实践项目——串

本文针对数据结构基础系列网络课程(4):串. 1. 串的基本概念及导学 2. 串的顺序存储及其基本操作实现 3. 串的顺序存储应用 4. 串的链式存储及其基本操作实现 5. 串的模式匹配(Brute-Force算法) 6. 串的模式匹配(KMP算法) [项目1 - 建立顺序串的算法库] 定义顺序串的存储结构,实现其基本运算,并完成测试. 要求: 1.头文件sqString.h中定义数据结构并声明用于完成基本运算的函数.对应基本运算的函数包括: void StrAssign(SqString &s

串的数据结构表——顺序串与链式串

串的结构类似与线性表,只不过串的数据元素是一个字符,即是由零个或多个字符组成的有限序列. 一.串的顺序存储 串的顺序存储结构也就是顺序存储,即串中的字符被依次的存在一组连续的存储单元中,可以类比线性表的顺序存储,可以写出其数据结构如下: typedef struct st { char *ch; //串存放的起始地址,串中第i个字符存储在ch[i-1]中 int length; //串的长度 int strsize; //分配的存储空间的大小,如果不足,在通过realloc()分配增加空间 }s

浅谈数据结构之KMP(串中的模式匹配算法)

KMP算法是一种模式匹配算法的改进版,其通过减少匹配的次数以及使主串不回朔来减少字符串匹配的次数,从而较少算法的相应代价,但是,事件万物是普遍归中的,KMP算法的有效性也是有一定的局限的,我将在本文的最后也讨论这个算法的局限性. 一般的匹配算法: KMP基本概念引入: 但是,其实我们会发现,上面的中间两个匹配步骤是没有必要的,因为他们的第一个匹配字母就不相同,完全没有可比性,而当我们在第四次匹配的时候,其实我们从模式串中就可得知,只有当模式串滑到这个地方的时候,它的匹配才是最有价值的,因为从模式