数据结构笔记(十三)-- 串的堆分配存储表示

串的堆分配存储表示

一、堆分配存储概述

堆分配内存仍是一组地址连续的存储单元来存放串值字符序列,但是存储空间实在程序执行过程中动态分配而得。在C语言中,存在一个称为“堆”的自由存储区,并由C语言的动态分配函数malloc()和free()来管理。利用函数malloc()为每个新产生的串分配一块实际串长所需的存储空间,若分配成功,则返回一个指向起始地址的指针,作为串的基址,同时为了方便以后的处理,约定串长也作为存储结构的一部分。

二、串的堆分配存储结构

在这里插入图片描述
在这里插入图片描述

三、串的操作

//1、初始化(产生空串)字符串S
void InitString(pHString S);
//2、将S清为空串
void ClearString(pHString S);
//3、生成一个其值等于串常量chars的串S
void StrAssign(pHString S, char *chars);
//4、显示字符串
void StrShow(pHString S);
//5、复制串S到T
void StrCopy(pHString T, pHString S);
//6、判断串是否为空,若为空返回True,否则返回false
bool StrEmpty(pHString S);
//7、比较两个串的最前面字符的ASCII码的大小,若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0 
int StrCompare(pHString S, pHString T);
//8、返回S的元素个数,称为串的长度
int StrLength(pHString &S);
//9、用T返回由S1和S2联接而成的新串
void StrConcat(pHString S1, pHString S2, pHString T);
//10、用Sub返回串S的第pos个字符起长度为len的子串。
bool StrSub(pHString Sub, pHString S, int pos, int len);
//11、找出子串T值主串S中的位置(与子串首字符相等的位置)
int Index1(pHString S, pHString T);
//12、 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数值为0,其中,T非空,1≤pos≤StrLength(S)。
int Index2(pHString S, pHString T, int pos);
//13、从串S中删除第pos个字符起长度为len的子串,从新申请空间
bool StrDelete1(pHString S, int pos, int len);
//14、从串S中删除第pos个字符起长度为len的子串,调整内存空间
bool StrDelete2(pHString S, int pos, int len);
typedef struct HString
{
	char * ch; // 若是非空串,则按串长分配存储区,否则ch为NULL
	int length; // 串长度
}HString,*pHString;

1、初始化(产生空串)字符串S

在这里插入图片描述

void InitString(pHString S)
{ 
	S->ch = NULL;
	S->length = 0;	
}

2、将S清为空串

在这里插入图片描述

void ClearString(pHString S)
{ 
	free(S->ch);
	S->ch = NULL;
	S->length = 0;
}

3、生成一个其值等于串常量chars的串S

在这里插入图片描述

void StrAssign(pHString S, char *chars)
{
	int i, j;
	if (S->ch)//若S的指针不为空则释放S指针域所指向的空间
		free(S->ch); // 释放S原有空间
	i = strlen(chars); // 求chars的长度i
	if (!i)//若果字符串为空则清空S(相当于复制了一个空字符串)
	{ // chars的长度为0
		S->ch = NULL;
		S->length = 0;
	}
	else
	{ // chars的长度不为0
		S->ch = (char*)malloc(i * sizeof(char)); // 分配大小跟chars大小相同的串空间
		if (!S->ch) // 分配串空间失败
			exit(-1);
		for (j = 0; j < i; j++) // 复制串
			S->ch[j] = chars[j];
		S->length = i;
	}
}

4、显示字符串

void StrShow(pHString S)
{ 
	int i;
	for (i = 0; i < S->length; i++)
		printf("%c", S->ch[i]);
	printf("\n");
}

5、复制串S到T

在这里插入图片描述

void StrCopy(pHString T,pHString S )
{
	if (T->ch)
		free(T->ch); // 释放T原有空间
	T->ch = (char *)malloc(S->length*(sizeof(char)));//申请内存
	if (T->ch == NULL)
	{
		printf("内存分配失败!");
		exit(-1);
	}
	for (int i = 0; i < S->length; i++)//逐一复制
	{
		T->ch[i] = S->ch[i];
	}
	T->length = S->length;//复制串长
	
}

