由于串的特殊性(每个元素只有一个字符),在具体实现时,每个结点既可以存放一个字符,也可以存放多个字符。每个结点称为块,整个链表称为链块结构。
typedef struct StringNode
{
char ch[3];
struct StringNode *next;
}
存储密度低:
typedef struct StringNode
{
char ch;//每个结点有一个字符
struct StringNode *next;//指针占据3B
}
1.创建块链
//生成一个其值等于chars的串T(要求chars中不包含填补空余的字符)
void List_BLString(BLString &T,char *chars)
{
int i;//用来表示串chars的长度
i = strlen(chars);
if(i == 0 || strchr(chars,blank))//strchr表示在字符串chars中查找blank.如果字符串为0或者包含blank不符合条件
exit(-1);
T.length = i;
int j;//j表示块链的长度
j = i/BlockSize;//向下取整
if(i%BlockSize != 0)
j = j+1;
int k;
int n = *(chars+i-1);//表示的是字符串最后一个元素的地址
for(k = 0; k <= j; ++k)
{
BString *p = (BString *)malloc(sizeof(BString));
if(p == NULL)
{
printf("动态内存分配失败,结束程序!\n");
exit(-1);
}
//使用尾插法来创建块链
if(k == 0)
{
T.Head = p;
T.Tail = p;
T.Tail->next = NULL;
}
if(k != 0)
{
T.Tail->next = p;
p->next = NULL;
T.Tail = p;
}
for(int m = 0; m < BlockSize; ++m)
{
*(p->ch+m) = *chars++;//结束某一块循环之后p就变成指向另一个块的地址,所以该循环仍然成立
if(n == *(chars-1) && m < BlockSize)//因为是*chars++,所以达到字符串最后一个元素地址之后还会加1,所以条件应该是n == *(chars-1),此时正好两个都是字符串的最后一个元素的地址
{
for(m = m+1; m < BlockSize; ++m)
{
*(p->ch+m) = blank;
}
}
}
}
}
2.遍历输出
//遍历输出
void BLStringprint(BLString &T)
{
if(T.length == 0)
printf("串为空!\n");
else
{
BString *p = T.Head;
int i = 0;
while(i < T.length)
{
for(int j = 0; j < BlockSize; ++j)
{
if(*(p->ch+j) != blank)
{
printf("%c",*(p->ch+j));
i++;
}
}
p = p->next;
}
}
}
3.运行结果:
这两个函数运行的完整代码
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
#define BlockSize 4//定义块的大小
//定义块链中块的结构体
typedef struct BString
{
char ch[BlockSize];//块中的数据域
BString *next;
}BString;
//定义块链
typedef struct BLString
{
BString *Head,*Tail;//块链的头指针与尾指针
int length;//当前串的长度
}BLString;
char blank = '#';
//函数说明
void InitBLString(BLString &T);
void List_BLString(BLString &T,char *chars);
void BLStringprint(BLString &T);
int main(void)
{
BLString L;
InitBLString(L);
List_BLString(L,"abcdefghijklmn");
BLStringprint(L);
return 0;
}
//初始化块链
void InitBLString(BLString &T)
{
T.Head = NULL;
T.Tail = NULL;
T.length = 0;
}
//生成一个其值等于chars的串T(要求chars中不包含填补空余的字符)
void List_BLString(BLString &T,char *chars)
{
int i;//用来表示串chars的长度
i = strlen(chars);
if(i == 0 || strchr(chars,blank))//strchr表示在字符串chars中查找blank.如果字符串为0或者包含blank不符合条件
exit(-1);
T.length = i;
int j;//j表示块链的长度
j = i/BlockSize;//向下取整
if(i%BlockSize != 0)
j = j+1;
int k;
int n = *(chars+i-1);//表示的是字符串最后一个元素的地址
for(k = 0; k <= j; ++k)
{
BString *p = (BString *)malloc(sizeof(BString));
if(p == NULL)
{
printf("动态内存分配失败,结束程序!\n");
exit(-1);
}
//使用尾插法来创建块链
if(k == 0)
{
T.Head = p;
T.Tail = p;
T.Tail->next = NULL;
}
if(k != 0)
{
T.Tail->next = p;
p->next = NULL;
T.Tail = p;
}
for(int m = 0; m < BlockSize; ++m)
{
*(p->ch+m) = *chars++;//结束某一块循环之后p就变成指向另一个块的地址,所以该循环仍然成立
if(n == *(chars-1) && m < BlockSize)//因为是*chars++,所以达到字符串最后一个元素地址之后还会加1,所以条件应该是n == *(chars-1),此时正好两个都是字符串的最后一个元素的地址
{
for(m = m+1; m < BlockSize; ++m)
{
*(p->ch+m) = blank;
}
}
}
}
}
//遍历输出
void BLStringprint(BLString &T)
{
if(T.length == 0)
printf("串为空!\n");
else
{
BString *p = T.Head;
int i = 0;
while(i < T.length)
{
for(int j = 0; j < BlockSize; ++j)
{
if(*(p->ch+j) != blank)
{
printf("%c",*(p->ch+j));
i++;
}
}
p = p->next;
}
}
}