数据结构~11.串

数据结构~11.串

本文是上一篇文章的后续,详情点击该链接~

串的基本定义

       串是由零个或者多个字符组成的有序序列。串中字符的个数称为串的长度,含有零个元素的串叫空串。

	//这就好比一个名为str的串
	char str[] = "today is greate day";

       串中任意连续的字符组成的子序列称为该串的子串,包含子串的串称为主串,某个字符在串中的序号称为这个字符的位置。通常用子串第一个字符作为子串在主串中的位置。要注意,空格也是串字符集合中的一个元素,由一个或者多个空格组成的串称为空格串(注意:空格串不是空串)

       串的逻辑和线性表类似,串限定了元素为字符的线性表。从操作集上讲,串和线性表有很大的区别,线性表的操作主要针对表内的某一个元素,而串操作主要针对串内的一个子串

串的存储结构

       一般不采用刚才的那种方式来定义并初始化一个串。原因是仅仅以'\0'作为串结束的标记在求串长的时候需要扫描整个串,时间复杂度为O(n)。不如额外来定义一个变量,专门来存储串的长度,这样一来求串长的时间复杂度为 O(1)

顺序存储表示结构体定义如下
#define MAXSIZE 100
typedef struct {
	char str[MAXSIZE + 1]; //MAX + 1 是为了多出一个 \0 作为结束标记
	int length;
}Str;
动态分配存储表示

       在程序执行的过程根据需要动态分配

typedef struct {
	char *ch;			//指向动态分配存储区首地址的字符指针
	int length;			//串的长度
}Str;

       这种存储方式在使用时,需要用函数malloc()来分配一个长度为length,类型为char的存储空间,分配的空间可以用函数free()释放掉。用函数malloc()分配存储的空间如果成功,则返回一个指向起始地址的指针,作为串的基地址,这个地址由ch指针来指向。如果分配失败,则返回NULL。

       动态分配存储比顺序存储更加灵活,因此在串处理应用程序中,更为常用。

串的基本操作

赋值操作

       与普通变量赋值操作不同,串的赋值操作不能直接用=来表示,因为串是一个数组,必须对数组中的每个元素进行逐一赋值。操作串的赋值操作可以用strassign()实现。其功能是将一个常量字符串赋值给str。成功返回1,失败返回0

int strassign(Str &str,char *ch) {
	int len = 0,i;
	char* c = ch;	//将ch赋给c,这样操作c时候,就不会破坏原来的ch
	//求串c的长度
	while (*c) {
		len++;
		c++;
	}
	if (len == 0) {	//如果ch为空串,则返回空串
		str.ch = NULL;
		str.length = 0;
		return 1;
	}
	else {
		//动态分配空间,取 len + 1 是为了多出一个空间存放 '\0'
		str.ch = (char*)malloc(sizeof(char) * (len + 1));
		if (str.ch == NULL) {
			return 0;
		}
		else {
			//把ch重新赋值给c,这样c又恢复到初始值
			c = ch;
			for (i = 0; i <= len; ++i,++c) {
				str.ch[i] = *c;
				str.length = len;
				return 1;
			}
		}
	}
}
获取串的长度操作
int strlength(Str str) {
	return str.length;
}
串的比较操作

       串的比较操作是串排序应用中的核心操作。通常是用ASCLL码进行比较

//串的比较操作
int strcompare(Str s1,Str s2) {
	int i;
	//任何一个串被遍历完毕就跳出循环
	for (i = 0; i < s1.length && i < s2.length; ++i) {
		//当两个串遇到不相同的字符的时候,就进行ASCLL比较
		if (s1.ch[i] != s2.ch[i]) {
			return s1.ch[i] - s2.ch[i];
		}
	}
	//假如两个串完全相同,就进行长度比较
	return s1.length - s2.length;
}
串的链接操作

       将两个串首尾相接,合并成一个字符串的操作称为串连接操作

//串的链接操作
int concat(Str& str, Str str1, Str str2) {
	int i = 0, j = 0;
	//这里 + 1是为了给 '\0' 留个位置
	str.ch = (char*)malloc(sizeof(char) * (str1.length + str2.length + 1));

	if (str.ch == NULL) {
		return 0;
	}

	while (i < str1.length) {
		str.ch[i] = str1.ch[i];
		++i;
	}
	//这里使用 <= 是为了连同 str2.ch最后 '\0' 一起复制
	while (j <= str2.length) {
		//从i的坐标开始赋值
		str.ch[i + j] - str2.ch[j];
		++j;
	}
	str.length = str1.length + str2.length;
	return 1;
}
求子串操作

       求从给定串中某一位置结束的串的操作称为求字串操作(规定开始位置总在结束位置的前边)。

//str串中从post开始到len,由substr返回
int substring(Str&substr,Str str,int pos,int len) {
	int i = 0, j = 0;
	if (pos < 0 || pos >= str.length || len < 0 || len > str.length - pos) {
		return 0;
	}
	if (substr.ch) {
		free(substr.ch);
		substr.ch = NULL;
	}
	if (len == 0) {
		substr.ch = NULL;
		substr.length = 0;
		return 1;
	}
	else {
		substr.ch = (char*)malloc(sizeof(char) * (len + 1));
		i = pos;
		j = 0;
		while (i < pos + len) {
			substr.ch[j] = str.ch[i];
			++i;
			++j;
		}
		substr.ch[j] = '\0';
		substr.length = len;
		return 1;
	}
}
串清空操作
int clearstring(Str &str) {
	if (str.ch) {
		free(str.ch);
		str.ch = NULL;
	}
	str.length = 0;
	return 1;
}

猜你喜欢

转载自blog.csdn.net/qq_41424688/article/details/107740054