数据结构与算法精解:顺序串

本文介绍了顺序串的基本概念、特点和应用场景。顺序串是一种用连续内存存储字符串的数据结构,具有随机访问、动态扩展等优点。文章详细说明了顺序串的常见操作,包括字符访问、修改、插入、删除和连接等,并列举了其在文本编辑和字符串处理中的应用。此外,还提供了顺序串的C语言实现代码,包括结点设计、接口函数定义和具体实现,涵盖了初始化、赋值、复制、比较、连接、查找子串等核心功能。最后给出了简单的测试案例,展示了顺序串的基本使用方法。

作者
WildPointer
发布
2024.06.07
专栏
数据结构与算法精解
阅读
约 9 分钟 / 649 次原文浏览

        1.顺序串是什么?


顺序串是什么?

顺序串,用于存储和操作字符串。在顺序串中,字符串被存储在一个连续的内存块中,通常是数组或动态数组(如C++中的std::vector或Java中的ArrayList)。顺序串的主要优点是它提供了一种简单且高效的方式来访问和修改字符串中的字符。以下是顺序串的特点:

        1.连续内存:字符串的所有字符都存储在连续的内存位置,这有助于提高访问速度

       2.动态扩展:顺序串通常使用动态数组实现,这意味着它们可以根据需要自动扩展其大小

       3.随机访问:由于字符串存储在数组中,任何字符都可以在常数时间内被访问,即O(1)时间复杂度


顺序串常见操作和应用

要实现顺序串需要实现以下操作:

1.访问字符:可以直接通过索引访问字符串中的任何字符

2.修改字符:可以直接通过索引修改字符串中的任何字符

3.插入字符:可以在字符串的任何位置插入字符,但可能需要移动插入点后的所有字符

4.删除字符:可以从字符串中删除任何字符,但可能需要移动删除点后的所有字符。

5.连接字符串:可以将两个或多个字符串连接在一起,通常需要扩展数组并复制字符

顺序串的应用:

1.文本编辑:顺序串常用于文本编辑器中,用于存储和操作文本数据

2.字符串处理:在需要频繁访问和修改字符串的场景下,顺序串提供了一种高效的数据结构


包含头文件

cpp
#include<stdio.h>#include<stdlib.h>#include<string.h>

结点设计

cpp
#define Initsize 10typedef char Elemtype;typedef struct SqString {	Elemtype data[Initsize];			//定义数组data为数据域,存储数据	int length;							//定义变量length存储串长度}SqString;

接口函数定义

cpp
bool InitString(SqString& A);					//用于初始化顺序串bool Assign(SqString& A, char str[]);			//用于将字符数组中的数据赋值给顺序串bool StringCopy(SqString& A, SqString B);		//用于将B顺序串数据复制到A顺序串bool Strlen(SqString A, SqString B);			//用于判断两个顺序串是否相等SqString Concat(SqString A, SqString B);		//用于将两个字符串连接bool Index(SqString A, SqString B);				//用于查找子串的位置bool InsertStr(SqString& A, SqString B, int i);	//用于在顺序串中插入子串bool InsertString(SqString& A);					//用于在顺序串中输入数据bool IdlString(SqString& A, int i, int j);		//用于选定删除子串void DispStr(SqString A);						//用于输出顺序串//用于在顺序串中查找等长度的子串,i为开始的次序,j为子串长度SqString SubStr(SqString A, int i, int j);

接口函数实现

