数据结构》严蔚敏 串的ADT实现 用堆串存储 算法4.4

跟前面的线性存储是一个道理的,本质上还是顺序存储,只不过用了堆来动态分配,使串的长度不受限制,更加灵活
借用大佬一张图:
在这里插入图片描述
在这里插入图片描述

4_4.h

#ifndef _4_4_H
#define _4_4_H

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

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -1

#define MAXSIZE 40
#define MAXSTRLEN 10

typedef int Status;

typedef struct
{
	char *ch;
	int length;

}Hstring;

void InitString(Hstring *T);
Status StrAssign(Hstring *T,char *chars);
int StrLength(Hstring T);
Status StrCopy(Hstring T,Hstring *S);
Status StrEmpty(Hstring T);
int StrCompare(Hstring S,Hstring T);
Status ClearString(Hstring *T);
Status SubString(Hstring *Sub,Hstring T,int pos,int len);
Status StrConcat(Hstring *T,Hstring S1,Hstring S2);
Status Replace(Hstring *S,Hstring T,Hstring V);
Status DestroyString(Hstring *S);
int Index(Hstring S,Hstring T,int pos);
Status StrTraverse(Hstring T);
Status StrDelete(Hstring *S,int pos,int len );
Status StrInsert(Hstring *S,int pos,Hstring T);

#endif

4_4.c

//堆分配存储串
//也是顺序结构,不过每一次都重新分配空间,所以对串的长度就没有限制
//查一下用堆分配是时间复杂度变低了吗,还是就是这一个好处呢?

#include "4_4.h"
//初始化为空串
void InitString(Hstring *T)
{
	(*T).ch = NULL;
	(*T).length = 0;
}

Status
StrAssign(Hstring *T,char *chars)
{
	int i,j;
	// if( (*T).ch != NULL )
	// 	free( (*T).ch );

	i = strlen(chars);
	if(!i)            //这也是一个我打死都想不到的地方。。。
	{
		(*T).ch = NULL;
		(*T).length = 0;
	}
	else
	{
		(*T).ch = (char*)malloc(i*sizeof(char));//注意这里为i*sizeof
		if( !((*T).ch) )
			exit(OVERFLOW);
		(*T).length = i; //话说也没有给length分配空间的,所以他到哪里去了?
		//这里这是一个堆串,堆串是个结构体
		//char指针指向动态分配的内存来存储字符,length用来存储串的长度。

		for(j = 0;j < i;j++)
		{
			(*T).ch[j] = chars[j];
		}
	}

	return OK;

}


int
StrLength(Hstring T)
{
	return T.length;
}

//由串T复制得到串S
//复制肯定没问图的 为什么打印不出来???
Status
StrCopy(Hstring T,Hstring *S)
{
	//这里不太会写

	if( (*S).ch != NULL )//是这样的,判断S.ch 而不是S
		free( (*S).ch );//这里不知道对不对
	(*S).ch = (char*)malloc(T.length * sizeof(char)); //怎样分配和T一样大小的空间呢
	//这边
	if( !(*S).ch )
		exit(OVERFLOW);


	for(int i = 0;i<T.length;i++)
	{
		(*S).ch[i] = T.ch[i];
	}

	(*S).length = T.length; //don't forget
	
	//StrTraverse((*S)); //真的很不明白,懂了 忘记给length赋值了。。。尴尬脸
	
	return OK;
}


Status
StrEmpty(Hstring T)
{
	return T.length == 0;

}

int
StrCompare(Hstring S,Hstring T) //这里应该有点小问题
{
	// for(int i = 0;i < S.length;)
	// {
	// 	if(S.ch[i] == T.ch[i])
	// 		i++;
	// 	else if(S.ch[i] > T.ch[i])
	// 		return 1;
	// 	else
	// 		return -1;
	// }

	// if(T.length > S.length)
	// 	return -1;
	// else
	// 	return 0;
    // 这种方法简洁,直接判断当不等于的嘶吼返回,到最后如果都等于就比较字符串长度
	int i;
	for(i = 0;i<S.length && i<T.length;i++)
	{
		if(S.ch[i] != T.ch[i])
			return S.ch[i]-T.ch[i];
	}

	return S.length - T.length;

}


Status
ClearString(Hstring *T)
{
	if((*T).ch) //这一步我给忘记了。。
	{
		free((*T).ch);
		(*T).ch = NULL;
	}
	(*T).length = 0;
	return OK;
}

Status
SubString(Hstring *Sub,Hstring T,int pos,int len)
{
	int i,j;
	//先判断pos len是否合法。我已经忘记一百万次了
	if(pos<1 || pos>T.length || len<0 || pos+len-1>T.length)
		return ERROR;
	//释放旧的空间,这个我也忘记一百万次了,但是加上它会报错诶
	// if((*Sub).ch)
	// 	free((*Sub).ch);
	if(!len)
	{
		(*Sub).ch = NULL;
		(*Sub).length = 0;
	}
	else
	{
		(*Sub).ch = (char*)malloc(len * sizeof(char)); 
		if(!(*Sub).ch)
			exit(OVERFLOW);

		for(i = 0; i<len; i++)
		{
			(*Sub).ch[i] = T.ch[i+pos-1];//oh,还没有给他分配空间,所以有段错误
		}

		Sub->length = len;

	}
	
	return OK;

}