6、判断串是否为空,若为空返回True,否则返回false

bool StrEmpty(pHString S)
{
	if (S->length==0&&S->ch==NULL)//空串标志
	{
		return true;
	}
	else
	{
		return false;
	}
}

7、比较两个串的最前面字符的ASCII码的大小,若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0

在这里插入图片描述

8、返回S的元素个数,称为串的长度

int StrLength(pHString &S)
{ 
	return S->length;
}

9、用T返回由S1和S2联接而成的新串

在这里插入图片描述

void StrConcat(pHString S1, pHString S2, pHString T)
{

	if (T->ch)
		free(T->ch); // 释放T原有空间
	T->ch = (char *)malloc((S1->length + S2->length)*(sizeof(char)));//申请内存
	if (T->ch == NULL)
	{
		printf("内存分配失败!");
		exit(-1);
	}
	for (int i = 0; i < S1->length; i++)//逐一复制S1
	{
		T->ch[i] = S1->ch[i];
	}
	for (int i = 0; i < S2->length; i++)//接着逐一复制S2
	{
		T->ch[S1->length +i] = S2->ch[i];
	}
	T->length = (S1->length + S2->length);//复制总串长
}

10、用Sub返回串S的第pos个字符起(包括pos位置处的字符)长度为len的子串。

在这里插入图片描述

bool StrSub(pHString Sub,pHString S,int pos,int len)
{
	if (StrEmpty(S))
	{
		return	false;
	}
	if (pos<1||pos>S->length||len<0||len>S->length-pos+1)//排除不符合条件的pos和len
	{
		return	false;
	}
	if (Sub->ch)
		free(Sub->ch); // 释放旧空间
	if (!len) // 空子串
	{
		Sub->ch = NULL;
		Sub->length = 0;
	}
	else
	{
		Sub->ch = (char*)malloc(len * sizeof(char));//申请len个空间
		if (!Sub->ch)
			exit(-1);
	}
	for (int i = pos; i < pos+len; i++)//逐个复制
	{
		Sub->ch[i - pos] = S->ch[i-1];
	}
	Sub->length = len;//保存长度
	return true;
}

11、找出子串T值在主串S中的位置(与子串首字符相等的位置)

在这里插入图片描述

int Index1(pHString S, pHString T)
{
	int i,j;
	for (i = 0; i < S->length; i++)//循环主串
	{
		if (S->ch[i] == T->ch[0])//如果在主串中找到一个与子串的第一个字符相等的字符时
		{
			int cont = 1;//计数变量
			for (j = 0; j < T->length; j++)//遍历子串
			{
				if (T->ch[j + 1] != S->ch[i + j+1])//在遍历T[0]时如果有不一致时退出遍历
				{
					break;
				}
				else//否则计数
				{
					cont++;
					if (cont == T->length)//当有T[0]个字符相同时则找到子串位置
						return i+1;
				}
			}
		}
		continue;
	}
	return 0;//不存在时
}

12、返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数值为0,其中,T非空,1≤pos≤StrLength(S)。在这里插入图片描述

int Index2(pHString S, pHString T, int pos)
{
	int i, j;
	if (1 <= pos && pos <= S->length)
	{
		i = pos;//从主串的第pos个字符开始和子串的第一个字符比较
		j = 0;
		while (i <= S->length && j < T->length)
		{
			if (S->ch[i] == T->ch[j]) // 若找到主串字符与子串首字符相等时继续比较后继字符
			{
				++i;
				++j;
			}
			else // 指针后退,主串字符下标后移一位,重新开始匹配
			{
				i = i + 1;
				j = 0;
			}
		}
		if (j == T->length)//条件成立,子串在主串中
			return i - T->length+1;//因为i是下标,下标编程序号需要+1
		else
			return 0;
	}
	else
		return 0;
}

13、从串S中删除第pos个字符起长度为len的子串,从新申请空间

在这里插入图片描述