cpp
void DispStr(SqString A) {				//用于输出顺序串	if (A.length == 0) {				//为减少存储空间,判断是否为空串		printf("传入的顺序串为空串");	}	else {		int i;		for (i = 0; i < A.length; i++) {//遍历输出串			printf("%c", A.data[i]);		}	}}bool IdlString(SqString& A, int i, int j) {	//用于选定删除子串	if (i<1 || i>A.length || j<1 || j + i>A.length + 1) {	//判断传入的次序是否有误		printf("传入的次序或长度有误");		return false;	}	else {		int k;		for (k = i-1+j; k < A.length; k++) {			//删除特定次序的子串			A.data[i - 1] = A.data[k];			i++;		}		A.length -= j;			//更新顺序串的大小		return true;	}}bool InsertString(SqString& A) { //用于在顺序串中输入数据	int i;	char x[Initsize];			 //定义一个字符数组存储字符	printf("创建的顺序串大小为%d,请问需要输入多少个数据:",Initsize);	scanf_s("%d", &A.length);	if (A.length == 0) {		return false;	}	printf("请输入数据:");	getchar();					//清除计算机缓存区	gets_s(x, A.length+1);		//使用get_s函数从键盘键入数据,大小为A.length+1	for (i = 0; i <A.length; i++) {			//更新顺序串数据		A.data[i] = x[i];	}	return true;}bool InsertStr(SqString& A, SqString B, int i) { //用于在顺序串中插入子串	int j,k=A.length-1;	if (i<1 || i>A.length + 1) {			//判断传入的次序是否合理		printf("插入的位序不合理\n");		return false;	}	else {		if (i + B.length +A.length> Initsize) {	  //判断顺序串是否有空间存储插入的子串			printf("传入的顺序串所剩的空间不足\n");			return false;		}		else {			for (j = A.length + B.length; j >= A.length; j--)	            //遍历顺序串,将传入的次序后的数据后移			{				A.data[j] = A.data[k];				k--;			}			k = 0;			for (j = i - 1; j < A.length; j++) {	//遍历顺序串,将子串插入对应的次序中				A.data[j] = B.data[k];				k++;			}		}	}	A.length += B.length;			//更新顺序串的长度length	printf("在顺序表中插入子串成功\n");	return true;}bool Index(SqString A, SqString B) {	//用于查找子串的位置	int i=0, j=0, len=0;	while (i < A.length && j < B.length) {		//遍历传入顺序表和子串		if (A.data[i] == B.data[j]) {			//判断传入的子串是否在传入的顺序表中			len = i;		//记录子串的位置			i++;			j++;		}		else {			len = 0;					j = 0;			i++;		}	}	if (j >= B.length) {	//判断是否在顺序表中找到对应的子串		printf("已找到对应的子串,其子串位于主串的第%d个到第%d个位置\n",len,len+B.length-1);		return true;	}	else {		printf("找不到对应的子串\n");		return false;	}}SqString SubStr(SqString A, int i, int j) {	//    用于在顺序串中查找等长度的子串,i为开始的次序,j为子串	SqString C;			//定义顺序串C,储存查找到的子串	if (i > A.length || i+j > A.length+1 || i<1 ||j<1) {//判断传入的次序和长度是否合理		C.length = 0;	//更新顺序串C的长度		printf("传入的长度参数错误,找不到子串\n");		return C;	}	else {		int K;		for (K = i - 1; K < i + j - 1; K++) {			C.data[K - i + 1] = A.data[K];			//将查找到的子串赋值给顺序串C		}		C.length = j;	//更新顺序串C的长度	}	return C;}SqString Concat(SqString A, SqString B) { //定义函数Concat用于将两个字符串连接	SqString C;			//定义顺序串C存储连接结果的数据	int i,j;	for (i = 0; i < A.length; i++) {	  //将顺序串A的数据赋值给新的顺序串C		C.data[i] = A.data[i];	}	for (j=0; j < B.length; j++) {		  //将顺序串B的数据赋值给新的顺序串C		C.data[A.length+j] = B.data[j];	}	C.length = i + j;			//更新顺序串C的长度length	printf("传入的两个顺序串连接成功\n");	return C;}bool Strlen(SqString A, SqString B) {	 //用于判断两个顺序串是否相等	if (A.length != B.length) {			 //判断传入的顺序串长度length是否相等		printf("顺序串长度不相等\n");		return false;	}	else {		int i;		for (i = 0; i < A.length; i++) { //遍历两个顺序串判断所含数据是否相等			if (A.data[i] != B.data[i]) {				printf("顺序串中所含数据不相等\n");				return false;			}		}		printf("传入的顺序串数据相等\n");		return true;	}}bool StringCopy(SqString& A, SqString B) {	//用于将B顺序串数据复制到A顺序串	if (A.length < B.length) {			//判断要复制的顺序串长度是否大于新的顺序串		printf("要复制的顺序串长度大于新的顺序串\n");		return false;	}	else {		int i=0;		while (i < B.length) {			//遍历要复制的顺序串			A.data[i] = B.data[i];			i++;		}		printf("顺序串复制成功\n");		A.length = B.length;			//更新新的顺序串的长度length		return true;	}}bool Assign(SqString& A, char str[]) {		//用于将字符数组中的数据赋值给顺序串	if (strlen(str) > Initsize) {			//判断传入的字符数组数据是否过大		printf("字符数组过大,顺序串存储不足\n");		return false;	}	else {		int i = 0;		while (str[i] != '\0') {			//遍历字符数组并将其数据赋值到顺序串			A.data[i] = str[i];			i++;		}		A.length = i;						//更新顺序串长度length		printf("赋值成功\n");		return true;	}}bool InitString(SqString& A) {	//用于初始化顺序串	A.length = 0;				//将串中length赋初值为0	printf("顺序串初始化成功\n");	return true;}

顺序串测试案列

cpp
void main() {	SqString X,Y,Z;	InitString(X);	InitString(Y);	InsertString(X);	InsertString(Y);	DispStr(X);	printf("\n");	Index(X, Y);}
6次原文点赞;这里的喜欢仅保存在本机
WildPointer

专注系统编程、工程实践与底层技术,记录 C++、Qt、OpenCV 与 VTK 的学习和实践。