相关定义
- 与线性表的链式储存结构类似,也可以用链表储存串值。但由于串的数据元素是字符,而一个节点可以储存一个字符,也可以储存多个字符,因此存在“节点大小问题”(节点理解为块)。
- 为便于进行操作,在串的块链表示中,除头指针外还附设一个尾指针,指示链表中最后一个节点,并给出当前串的长度。
- 引入存储密度:存储密度=串值所占储存位/实际所占储存位
在链式存储结构中,节点的大小选择与顺序存储结构的格式选择一样重要,直接影响着串处理的效率。存储密度小(如节点大小为一)时,运算处理方便,但占用储存空间大,会影响处理效率。
- 链式存储优劣
优势 |
对于某些操作,如连接操作更方便 |
劣势 |
不灵活,占用储存量大且操作复杂 |
块链储存表示和相关操作实现
#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");
}
关注公众号,让我们携手共进
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。