串(string)的堆方式实现详解----线性结构

前面已经完成了线性表、栈、队列等线性表的学习与实现,今天终于完成了线性结构中另一重要的数据结构----串(string),来和大家分享一下,共同进步。

串,又称字符串。

其实就是由一个或多个字符组成的字符序列,使用串可以方便地存储我们想要存储的一切信息。

假如我们现在需要存储某个同学的具体姓名、某个名人名言、某个段落、某篇文章,这些信息中既包含有数字信息、英文信息、中文信息、标点符号、特殊符号等,我们此时就可以用 串(string) 来进行存储了。

串拥有很多操作方法,如初始化字符串、拷贝字符串、检索字符串、截取字符串、连接字符串、插入字符串、删除字符串、替换字符串、比较字符串等,使用这些方法可以很方便地对字符串进行各种操作,实现用户的需要。

串可以分为顺序串堆串

顺序串采用字符数组进行实现,由于采用字符数组需要预先开辟一个固定的存储空间,而且不易拓展,所以这篇文章暂时不为大家推荐顺序串,顺序串具体的代码我一会分享给大家。

堆串采用堆的方法动态地为串的内容开辟内存空间,能够有效的节约内存资源,并有益于串的扩展操作和兼容操作,便于用户操作。

下面是串的具体实现代码,如果有小伙伴有不理解的地方或者疑虑,欢迎留言评论~

串的定义

#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2

#define STRING_INIT_SIZE 100

//定义字符串 string 类型 
typedef struct StringNode{
    
    
	char *content;			//字符串内容 content 
	int length;				//字符串长度 length 
}*String;

所有方法的声明

int initString(String &string);						//初始化线性化结构 串(string) 
int destroyString(String &string);					//销毁字符串string  
int isEmptyString(String &string);					//判断是否为空串 
int strLength(String &string);						//返回字符串的长度 
void printString(String &string);					//打印字符串string
int clearString(String &string);					//清空字符串
int assignString(String &string, char chars[]);					//生成一个值为常量为chars的字符串string 
int copyString(String &string, String s);						//拷贝字符串,将字符串s拷贝赋值给string 
int compareString(String &string, String s);					//对比两个字符串,若string>s,返回>0,相等返回0,否则返回<0
int concatString(String &string, String s1, String s2);			//将s1和s2连接的新串赋值给string 
int subString(String &string, String &s, int pos, int len);		//截取字符串,以s串返回string字符串第pos开始len个长度的串 
int indexString(String &string, String s, int pos);				//检索字符串,返回string串第pos位置后第一次和s串相同子串的开始位置,否则返回0 
int replaceString(String &string, String s1, String s2);		//替换字符串,以串s2替换掉string串中所有的串s1 
int insertString(String &string, String s, int pos);			//插入字符串,将子串s插入到string字符串的第pos个位置 
int deleteString(String &string, int pos, int len);				//删除字符串,删除string字符串中第pos个位置开始,长度为n的字串 

初始化字符串数据类型
//使用字符数组对串进行初始化 
int assignString(String &string, char chars[])
{
    
    
	int i, j;
	char *p = chars;					//定义一个字符指针指向字符数组 
	while(*p != '\0' && *p != '\n')			//循环统计字符数组长度 
	{
    
    
		p++;
		i++;							//计数器累加 
	}
	
	string->content = (char *)malloc(i*sizeof(char));	//动态地为串的内容开辟相应地内存空间存储串信息 
	string->length = i; 				//设置串的长度 
	
	for(j = 0; j < i; j++)
	{
    
    
		string->content[j] = chars[j];		//将字符数组内容复制给串的内容	
	}
	string->content[j] = '\0';			//字符串内容的最后一位设置为字符结束符 
	return OK;						//返回结果 
}

拷贝字符串

//复制字符串,将字符串s的内容复制给string 
int copyString(String &string, String s)
{
    
    
	int length = s->length;					//记录字符串s的长度 
	if(length == 0)							//若字符串的长度为0,则直接清空string串,返回 
	{
    
    
		clearString(string);
		return OK;
	}
	else									//否则 
	{
    
    
		//根据新的内容使用realloc()函数重新为串string开辟内容空间 
		string->content = (char *)realloc(string->content, length*sizeof(char));
		char *p = s->content, *q = string->content;		//定义p指针指向s内容,q指针指向string内容 
		while(*p != '\0' && *p != '\n')			//使用p指针重复读取s之中的内容,直至s串结束 
		{
    
    
			*q = *p;				//将p指针中的内容赋值给q指针指向的内容,进行复制 
			p++;
			q++;					//p、q指针累加,指向串中的下一内容 
		}
		*q = '\0';					//复制完毕,q指针指向的string串以'\0'结束 
		string->length = s->length;			//更新串string的长度 
		return OK;			//返回结果 
	}
	
}

