串的链块表示,操作复杂,不实用
串的链块表示
#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define ERROR 0
#define SRUE 1
#define FALSE 0
typedef int Status;
#define CHUNKSIZE 5
typedef struct Chunk
{
char ch[CHUNKSIZE];
struct Chunk *next;
}Chunk;
typedef struct
{
Chunk * head, *tail; /* 串的头和尾指针*/
int curlen; /* 串的当前长度 */
}LString;
/* 生成一个其值等于chars的串S */
Status StrAssign(LString *S, char * chars)
{
if(!S->head) { /* 头结点不存在 */
S->head = (Chunk *)malloc(sizeof(Chunk)); /* 创建头结点 */
S->tail = S->head;
S->head->next = NULL;
}
if(!S->head->next) {
S->head->next = (Chunk *)malloc(sizeof(Chunk)); /* 创建第一个结点 */
S->tail = S->head->next; /* 尾指针指向第一个结点 */
S->head->next->next = NULL;
S->curlen = 0; /* 字符元素清零 */
}
Chunk * p = S->head->next; /* 指向第一个结点 */
int chunklen = 0;
for(int i=0; chars[i] != '\0'; i++,S->curlen++) {
p->ch[chunklen++] = chars[i];
if(chunklen % CHUNKSIZE == 0) { /* 数组到达末尾,则新开结点 */
Chunk * q = (Chunk *)malloc(sizeof(Chunk));
q->next = p->next;
p->next = q; /* 插入到末尾 */
S->tail = q; /* 尾指针指向末尾结点 */
p = q; /* 指向新插入点 */
chunklen = 0;
}
}
while(chunklen < CHUNKSIZE)
p->ch[chunklen++] = '#'; /* 最后剩余空间填满 # */
return OK;
}
/* 返回串S的元素个数 */
int StrLength(LString S)
{
return S.curlen;
}
/* 清空字符串,并释放S所占的空间 */
Status ClearString(LString *S)
{
int index = 0;
while(S->head) {
S->tail = S->head->next;
free(S->head);
index++;
S->head = S->tail;
}
printf("free %d\n",index);
S->curlen = 0;
return OK;
}
/* 比较S,T,若S>T返回值>0 ,若S=T,返回0,若S<T,返回值<0 */
int StrCompare(LString S, LString T)
{
if(!S.head->next || !T.head->next)
return 0;
int chunklen = 0;
Chunk * pS = S.head->next; /* 指向第一个结点 */
Chunk * pT = T.head->next;
for(int i=0; i<S.curlen && i<S.curlen; i++) {
if(pS->ch[chunklen] != pT->ch[chunklen])
return pS->ch[chunklen] - pT->ch[chunklen];
chunklen++;
if(chunklen % CHUNKSIZE == 0) {
pS = pS->next;
pT = pT->next;
chunklen = 0;
}
}
return S.curlen - T.curlen;
}
/* 用T返回由S1,S2拼接成的串 */
Status Concat(LString *T, LString S1, LString S2)
{
// ... 未完成,这链块拼接真的不是那么简单,纠结在于最后的结点并不匹配,
// 直接链表指指针的方式根本无法完成嘛
if(!T->head) { /* 头结点不存在 */
T->head = (Chunk *)malloc(sizeof(Chunk)); /* 创建头结点 */
T->tail = T->head;
T->head->next = NULL;
}
T->head->next = S1.head->next;
S1.tail->next = S2.head->next;
T->curlen = S1.curlen + S2.curlen;
return OK;
}
void PrintStr(LString S)
{
if(!S.head) return;
Chunk * p = S.head->next; /* 指向第一个结点 */
for(int chunklen=0,i=0; p && i<S.curlen; i++) {
printf("%c",p->ch[chunklen++]);
if(chunklen % CHUNKSIZE == 0) { /* 当前结点已经遍历,指向下一个结点 */
p = p->next;
chunklen = 0;
}
}
printf("\n");
}
int main()
{
LString S1,S2,T;
S1.head = NULL;
S2.head = NULL;
T.head = NULL;
StrAssign(&S1,"Hello World");
StrAssign(&S2,"This is a hello world");
PrintStr(S1);
PrintStr(S2);
printf("compare %d\n",StrCompare(S1,S2));
Concat(&T,S1,S2);
PrintStr(T);
ClearString(&T);
ClearString(&S1);
ClearString(&S2);
printf("OK");
}
可以看输出结果
最后一个结点填充#号,而拼接的时候如果只是把链表指向重新定向一下是不行的,没法去掉最后一个结点问题。而如果用一个一个复制的方法,那还不如用数组。强行改造也不行,一样效率低。