数据结构》严蔚敏 串的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;
}