bool StrDelete1(pHString S, int pos, int len)
{
	if (StrEmpty(S))//S为空时
	{
		return	false;
	}
	if (pos<1||pos>S->length||len<0||len>S->length-pos+1)//pos和len不满足条件时
	{
		return false;
	}
	char *pNew = (char*)malloc((S->length - len) * sizeof(char));//从新申请空间
	if (pNew==NULL)//申请失败
	{
		return false;
	}
	for (int i = 0; i < pos-1; i++)//复制pos前的字符
	{
		pNew[i] = S->ch[i];
	}
	for (int i = pos+len-1; i < S->length; i++)//复制pos+len-1后的字符
	{
		pNew[i-len] = S->ch[i];
	}
	free(S->ch);//释放原内存
	S->ch = pNew;
	S->length = S->length - len;//更新长度
	return true;
}

14、从串S中删除第pos个字符起长度为len的子串,调整内存空间

在这里插入图片描述

bool StrDelete2(pHString S, int pos, int len)
{
	int i;
	if (StrEmpty(S))//S为空时
	{
		return	false;
	}
	if (S->length < pos + len - 1)//pos和len不满足条件时
		return false;
	for (i = pos - 1; i <= S->length - len; i++)//从pos + len - 1起,之后的元素向前移动
		S->ch[i] = S->ch[i + len];
	S->length -= len;
	S->ch = (char*)realloc(S->ch, S->length * sizeof(char));//调整S->ch的空间
	return true;
}

最后给出完整代码

// 串的堆分配存储.cpp 
#include<string.h>
#include<malloc.h> // malloc()等
#include<stdio.h> // EOF(=^Z或F6),NULL
#include<stdlib.h> // atoi()

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

//1、初始化(产生空串)字符串S
void InitString(pHString S);
//2、将S清为空串
void ClearString(pHString S);
//3、生成一个其值等于串常量chars的串S
void StrAssign(pHString S, char *chars);
//4、显示字符串
void StrShow(pHString S);
//5、复制串S到T
void StrCopy(pHString T, pHString S);
//6、判断串是否为空,若为空返回True,否则返回false
bool StrEmpty(pHString S);
//7、比较两个串的最前面字符的ASCII码的大小,若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0 
int StrCompare(pHString S, pHString T);
//8、返回S的元素个数,称为串的长度
int StrLength(pHString &S);
//9、用T返回由S1和S2联接而成的新串
void StrConcat(pHString S1, pHString S2, pHString T);
//10、用Sub返回串S的第pos个字符起长度为len的子串。
bool StrSub(pHString Sub, pHString S, int pos, int len);
//11、找出子串T值主串S中的位置(与子串首字符相等的位置)
int Index1(pHString S, pHString T);
//12、 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数值为0,其中,T非空,1≤pos≤StrLength(S)。
int Index2(pHString S, pHString T, int pos);
//13、从串S中删除第pos个字符起长度为len的子串,从新申请空间
bool StrDelete1(pHString S, int pos, int len);
//14、从串S中删除第pos个字符起长度为len的子串,调整内存空间
bool StrDelete2(pHString S, int pos, int len);

int main()
{
	HString S, T, S1,Sub;
	InitString(&S);	
	InitString(&S1);	
	InitString(&T);
	InitString(&Sub);
	char chars[] = "god bye!";
	StrAssign(&S, chars);
	StrShow(&S);

	StrCopy(&T,&S);
	StrShow(&T);
	if (StrEmpty(&S))
	{
		printf("串S为空\n");
	}
	else
	{
		printf("串S不为空\n");
	}
	char char1[] = "god hello!";
	StrAssign(&T, char1);
	StrShow(&T);
	printf("比较S和T的结果%d\n", StrCompare(&S, &T));
	StrAssign(&S1, char1);
	printf("拼接字符串");
	StrShow(&S);
	StrShow(&S1);
	StrConcat(&S,&S1,&T);
	StrShow(&T);

	int pos = 3, len = 3;
	if (StrSub(&Sub, &S, pos, len))
	{
		StrShow(&Sub);
	}
	HString SS, TT;
	InitString(&SS);
	InitString(&TT);
	char char2[] = "abcdefghijklmn";
	char char3[] = "bcd";
	StrAssign(&SS, char2);
	StrShow(&SS);
	StrAssign(&TT, char3);
	printf("子串T在主串S中的位置为 %d\n", Index1(&SS,&TT));
	printf("子串T在主串S中的位置为 %d\n", Index2(&SS,&TT,5));
	StrShow(&SS);
	StrDelete1(&SS, pos, 3);
	StrShow(&SS);
	StrDelete2(&SS, pos, 3);
	StrShow(&SS);
	


	return 0;
}