//这块不是很理解
int
Index(Hstring S,Hstring T,int pos)
{
	int s,t,i;
	Hstring tmp;
	InitString(&tmp);
	
	if(pos > 0) //我打死都想不起来要判断一下。。
	{
		s = StrLength(S);
		t = StrLength(T);
		i = pos;
		while(i+t-1 <= s)
		{
			SubString(&tmp,S,i,t);
			if(StrCompare(tmp,T) == 0) //直接就这样比较,也不看看是不是都相等啊
				return i;
			else
				i++;
		}
	}
	


	return 0;
}

//因为是动态分配,所以不存在截断问题
Status
StrConcat(Hstring *T,Hstring S1,Hstring S2)
{
	int i;
	// if((*T).ch)      //释放旧的空间,这一步不要忘记了
	// 	free((*T).ch);
	//看来这个得慎用。总是报错
	(*T).length = S1.length + S2.length;
	(*T).ch = (char*)malloc((*T).length*sizeof(char));
	if(!(*T).ch)
		exit(OVERFLOW);

	for(i = 0;i<S1.length;i++)
		(*T).ch[i] = S1.ch[i];
	for(i = 0;i<S2.length;i++)
		(*T).ch[S1.length+i] = S2.ch[i];

	return OK;  
}

Status
Replace(Hstring *S,Hstring T,Hstring V)
{
	int i;
	if(StrEmpty(T))
		return ERROR;
	i = Index(*S,T,1);

	while(i != 0)
	{
		StrDelete(S,i,StrLength(T));
		StrInsert(S,i,V);

		i += StrLength(V);
		i = Index(*S,T,i);
	}
	return OK;
}

Status
StrDelete(Hstring *S,int pos,int len )
{
	int i;
	if(StrEmpty(*S))
		return ERROR;
	if(pos < 1 || pos+len-1 > (*S).length || len<0)
		return ERROR;
	for(i = pos-1;i+len<=(*S).length;i++)
		(*S).ch[i] = (*S).ch[i+len];

	(*S).length -= len;
	(*S).ch = (char*)realloc( (*S).ch, (*S).length*sizeof(char));

	return OK;

}

Status
StrInsert(Hstring *S,int pos,Hstring T)
{
	int i;
	if(pos<1 || pos>(*S).length)
		return ERROR;
	if(StrEmpty(T))
		return ERROR;
	else
	{
		(*S).ch = (char*)realloc((*S).ch, ((*S).length+T.length) *sizeof(char));
		if(!(*S).ch)
			exit(OVERFLOW);
		for(i = (*S).length -1;i>pos-1;i--)
			(*S).ch[i+T.length] = (*S).ch[i];

		for(i = 0;i<T.length;i++)
			(*S).ch[pos-1+i] = T.ch[i];

		(*S).length += T.length;
	}

	return OK;

}

Status
DestroyString(Hstring *S)
{
	//堆串不能被销毁

	return ERROR;

}


Status
StrTraverse(Hstring T)
{
	for(int i = 0;i<T.length;i++)
		printf("%c",T.ch[i]);

	printf("\n");
	return OK;
}

测试用例(写的比较水)

int main(int argc, char const *argv[])
{
	Hstring T,S,W,V,X,Y;
	char *chars = "hello,yannie~";
	char *chars1 = "yannie";
	char *chars2 = "*_*";
	StrAssign(&T,chars);
	StrAssign(&V,chars1);
	StrAssign(&X,chars2);
	StrTraverse(T);

	int i = StrLength(T);
	printf("T's length is %d\n", i);

	printf("Now i will copy T to S\n");
	StrCopy(T,&S);
	printf("S: ");
	StrTraverse(S);

	printf("judge the String W is empty or not: ");
	int tmp = StrEmpty(W);
	if(tmp == 1)
		printf("Yes!\n");
	else
		printf("No!\n");

	printf("test the T and S: ");
	int j = StrCompare(S,T);
	if(j == 0)
		printf("the same big!\n");
	if(j > 0)
		printf("S is bigger!\n");
	if(j < 0)
		printf("T is bigger!\n");	

	printf("from T find sit 2 to sit 4,and stored in W\n");
	SubString(&W,T,2,4);
	printf("W: ");
	StrTraverse(W);


	printf("whether V in T after pos = 2 ?if yes,return the sitution: ");
	int k = Index(T,V,2);
	printf("%d\n",k);

	printf("delete S sit 2-5\n");
	printf("origin S: "); StrTraverse(S);
	StrDelete(&S,2,5);
	printf("Now S: "); StrTraverse(S);

	printf("insert X into S(before sit 2) \n");
	StrInsert(&S,2,X);
	printf("Now S: "); StrTraverse(S);

	printf("concat S and X:\n");
	StrConcat(&Y,S,X);
	printf("Now Y: "); StrTraverse(Y);


	return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五月的天气

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值