比较字符串

//对两个字符串string和s进行比较,
//若string > s,返回 > 0;
//若string < s,返回 < 0;
//否则返回0 
int compareString(String &string, String s)
{
    
    
	//循环比较string串和s串,当string和s的第一个字符相等时,比较第2个,再相等比较第3个...,直至string串或s串结束 
	for(int i = 0; i < string->length && i < s->length; i++)
	{
    
    
		if(string->content[i] != s->content[i])			//若两个串的某个位置的字符串不等 
			return string->content[i] - s->content[i];		//返回它们的差值,即为结果(ASCLL码) 
	}
	return string->length - string->length;			//若持续相等,返回它们的长度的差值 
}

连接字符串

//将字符串s1和字符串s2连接成为新的字符串string 
int concatString(String &string, String s1, String s2)
{
    
    
	int length = s1->length + s2->length, i;	//记录s1和s2字符串长度之和 
	string->content = (char *)realloc(string->content, length*(sizeof(char)));		//重新为string串内容开辟此长度的空间 
	//通过循环的方式连接两个字符串 
	for(i = 0; i < length; i++)
	{
    
    
		if(i < s1->length)			//若 i < s1的长度,则先添加s1字符串内容 
			string->content[i] = s1->content[i];
		else						//之后再添加s2字符串的内容 
			string->content[i] = s2->content[i-(s1->length)];
	}
	string->content[i] = '\0';		//连接形成的新的字符串string以'\0'结束 
	string->length = length;		//更新字符串string的长度 
	
	return OK;		//返回结果 
}

截取字符串

//截取字符串,把string字符串的第pos个位置开始,长度为len的子字符串截取下来,赋值给s返回 
int subString(String &string, String &s, int pos, int len)
{
    
    
	if(pos < 1 || pos > string->length || len < 0 || len > string->length+1)
		return ERROR;			//若截取参数有误,直接返回错误信息 
	
	int i = 0;			//定义计数器 
	s->content = (char *)malloc(len*sizeof(char));		//动态为s字符串开辟长度为len的字符串内容 
	s->length = len;					//并设置字符串的长度 
	
	//从字符串的第pos个位置开始,循环进行截取内容 
	for(i = pos-1; i < pos-1+len; i++)
	{
    
    
		s->content[i-(pos-1)] = string->content[i];		//截取内容赋值给s字符串 
	}
	
	s->content[i-(pos-1)] = '\0';		//为s字符串的最后字符'\0'作为字符串结束标志 
	return OK;		//返回结果 
}


插入字符串

//在字符串string的第pos个位置插入新的字符串s 
int insertString(String &string, String s, int pos)
{
    
    
	if(s->length == 0 || pos < 1 || pos > string->length+1)
		return ERROR;		//若插入参数有误,直接返回错误信息 
	
	int length = string->length + s->length;		//对插入的长度进行增加保存 
	
	int i = 0;
	String new_string; 				//定义新的new_string字符串准备接收 
	initString(new_string);			//初始化new_string字符串 
	new_string->content = (char *)malloc(length*sizeof(char));		//动态为该字符串开辟长度为length的空间 

	//循环通过3段连接的方式进行字符串的添加,暂添加至new_string 
	for(i = 0; i < length; i++)
	{
    
    
		if(i < pos-1)
			new_string->content[i] = string->content[i];	//添加pos之前string字符串的内容 
		else if(i >= pos-1 && i < pos - 1 + s->length)
			new_string->content[i] = s->content[i-(pos-1)];		//添加s字符串的内容 
		else
			new_string->content[i] = string->content[i-s->length];		//添加pos位置之后string字符串的内容 
	}
	new_string->content[i] = '\0';		//字符串new_string内容以'\0'结束标志 
	new_string->length = length;		//设置字符串长度 
	
	copyString(string, new_string); 	//进行字符串复制,即此时string便是已成功插入的字符串 
	return OK;		//返回结果 
}


