数据结构---串的基本操作

串的基本概念

计算机上的非数值处理的对象大部分是字符串数据, 字符串(由零个或多个字符组成的有限序列)一般简称为串,记为s= "a1 a2 … an" (n>=0)

串是一种特殊的线性表, 其特殊性体现在数据元素是一个字符, 也就是说, 串是一种内容受限的线性表。

串的值:双引号括起来的字符序列

串的长度:串中字符的数目n

子串:串中任意个连续的字符组成的子序列

主串:包含子串的串

字串的位置:子串的第一个字符在主串中的位置

空串:零个字符的串,其长度为零

空格串:一个或多个空格组成的串,其长度为串中空格字符的个数

串的类型定义、存储结构及其运算

串的抽象数据类型的定义

ADT String

{

数据对象:D= { ai I ai E CharacterSet, i=l, 2, …, n, n>=0}

数据关系:R 1= {< ai-1, ai> lai-1, ai属于D,i=2, …,n}

基本操作:

}ADT String

串的存储结构

1.串的顺序存储---用一组地址连续的存储单元存储串值的字符序列
#define MAXLEN 255 //串的最大长度
typedef struct { 
char ch[MAXLEN+l);//存储串的一维数组,长度为256,数组分量下标1-255
int length;       //串的当前长度
} SString;

注意!本章算法用到的顺序存储结构都是从下标为1的数组分量开始存储的,这种存储方式空间大小编译时就提前确定了

typedef struct{ 
char *ch;//按串长分配空间,分配成功返回指向起始地址的指针,否则ch为NULL
int length; 
}HString;

可以根据实际需要在程序执行的过程中动态地分配和释放字符数组空间。

2.串的链式存储
#define CHUNKSIZE 80//定义块的大小
typedef struct Chunk{ 
char ch [ CHUNKSIZE」;//每个结点可以存放一个字符也可以存放多个字符
struct Chunk *next; //指针域
) Chunk; 
typedef struct{ 
Chunk *head,*tail; //头尾指针
int length; 
) LString

串的基本操作

1.生成串

int StrAssign(SString& S, char chars[])//生成串S
{
	int i = 0;
	while (chars[i] != ' ')
	{
		S.ch[i] = chars[i];//将字符串常量的值赋值给S
		++i;
	}
	S.length = i;//将i赋值给S的长度
	return 0;
}

2.复制串

void StrCopy(SString&S1, SString&S2)//将串S2复制到串S1
{
	int i = 0;
	for (i = 0; i < S2.length; i++)
	{
		S1.ch[i] = S2.ch[i];//将S2中字符复制给S1
	}
	S1.length = S2.length;//复制长度
}

3.判断栈是否为空

int StrEmpty(SString& S)//判断串S是否为空
{
	if (S.length == 0)return 1;//直接看串的长度
	else
		return 0;
}

4.比较两个串

int StrCompare(SString& S1, SString& S2)//比较串S1和串S2
{
	int i = 0;
	while ((i < S1.length) && (i < S2.length))//串S1,S2均不为空
	{
		if ((int)(S1.ch[i]) > (int)(S2.ch[i]))//将字符强制转换为整型比较大小
			return 1;//若S1 > S2,则返回1
		if ((int)(S1.ch[i]) < (int)(S2.ch[i]))
			return -1;//若S1 < S2,则返回-1
		if (S1.ch[i] == S2.ch[i])
		{
			++i;
			continue;//如果两字符相等,则退出该次循环,进行下一次循环
		}
		++i;
	}
	if ((i == S1.length) && (i != S2.length))
		return -1;
	else if ((i != S1.length) && (i == S2.length))
		return 1;
	else
		return 0;//若S1 = S2,则返回0
}

5.求串的长度

int LengthString(SString& S)//求串S的长度
{
	return S.length;
}

6.遍历并打印串

int ShowString(SString* S)//打印串S
{
	if (S->length == 0)
	{
		printf("当前串为空! ");
		return 0;
	}
	int i;
	for (i = 0; i < S->length; i++)
	{
		printf("%c", S->ch[i]);
	}
	printf(" ");
	return 0;
}

7.联结串

int ConcatString(SString* S, SString& S1, SString& S2)//用S返回由S1和S2连接而成的新串
{
	int i, j;
	for (i = 0; i < S1.length; i++)//首先将S1复制到串S
	{
		S->ch[i] = S1.ch[i];
	}
	S->length = S1.length;
	for (j = 0; j < S2.length; j++)//再次循环,将S2复制到串S
	{
		S->ch[S->length] = S2.ch[j];
		++S->length;
	}
	return 0;
}

8.用Sub返回串S的第pos个字符起长度为len的子串

int SubString(SString* Sub, SString* S, int pos, int len)//用Sub返回串S的第pos个字符起长度为len的子串
{
	if ((1 > pos) || (pos > S->length) || (len < 0) || (len > S->length - pos + 1))
	{
		printf("输入有误! ");
		return 0;
	}
	int j = 0;
	while (j < len)
	{
		Sub->ch[j] = S->ch[pos - 1];//将第pos个字符起长度为len的字串赋给Sub
		++j;
		++pos;
	}
	Sub->length = len;
	return 0;
}

在串S1的第pos个字符之前插入串S2

int StrInsert(SString* S1, int pos, SString* S2)//在串S1的第pos个字符之前插入串S2
{
	if (pos < 1 || (pos > S1->length))
	{
		printf("输入有误! ");
		return 0;
	}
	int i;
	for (i = (S1->length - 1); i >= pos - 1; i--)//循环,将S1从第pos个字符往后的
	{//所有字符都后移S2->length个位置
		S1->ch[i + S2->length] = S1->ch[i];
	}
	int j = 0;
	int k = pos - 1;
	for (j = 0; j < S2->length; j++)//循环,将串S2依次插入到S1移动后空出来的位置
	{
		S1->ch[k] = S2->ch[j];
		k++;
	}
	S1->length += S2->length;//更新S1的长度
	return 0;
}

10.从串S中删除第pos个字符起长度为len的子串

int StrDelete(SString* S, int pos, int len)//从串S中删除第pos个字符起长度为len的子串
{
	if (pos < 1 || pos >(S->length - len + 1))
	{
		printf("输入有误! ");
		return 0;
	}
	int i;
	for (i = pos + len; i <= S->length; i++)
	{
		S->ch[i - len - 1] = S->ch[i - 1];
	}
	S->length -= len;//更新S的长度,超过S->length后的字符会被省略
	return 0;
}

11.清空串

void StrClear(SString* S)//清空串
{
	if (S->ch)
	{
		delete S->ch;
	}
	S->length = 0;
}

12.销毁串

void StrDestory(SString& S)//销毁栈
{
	if (S.ch)
	{
		delete S.ch;
	}
}

13.返回子串T在主串S中第pos个字符之后的位置

int Index(SString* S, SString* T, int pos)//返回子串T在主串S中第pos个字符之后的位置,若不存在,返回0
{
	if (pos < 1 || pos > S->length)
	{
		printf("输入有误!");
		return 0;
	}
	int i = pos;
	int j = 0;
	while (i <= S->length && j <= T->length)
	{
		if (S->ch[i - 1] == T->ch[j])//判断主串S中第pos个字符后的字符和子串中各字符是否相同

		{
			++i;
			++j;
		}
		else
		{
			i = i - j + 1;//i退回到上次匹配首位的下一位
			j = 0;
		}
	}
	if (j == T->length)
		return i - T->length;
	else
		return 0;
}

image-20220120185148189

posted on 2022-02-06 20:08  眉目作山河  阅读(1751)  评论(0编辑  收藏  举报

导航