//1、初始化(产生空串)字符串S
void InitString(pHString S)
{ 
	S->ch = NULL;
	S->length = 0;	
}

//2、将S清为空串
void ClearString(pHString S)
{ 
	free(S->ch);
	S->ch = NULL;
	S->length = 0;
}
//3、生成一个其值等于串常量chars的串S
void StrAssign(pHString S, char *chars)
{
	int i, j;
	if (S->ch)//若S的指针不为空则释放S指针域所指向的空间
		free(S->ch); // 释放S原有空间
	i = strlen(chars); // 求chars的长度i
	if (!i)//若果字符串为空则清空S(相当于复制了一个空字符串)
	{ // chars的长度为0
		S->ch = NULL;
		S->length = 0;
	}
	else
	{ // chars的长度不为0
		S->ch = (char*)malloc(i * sizeof(char)); // 分配大小跟chars大小相同的串空间
		if (!S->ch) // 分配串空间失败
			exit(-1);
		for (j = 0; j < i; j++) // 复制串
			S->ch[j] = chars[j];
		S->length = i;
	}
}
//4、显示字符串
void StrShow(pHString S)
{ 
	int i;
	for (i = 0; i < S->length; i++)
		printf("%c", S->ch[i]);
	printf("\n");
}
//5、复制串S到T
void StrCopy(pHString T,pHString S )
{
	if (T->ch)
		free(T->ch); // 释放T原有空间
	T->ch = (char *)malloc(S->length*(sizeof(char)));//申请内存
	if (T->ch == NULL)
	{
		printf("内存分配失败!");
		exit(-1);
	}
	for (int i = 0; i < S->length; i++)//逐一复制
	{
		T->ch[i] = S->ch[i];
	}
	T->length = S->length;//复制串长
	
}
//6、判断串是否为空,若为空返回True,否则返回false
bool StrEmpty(pHString S)
{
	if (S->length==0&&S->ch==NULL)//空串标志
	{
		return true;
	}
	else
	{
		return false;
	}
}
//7、比较两个串的最前面字符的ASCII码的大小,若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0 
int StrCompare(pHString S, pHString T)
{
	for (int i = 0; i < S->length&&T->length; i++)
	{
		if (S->ch[i]!=T->ch[i])//逐一比较字符
		{
			return	S->ch[i] - T->ch[i];//一旦不相等,则返回不想等字符的ASCII码的差值
		}
	}
	return S->length - T->length;//如果全部相等则返回其长度差值
}
//8、返回S的元素个数,称为串的长度
int StrLength(pHString &S)
{ 
	return S->length;
}
//9、用T返回由S1和S2联接而成的新串
void StrConcat(pHString S1, pHString S2, pHString T)
{

	if (T->ch)
		free(T->ch); // 释放T原有空间
	T->ch = (char *)malloc((S1->length + S2->length)*(sizeof(char)));//申请内存
	if (T->ch == NULL)
	{
		printf("内存分配失败!");
		exit(-1);
	}
	for (int i = 0; i < S1->length; i++)//逐一复制S1
	{
		T->ch[i] = S1->ch[i];
	}
	for (int i = 0; i < S2->length; i++)//接着逐一复制S2
	{
		T->ch[S1->length +i] = S2->ch[i];
	}
	T->length = (S1->length + S2->length);//复制总串长
}

