请相信我,我可以带你更简单的了解代码,而不是只丢下好些代码让你自己去理解然后放弃!
串
概念:字符串的简称,属于线性表,比较特殊,因为它的每一个元素都必须是字符。
基本形式:将输入法换为英文输入,然后打出一对双引号,就像如下:
————“abcdefg” ,我在里面随便加上了一些字母或什么的,就是不空的字符串,当然也可以什么都不加,那么就是空的字符串.
可以发现,当我输入一些东西到("")里面后就相当于已经给字符串初始化了,也就是顺序已经被我弄好了,个数也是。
数组
以前的定义方式,例如:char ch[10];
上面就是一个字符串,长度为10,下标从0到9,总共10个
如果我现在向其中存入一些字母,那么这里面就是储存了字符串了!而且还会很人性化的自动帮我们在字母最后面加上字符串应该带有的结束标志:’\0’,如果在ch[10]中只储存了几个字符,没有满10个,那么余下的位置全部会补上’\0’.
一些术语:
位置与长度:假设现在有字符串"abcdefg",那么a的位置是0,g的位置是6(也就是字符在串中的序号字符在串中的位置),字符串的长度是7(长度可以用函数strlen()测,头文件是string.h)
子串与主串:串中任意个连续的字符组成的子序列称为子串,包含子串的叫做主串,子串在主串中的位置就不一样,是从1开始。
1)
串的定长存储
其实很容易理解,就一种静态结构类型,数组的样子。
#defien MAXSIZE 50
typedef struct{
char ch[MAXSIZE+1];//加一的原因是希望50真的是字符串的长度,留多一个空间来放结束标识'\0'
int length;
}SString;
串的插入:(已知:数组总长度为MAXSIZE,已经有一个字符串s在数组中了,现在还想插入一个一个字符串t ,插入位置就定为 pos)
思维:竟然我要将t插入s中,且插入位置的下标为pos,那么肯定字符串s被我们拆断了,后面一截肯定是要加在字符串t之后的,那么问题来了,这被截下的一端还能完整的放入数组中吗?
能时:那么肯定很好!不能时,又得分了,因为我们只是知道被截下的那一段不能放入数组中,但不知道字符串t能不能放入完全呢?所以有三种情况需要分析!
插入算法实现
如下:
int str_insert(SString *s,SString t,int pos)
{
int i;
if(pos<0 || pos>s->length)//首先需要判断的是pos的位置是否合法性
//提一嘴,字符串s的长度可以用strlen()函数测得
return 0;
if(s->length+t.length<=MAXSIZE)//第一种情况,插入后没有满,很理想的情况
//请见下面的图解一
for(i=s->length+t.length-1; i>=t.length; i--)
s->ch[i]=s->ch[i-t.length];//先将被截断的字符串于后排补上
for(i=0; i<t.length; i++)//将字符串t放入该放的位置
s->ch[i+pos]=t.ch[i];
s->length=s->length+t.length;//将字符串s的长度更新
//提一嘴,s是指针,所以用的是->引用,而t只是一个正常的结构体变量,所以只能用.引用。
else if(pos+t.length<=MAXSIZE)//此种情况为能保留完整的t,但没法保留完整的被截断那一段
{
//请看图解二
for(i=MAXSIZE-1; i>=t.length+pos; i--)//先固定最大长度,再用减的原理去实现
s->ch[i]=s->ch[i-t.length];
for(i=0; i<t.length; i++)//将该插入的t插入进去
s->ch[i+pos]=t.ch[i];
s->length=MAXSIZE;//满了啦!
}
else//此种情况就是字符串t也放不完,能放多少就多少
{
//请看图解三
for(i=0; i<MAXSIZE; i++){
s->ch[i+pos]=t.ch[i];
s->length=MAXSIZE;
}
return 1;
}
}
图解一:
图解二:
图解三:
删除算法实现
int str_delete(SString *s,int pos,int len)//直接就是将删除剩余的那部分接上就是了
{
//请看图解四
int i;
if(pos<0 || pos>s->length; i++)//先判断删除位置的合法性
return 0;
for(i=pos+len; i<s->length; ++i)
s->ch[i-len]=s->ch[i];//i-len兜兜转转又回到pos位置
s->length=s->length-len;//长度更新
return 1;
}
图解四:
2)
串的堆存储
自然说到堆栈,能不想到申请动态空间吗?
用到的两个函数
- malloc() 作用:申请动态空间。
- free() 作用:释放不再需要的空间。
typedef struct {
char *ch;//
int length;
}SString,S;
S=(SString)malloc(sizeof(SString));
S->ch[0]、S->ch[1]等,充分证明ch不是简单的用作指针指向的,而是可以转变为数组的功能.其中的ch就是首地址。
3)
串的块链存储
引入了存储密度这个概念:
#define CHUNKSIZE 100
typedef struct Chunk_link{
{
char ch[CHUNKSIZE];
struct Chunk_link *next;//自引用
}Chunk;
typedef struct{
Chunk *head,*tail;//增加了头指针和尾指针
int length;//负责记录长度
}CString;