删除字符串

//删除字符串string从第pos个位置开始,长度为len的子串 
int deleteString(String &string, int pos, int len)
{
    
    
	if(pos < 1 || pos > string->length || len < 1 || pos - 1 + len > string->length)
		return ERROR;		//若删除参数有误,直接返回错误信息 
		
	int i,j;
	String new_string;		//同插入字符串操作,定义新的字符串new_string 
	initString(new_string);			//初始化字符串 
	new_string->content = (char *)malloc((string->length-len)*(sizeof(char)));		//为新的字符串内容动态开辟空间 
	
	//循环通过2段字符串的连接进行子串的删除 
	for(i = 0, j = 0; i < string->length; i++)
	{
    
    
		if(i < pos-1)
			new_string->content[j++] = string->content[i];		//添加pos位置之前的string串的内容 
		if(i >= pos-1+len)
			new_string->content[j++] = string->content[i];		//添加pos-1+len位置之后string串的内容,便实现删除 
	}
	new_string->content[j] = '\0';				//字符串new_string内容以'\0'结束标志 
	new_string->length = string->length-len;	//设置字符串的长度 
	
	copyString(string, new_string);			//进行字符串复制,即此时string便是已成功删除子串的字符串 	
	return OK;			//返回结果 
}

替换字符串


//字符串替换操作,将string串中所有s1子串替换为s2子串 
int replaceString(String &string, String s1, String s2)
{
    
    
	if(string->length == 0)			//string为空串,直接返回 
		return ERROR;
	if(indexString(s2, s1, 1) != 0)		//s2中包含s1子串,会造成递归无限替换,直接返回 
		return ERROR;
	
	for(int i = 0; i < string->length; i++)			//循环检索所有的情况 
	{
    
    
		int j = indexString(string, s1, i+1);			//从第i+1个位置后检索string串是否包含s1串,若包含,返回子串开始位置 
		if(j > 0)			//若包含 
		{
    
    
			deleteString(string, j, s1->length);		//删除string中的从j位置开始的子串 s1 
			insertString(string, s2, j);				//添加子串s2 到字符串string的第j个位置,替换成功 
		}
	}
	
	return OK;			//返回结果 
}

检索字符串

//从第pos个位置开始,检索string中是否包含子串s,若包含返回第一次发现子串的起始位置,否则返回0 
int indexString(String &string, String s, int pos)
{
    
    
	if(pos > string->length)
		return ERROR;			//若pos位置有误,直接返回 

	String new_string; 
	initString(new_string);			//定义并初始化新的字符串new_string 
	for(int i = pos-1; i < string->length; i++)		//从第pos个位置循环检索每一个子串 
	{
    
    
		subString(string, new_string, i+1, s->length);		//截取string串中的每个子串 
		if(compareString(new_string, s) == 0)		//若该子串和子串s相等,说明检索成功 
			return i+1;				//返回该子串的起始位置 
	}
	
	return FALSE;			//否则,返回false,即0 
}


字符串判空、清空、销毁、打印字符串


//判断字符串string是否为空串 
int isEmptyString(String &string)
{
    
    
	if(string->length == 0)
		return TRUE;			//空串返回1 
	else
		return FALSE;			//否则返回0 
}


//返回字符串string的长度,冗余操作 
int strLength(String &string)
{
    
    
	return string->length;
}


//清空字符串string
int clearString(String &string)
{
    
    
	free(string->content);		//释放string字符串内容空间 
	string->content = NULL;		//设置string内容空间为NULL 
	string->length = 0;			//设置string内容长度为0 
	return OK;		//返回结果 
}


//销毁字符串string
int destroyString(String &string)
{
    
    
	clearString(string);		//清空字符串string
	
	free(string);			//释放字符串string空间 
	string = NULL;			//字符串string为NULL 
	
	return OK;			//返回结果 
}


//打印字符串string
void printString(String &string)
{
    
    
	printf("字符串的内容为:\n");
	printf("%s\n", string->content);
	printf("长度---->%d.\n", string->length);
	return;
}


好啦,明天有空再把串的顺序实现代码分享给大家,加油~

猜你喜欢

转载自blog.csdn.net/weixin_43479947/article/details/113732358