#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#define CHUNKSIZE 8 // 块大小
char blank = '#';
typedef struct Chunk
{
char ch[CHUNKSIZE]; //块的数据域
struct Chunk *next; //块的指针域
}Chunk;
typedef struct
{
Chunk *head, // 串的头指针
*tail; // 串的尾指针
int curlen; // 串的当前长度
}LString;
// 返回S的元素个数,称为串的长度
int StrLength(LString S)
{
return S.curlen;
}
int StrAssign(LString *T,char *chars)
{
int i,j,k,l;
Chunk *p,*q;
i=strlen(chars); // i为串的长度
if(!i||strchr(chars,blank)) // 串长为0或chars中包含填补空余的字符
return 0;
(*T).curlen=i;
j=i/CHUNKSIZE; // j为块链的结点数,块的个数
if(i%CHUNKSIZE) //不足一个块的,当成一个块即块数加1
j++;
for(k=0;k<j;k++)
{
p=(Chunk*)malloc(sizeof(Chunk));
if(!p)
return 0;
if(k==0) // 第一个链块
(*T).head=q=p;
else
{
q->next=p;
q=p;
}
for(l=0;l<CHUNKSIZE&&*chars;l++)
*(q->ch+l)=*chars++;
if(!*chars) // 最后一个链块
{
(*T).tail=q;
q->next=NULL;
for(;l<CHUNKSIZE;l++)
// 用填补空余的字符(blank=‘#’)填满链表
*(q->ch+l)=blank;
}
}
return 1;
}
// 由串S复制得串T(连填补空余的字符一块拷贝)
int StrCopy(LString *T,LString S)
{
Chunk *h=S.head,*p,*q;
(*T).curlen=S.curlen;
if(h)
{
p=(*T).head=(Chunk*)malloc(sizeof(Chunk));
*p=*h; // 复制1个结点
h=h->next;
while(h) //没到队尾,继续复制块
{
q=p;
p=(Chunk*)malloc(sizeof(Chunk));
q->next=p;
*p=*h;
h=h->next;
}
p->next=NULL;
(*T).tail=p;
return 1;
}
else
return 0;
}
// 将S清为空串
int ClearString(LString *S)
{
Chunk *p,*q;
//释放空间,并置空
p=(*S).head;
while(p)
{
q=p->next;
free(p);
p=q;
}
(*S).head=NULL;
(*S).tail=NULL;
(*S).curlen=0;
return 1;
}
void Zip(LString *S)
{
int j,n=0;
Chunk *h=(*S).head;
char *q;
q=(char*)malloc(((*S).curlen+1)*sizeof(char));
while(h) // 将LString类型的字符串转换为char[]类型的字符串
{
for(j=0; j<CHUNKSIZE; j++)
if(*(h->ch+j)!=blank)
{
*(q+n)=*(h->ch+j);
n++;
}
h=h->next; //h指向下一个块
}
*(q+n)=0; // 串结束符
ClearString(S); // 清空S
StrAssign(S,q); // 重新生成S
}
// 在串S的第pos个字符之前插入串T
int StrInsert(LString *S,int pos,LString T)
{
int i,j,k;
Chunk *p,*q;
LString t;
if(pos<1||pos>StrLength(*S)+1) // pos超出范围
return 0;
StrCopy(&t,T); // 复制T为t
Zip(S); // 去掉S中多余的填补空余的字符
i=(pos-1)/CHUNKSIZE; // 到达插入点要移动的块数
j=(pos-1)%CHUNKSIZE; // 到达插入点在最后一块上要移动的字符数
p=(*S).head;
if(pos==1) // 插在S串前
{
t.tail->next=(*S).head;
(*S).head=t.head;
}
else if(j==0) // 插在块之间
{
for(k=1;k<i;k++)
p=p->next; // p指向插入点的左块
q=p->next; // q指向插入点的右块
p->next=t.head; // 插入t
t.tail->next=q;
if(q==NULL) // 插在S串后
(*S).tail=t.tail; // 改变尾指针
}
else // 插在一块内的两个字符之间
{
for(k=1;k<=i;k++)
p=p->next; // p指向插入点所在块
q=(Chunk*)malloc(sizeof(Chunk)); // 生成新块
for(i=0;i<j;i++)
*(q->ch+i)=blank; // 块q的前j个字符为填补空余的字符
for(i=j;i<CHUNKSIZE;i++)
{
*(q->ch+i)=*(p->ch+i); // 复制插入点后的字符到q
*(p->ch+i)=blank; // p的该字符为填补空余的字符
}
q->next=p->next;
p->next=t.head;
t.tail->next=q;
}
(*S).curlen+=t.curlen;
Zip(S); //进行压缩
return 1;
}
// 输出字符串T。
void StrPrint(LString T)
{
int i=0,j;
Chunk *h;
h=T.head;
while(i<T.curlen)
{
for(j=0;j<CHUNKSIZE;j++)
if(*(h->ch+j)!=blank) // 不是填补空余的字符
{
printf("%c",*(h->ch+j));
i++;
}
h=h->next;
}
printf("\n");
}
int main()
{
int k;
int pos,len;
char str1[100],str2[100];
printf("\n请输入第一个长度不超过100个字符的字符串(不包含字符#):");
gets(str1);
LString t1,t2;
// InitString(&t1);
// InitString(&t2);
StrAssign(&t1,str1);
StrPrint(t1);
printf("\n请输入第二个长度不超过100个字符的字符串(不包含字符#):");
gets(str2);
StrAssign(&t2,str2);
StrPrint(t2);
printf("\n请输入要插入的位置pos= ");
scanf("%d",&pos);
StrInsert(&t1,pos,t2);
printf("\n插入后的字符串为:");
StrPrint(t1);
getchar();
return 0;
}
字符串的块链实现
最新推荐文章于 2022-05-21 13:44:10 发布