![fdce4769a92901df7956674329c7ab62.png](https://img-blog.csdnimg.cn/img_convert/fdce4769a92901df7956674329c7ab62.png)
相关定义
- 与线性表的链式储存结构类似,也可以用链表储存串值。但由于串的数据元素是字符,而一个节点可以储存一个字符,也可以储存多个字符,因此存在“节点大小问题”(节点理解为块)。
- 为便于进行操作,在串的块链表示中,除头指针外还附设一个尾指针,指示链表中最后一个节点,并给出当前串的长度。
- 引入存储密度:存储密度=串值所占储存位/实际所占储存位
在链式存储结构中,节点的大小选择与顺序存储结构的格式选择一样重要,直接影响着串处理的效率。存储密度小(如节点大小为一)时,运算处理方便,但占用储存空间大,会影响处理效率。 - 链式存储优劣
优势对于某些操作,如连接操作更方便劣势不灵活,占用储存量大且操作复杂
块链储存表示和相关操作实现
- 串的块链表示
#define BLANK '#'//链表的最后一个节点不一定全被串值占满,用#补全
#define CHUNKSIZE 4//块(节点)大小
typedef struct Chunk{
char ch[CHUNKSIZE];
Chunk *next;
}Chunk;
typedef struct{
Chunk *head,*tail;
int curlen;
}LString;
- 相关函数表示
Status InitString(LString *S);
Status StrAssign(LString *S, char *chars);
Status StrCopy(LString *S, LString T);
Status StrEmpty(LString S);
int StrCompare(LString S, LString T);
Status ClearString(LString *S);
Status SubString(LString *Sub, LString S, int pos, int len);
int Index(LString S, LString T, int pos);
void Zip(LString *S); //压缩串
Status StrInsert(LString *S, int pos, LString T);
Status StrDelete(LString *S, int pos, int len);
Status Replace(LString *S, LString T, LString V);
void TraverseStr(LString S);
- 初始化
Status InitString(LString *S){
S->head=NULL;
S->tail=NULL;
S->curlen=0;
return OK;
}
- 赋值
Status StrAssign(LString *S, char *chars){
int len,blockNum;
Chunk *p,*temp;
len=strlen(chars);
if(!len||strchr(chars,BLANK)){
return ERROR;
}
S->curlen=len;//确定串的长度
blockNum=len/CHUNKSIZE;
if(len%CHUNKSIZE){
blockNum++;
}//确定串的块数
for(int i=0;i<blockNum;i++){
p=(Chunk*)malloc(sizeof(Chunk));
if(!p){
return OVERFLOW;
}
if(S->head=NULL){
S->head=p=temp;
}
else{
temp->next=p;
temp=p;
}
for(int j=0;i<CHUNKSIZE&&chars[j];j++){
*(p->ch+j)=chars[j];
if(!chars[j]){
S->tail=p;
S->tail->next=NULL;
for(;j<CHUNKSIZE;j++){
*(p->ch+j)=BLANK;
}
}
}
}
return OK;
}
- 复制
Status StrCopy(LString *S, LString T){
Chunk *h=T.head,*p;
if(!h){
return ERROR;
}
S->head=(Chunk*)malloc(sizeof(Chunk));
if(!S->head){
return OVERFLOW;
}
*S->head=*h;
h=h->next;
p=S->head;
if(h){
p=(Chunk*)malloc(sizeof(Chunk));
p=p->next;
*p=*h;
h=h->next;
}
S->tail=p;
p->next=NULL;
return OK;
}
- 检查是否为空串
Status StrEmpty(LString S){
if(!S.curlen){
return TRUE;
}
else{
return FALSE;
}
}
- 比较两个串大小
int StrCompare(LString S, LString T){
Chunk *ps=S.head,*pt=S.tail;
while(ps&&pt){
for(int i=0;i<CHUNKSIZE;i++){
if(*(ps->ch+i)!=*(pt->ch+i)){
if(*(ps->ch+i)=BLANK){
return -1;
}
else if(*(pt->ch+i)=BLANK){
return 1;
}
else{
return *(ps->ch+i)-*(pt->ch+i);
}
}
}
ps=ps->next;
pt=pt->next;
}
return ps-pt;
}
- 清空串
Status ClearString(LString *S){
Chunk *p,*temp;
if(!S->head){
return ERROR;
}
p=S->head;
while(p){
temp=p->next;
free(p);
p=temp;
}
S->head=NULL;
S->tail=NULL;
S->curlen=0;
return OK;
}
- 遍历串
void TraverseStr(LString S){
Chunk *p;
p=S.head;
while(p){
for(int i=0;i<CHUNKSIZE;i++){
if(*(p->ch)!=BLANK){
printf("%c",*(p->ch));
}
}
p=p->next;
}
printf("n");
}
关注公众号,让我们携手共进
![3431d82835cc0b05cfb1fe9b33e0a0b4.png](https://img-blog.csdnimg.cn/img_convert/3431d82835cc0b05cfb1fe9b33e0a0b4.png)