//10、用Sub返回串S的第pos个字符起(包括pos位置处的字符)长度为len的子串。
bool StrSub(pHString Sub,pHString S,int pos,int len)
{
	if (StrEmpty(S))
	{
		return	false;
	}
	if (pos<1||pos>S->length||len<0||len>S->length-pos+1)//排除不符合条件的pos和len
	{
		return	false;
	}
	if (Sub->ch)
		free(Sub->ch); // 释放旧空间
	if (!len) // 空子串
	{
		Sub->ch = NULL;
		Sub->length = 0;
	}
	else
	{
		Sub->ch = (char*)malloc(len * sizeof(char));//申请len个空间
		if (!Sub->ch)
			exit(-1);
	}
	for (int i = pos; i < pos+len; i++)//逐个复制
	{
		Sub->ch[i - pos] = S->ch[i-1];
	}
	Sub->length = len;//保存长度
	return true;
}
//11、找出子串T值在主串S中的位置(与子串首字符相等的位置)
int Index1(pHString S, pHString T)
{
	int i,j;
	for (i = 0; i < S->length; i++)//循环主串
	{
		if (S->ch[i] == T->ch[0])//如果在主串中找到一个与子串的第一个字符相等的字符时
		{
			int cont = 1;//计数变量
			for (j = 0; j < T->length; j++)//遍历子串
			{
				if (T->ch[j + 1] != S->ch[i + j+1])//在遍历T[0]时如果有不一致时退出遍历
				{
					break;
				}
				else//否则计数
				{
					cont++;
					if (cont == T->length)//当有T[0]个字符相同时则找到子串位置
						return i+1;
				}
			}
		}
		continue;
	}
	return 0;//不存在时
}

//12、返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数值为0,其中,T非空,1≤pos≤StrLength(S)。
int Index2(pHString S, pHString T, int pos)
{
	int i, j;
	if (1 <= pos && pos <= S->length)
	{
		i = pos;//从主串的第pos个字符开始和子串的第一个字符比较
		j = 0;
		while (i <= S->length && j < T->length)
		{
			if (S->ch[i] == T->ch[j]) // 若找到主串字符与子串首字符相等时继续比较后继字符
			{
				++i;
				++j;
			}
			else // 指针后退,主串字符下标后移一位,重新开始匹配
			{
				i = i + 1;
				j = 0;
			}
		}
		if (j == T->length)//条件成立,子串在主串中
			return i - T->length+1;//因为i是下标,下标编程序号需要+1
		else
			return 0;
	}
	else
		return 0;
}

//13、从串S中删除第pos个字符起长度为len的子串,从新申请空间
bool StrDelete1(pHString S, int pos, int len)
{
	if (StrEmpty(S))//S为空时
	{
		return	false;
	}
	if (pos<1||pos>S->length||len<0||len>S->length-pos+1)//pos和len不满足条件时
	{
		return false;
	}
	char *pNew = (char*)malloc((S->length - len) * sizeof(char));//从新申请空间
	if (pNew==NULL)//申请失败
	{
		return false;
	}
	for (int i = 0; i < pos-1; i++)//复制pos前的字符
	{
		pNew[i] = S->ch[i];
	}
	for (int i = pos+len-1; i < S->length; i++)//复制pos+len-1后的字符
	{
		pNew[i-len] = S->ch[i];
	}
	free(S->ch);//释放原内存
	S->ch = pNew;
	S->length = S->length - len;//更新长度
	return true;
}
//14、从串S中删除第pos个字符起长度为len的子串,调整内存空间
bool StrDelete2(pHString S, int pos, int len)
{
	int i;
	if (StrEmpty(S))//S为空时
	{
		return	false;
	}
	if (S->length < pos + len - 1)//pos和len不满足条件时
		return false;
	for (i = pos - 1; i <= S->length - len; i++)//从pos + len - 1起,之后的元素向前移动
		S->ch[i] = S->ch[i + len];
	S->length -= len;
	S->ch = (char*)realloc(S->ch, S->length * sizeof(char));//调整S->ch的空间
	return true;
}

  • 20
    点赞
  • 106
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值