这里的代码对应的是紫薇星上的数据结构(6)中的链串的代码,如果对您有需要也可使用,使用时请注明出处。
mian.c
#include <stdio.h>
#include <stdlib.h>
#include "SeqString.h"
#include "LinkedString.h"
void TestLinkedString();
int main()
{
TestLinkedString();
return 0;
}
void TestLinkedString(){
LString str1;
LString str2;
StrAssign_LinkedString(&str1, "testlinkedstr");
PrintLinkedString(&str1);
printf("\n复制链串:");
StrCopy_LinkedString(&str2, &str1);
PrintLinkedString(&str2);
LString str3;
StrAssign_LinkedString(&str3, "testlinkedstr");
printf("\n比较链串:%d\n", StrCompare_LinkedString(&str1, &str3));
printf("\n连接串:");
Concat_LinkedString(&str3, &str1, &str2);
PrintLinkedString(&str3);
printf("\n截取字符串");
SubString_LinkedString(&str3, str1, 2, 5);
PrintLinkedString(&str3);
printf("\nlink在str1中的位置:");
LString str4;
StrAssign_LinkedString(&str4, "link");
printf("\n\nstr1:");
PrintLinkedString(&str1);
printf("\tstr4:");
PrintLinkedString(&str4);
printf("\nstr4在str1中的位置:%d\n", Index_LinkedString(&str1, &str4, 1));
printf("\n从指定的位置删除字符:");
printf("删除前-");
PrintLinkedString(&str1);
StrDelete_LinkedString(&str1, 2, 5);
printf("\t删除后-");
PrintLinkedString(&str1);
printf("\n\n插入串:");
StrInsert_LinkedString(&str1, 4, &str4);
PrintLinkedString(&str1);
printf("\n\n替换:");
LString str5;
StrAssign_LinkedString(&str5, "link");
LString str6;
StrAssign_LinkedString(&str6, "HelloDataStrct");
Replace_LinkedString(&str1, str5, str6);
PrintLinkedString(&str1);
}
StatusLib.h
#ifndef STATUSLIB_H_INCLUDED
#define STATUSLIB_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
/**状态码*/
#define ERROR 0
#define OK 1
#define TRUE 1
#define FALSE 0
#define EQ 0 //相等
#define GT 1 //大于
#define LF -1 //小于
#ifndef _STATUS_H_ //如果系统中已经有了下列状态码的定义,就不再定义
#define OVERFLOW -2 //堆栈上溢,超过所能表示的最大正数
#define UNDERFLOW -3 //堆栈下溢,超过所能表示的最小负数
#endif // _STATUS_H_
typedef int Status; //自定义一个状态码识别类型
#endif // STATUSLIB_H_INCLUDED
LinkString.h
#ifndef LINKEDSTRING_H_INCLUDED
#define LINKEDSTRING_H_INCLUDED
#include "StatusLib.h"
#include <string.h>
#define BLOCK_SIZE 80 //定义块的大小,可自行修改
/** 块的定义 */
typedef struct block{
char ch[BLOCK_SIZE]; //块数据
struct block * next; //指向下一个块的指针
}Block;
/** 串的链式存储结构 */
typedef struct {
Block * head; //串的头指针
Block * tail; //串的尾指针
int length; //串的当前长度
}LString; //LinkedString的缩写
/** 初始化链串 */
void InitString_LinkedString(LString * str);
/** 为链串str赋值,值为字符串常量chars */
Status StrAssign_LinkedString(LString * str, char * chars);
/** 将链串srcStr中的内容复制到链串destStr中 */
Status StrCopy_LinkedString(LString * destStr, LString * srcStr);
/** 比较两个链串的大小,str1 == str2 返回0;str1 < str2 返回负数;str1 > str2 返回正数 */
Status StrCompare_LinkedString(LString * str1, LString * str2);
/** 连接两个链串,连接的结果以链串destStr返回 */
void Concat_LinkedString(LString * destStr, LString * str1, LString * str2);
/** 从pos位置(从1开始)处截取len长度的字符串到串destStr中 */
Status SubString_LinkedString(LString * destStr, LString str, int pos, int len);
/** 返回从pos位置开始的子串child在父串parent中的位置 */
int Index_LinkedString(LString * parent, LString * child, int pos);
/** 从pos位置处删除长度len */
Status StrDelete_LinkedString(LString * str, int pos, int len);
/** 向指定的位置插入串insertStr */
Status StrInsert_LinkedString(LString * str, int pos, LString * insertStr);
/** 将串str中的oldStr替换成newStr */
Status Replace_LinkedString(LString * str, LString oldStr, LString newStr);
/** 返回链串是否为空 */
Status IsEmpty_LinkedString(LString * str);
/** 清空链串 */
void ClearString_LinkedString(LString * str);
/** 打印链串 */
void PrintLinkedString(LString * str);
#endif // LINKEDSTRING_H_INCLUDED
LinkString.c
#include "LinkedString.h"
/** 初始化链串 */
void InitString_LinkedString(LString * str){
str->head = NULL;
str->tail = NULL;
str->length = 0;
}
/** 为链串str赋值,值为字符串常量chars */
Status StrAssign_LinkedString(LString * str, char * chars){
int len = strlen(chars);
if(!len) return ERROR;
InitString_LinkedString(str);
//计算出块的总数:假设长度96,那么就需要有1个块零16个字符
int block_count = (len + 1) / BLOCK_SIZE; //len+1是因为最后要赋值'\0'表示字符串的结束
//余下的字符总数
int surplus_count = (len + 1) % BLOCK_SIZE;
if(surplus_count > 0){
block_count++; //如果有余下的字符,就需要多一个块来存放
}
Block * block;
for(int i = 1; i <= block_count; i++){
block = (Block *)malloc(sizeof(Block));
if(!block) exit(OVERFLOW);
block->next = NULL;
//在每个块中复制对应的字符
int count = 0;
for(; count < BLOCK_SIZE && (count + (i - 1) * BLOCK_SIZE < len); count++){
//count为当前块要复制的字符个数
//(i - 1) * BLOCK_SIZE 为 第i个块之前的字符总数
block->ch[count] = chars[count + (i - 1) * BLOCK_SIZE]; //逐个字符复制
}
if(i == block_count){//最后一个块
block->ch[count] = '\0';
}
if(i == 1){//如果是第一个块,链串首尾指针都指向这个块
str->head = str->tail = block;
}else{
//如果不是第一个块,就需要连接这个块
str->tail->next = block; //当前链尾的next指向block
str->tail = block; //链尾再修改为block - 链表的常用操作
}
}
str->length = len;
return OK;
}
/** 将链串srcStr中的内容复制到链串destStr中 */
Status StrCopy_LinkedString(LString * destStr, LString * srcStr){
InitString_LinkedString(destStr);
for(Block * block = srcStr->head; block != NULL; block = block->next){
Block * newBlock = (Block *)malloc(sizeof(Block));
if(!newBlock) exit(OVERFLOW);
newBlock->next = NULL;
if(block == srcStr->head){//第一个块
destStr->head = destStr->tail = newBlock;
}else{
destStr->tail->next = newBlock;
destStr->tail = newBlock;
}
for(int i = 0; i < BLOCK_SIZE; i++){//逐个复制块中的字符
newBlock->ch[i] = block->ch[i];
}
}
destStr->length = srcStr->length;
return OK;
}
/** 比较两个链串的大小,str1 == str2 返回0;str1 < str2 返回负数;str1 > str2 返回正数 */
Status StrCompare_LinkedString(LString * str1, LString * str2){
Block * str1Head = str1->head;
Block * str2Head = str2->head;
while(str1Head && str2Head){
for(int i = 0; i < BLOCK_SIZE && str1Head->ch[i] != '\0' && str2Head->ch[i] != '\0' ; i++){
if(str1Head->ch[i] != str2Head->ch[i]){
return str1Head->ch[i] - str2Head->ch[i];
}
}
str1Head = str1Head->next;
str2Head = str2Head->next;
}
return str1->length - str2->length;
}
/** 连接两个链串,连接的结果以链串destStr返回 */
void Concat_LinkedString(LString * destStr, LString * str1, LString * str2){
int i, j, k, count;
InitString_LinkedString(destStr);
Block * str1Head = str1->head;
Block * str2Head = str2->head;
Block * destHead = destStr->head;
i = j = k = 0;
while(str1Head || str2Head){
if(!destHead){
destHead = (Block *)malloc(sizeof(Block));
if(!destHead) exit(OVERFLOW);
destHead->next = NULL;
if(!destStr->head){
destStr->head = destStr->tail = destHead;
}else{
destStr->tail->next = destHead;
destStr->tail = destHead;
}
}
if(str1Head){
while(str1Head && str1Head->ch[i]){
destHead->ch[i] = str1Head->ch[i];
i = (i + 1) % BLOCK_SIZE;
j = (j + 1) % BLOCK_SIZE;
if(!j || !(str1Head->ch[j])){
str1Head = str1Head->next;
}
if(!i){
destHead = destHead->next;
}
}
}else{
while(str2Head && str2Head->ch[k]){
destHead->ch[i] = str2Head->ch[k];
i = (i + 1) % BLOCK_SIZE;
k = (k + 1) % BLOCK_SIZE;
if(!k || !str2Head->ch[k]){
str2Head = str2Head->next;
}
if(!i){
destHead = destHead->next;
}
}
}
}
destStr->length = str1->length + str2->length;
count = (destStr->length - 1) % BLOCK_SIZE + 1;
if(count < BLOCK_SIZE){
destStr->tail->ch[count] = '\0';
}
}
/** 从pos位置(从1开始)处截取len长度的字符串到串destStr中 */
Status SubString_LinkedString(LString * destStr, LString str, int pos, int len){
if(IsEmpty_LinkedString(&str)) return ERROR;
if(pos < 1 || pos > str.length || len < 0 || pos + len - 1 > str.length){
return ERROR;
}
int i, j, k, count;
InitString_LinkedString(destStr);
Block * strHead = str.head;
for(count = 1; pos > count * BLOCK_SIZE; count++){
strHead = strHead->next; //指向第pos个元素
}
Block * destHead = destStr->head;
i = j = 0;
k = (pos % BLOCK_SIZE) - 1;
while(i < len){
if(!destHead){
destHead = (Block *)malloc(sizeof(Block));
if(!destHead) exit(OVERFLOW);
destHead->next = NULL;
if(!destStr->head){
destStr->head = destStr->tail = destHead;
}else{
destStr->tail->next = destHead;
destStr->tail = destHead;
}
}
while(i < len){
destHead->ch[j] = strHead->ch[k];
j = (j + 1) % BLOCK_SIZE;
k = (k + 1) % BLOCK_SIZE;
i++;
if(!k){
strHead = strHead->next;
}
if(!j){
destHead = destHead->next;
break;
}
}
}
destStr->length = len;
count = (destStr->length - 1) % BLOCK_SIZE + 1;
if(count < BLOCK_SIZE){
destStr->tail->ch[count] = '\0';
count++;
}
return OK;
}
/** 返回从pos位置开始的子串child在父串parent中的位置 */
int Index_LinkedString(LString * parent, LString * child, int pos){
LString subStr;
int i, pLen, cLen; //循环变量及父串、子串的长度
if(pos > 0 && pos <= parent->length){
pLen = parent->length;
cLen = child->length;
i = pos;
while(i + cLen - 1 <= pLen){
SubString_LinkedString(&subStr, *parent, i, cLen);
if(StrCompare_LinkedString(&subStr, child) != EQ){
i++;
}else{
return i;
}
}
}
return 0;
}
/** 从pos位置处删除长度len */
Status StrDelete_LinkedString(LString * str, int pos, int len){
if(pos < 1 || pos > str->length || len < 0 || pos + len - 1 > str->length){
return ERROR;
}
if(pos == 1 && len == str->length){
ClearString_LinkedString(str);
}
int first, last, count, i, j;
Block * firstBlock, * lastBlock;
first = pos;
last = pos + len - 1;
//让firstBlock指向first或pos所在块
for(count = 1, firstBlock = str->head; first > count * BLOCK_SIZE; count++, firstBlock = firstBlock->next);
//让lastBlock指向last所在块
for(lastBlock = firstBlock; last > count * BLOCK_SIZE; count++, lastBlock = lastBlock->next);
i = (first - 1) % BLOCK_SIZE;
j = (last - 1) % BLOCK_SIZE;
j = (j + 1) % BLOCK_SIZE;
if(!j){
lastBlock = lastBlock->next;
}
while(lastBlock && lastBlock->ch[j]){
firstBlock->ch[i] = lastBlock->ch[j];
i = (i + 1) % BLOCK_SIZE;
j = (j + 1) % BLOCK_SIZE;
if(!i){
firstBlock = firstBlock->next;
}
if(!j){
lastBlock = lastBlock->next;
}
}
str->length -= len;
for(count = 1, str->tail = str->head; str->length > count * BLOCK_SIZE; count++, str->tail = str->tail->next);
count = (str->length - 1) % BLOCK_SIZE + 1;
if(count < BLOCK_SIZE){
str->tail->ch[count] = '\0';
}
//释放内存
Block * block = str->tail->next;
while(block){
str->tail->next = block->next;
free(block);
block = str->tail->next;
}
return OK;
}
/** 向指定的位置插入串insertStr */
Status StrInsert_LinkedString(LString * str, int pos, LString * insertStr){
if(pos < 1 || pos > str->length + 1){
return ERROR;
}
/*声明变量*/
int i, j, k, count;
Block * tempHead, * strHead1, * strHead2, * insertStrHead;
LString * tempStr = (LString *)malloc(sizeof(LString));
/*初始化变量*/
InitString_LinkedString(tempStr);
tempHead = tempStr->head;
strHead1 = (*str).head;
strHead2 = NULL;
insertStrHead = insertStr->head;
i = j = k = 0;
count = 1;
while(strHead1 || strHead2 || insertStrHead){
if(!tempHead){
tempHead = (Block *)malloc(sizeof(Block));
if(!tempHead) exit(OVERFLOW);
tempHead->next = NULL;
if(!tempStr->head){
tempStr->head = tempStr->tail = tempHead;
}else{
tempStr->tail->next = tempHead;
tempStr->tail = tempHead;
}
}
if(strHead1){
while(strHead1 && count < pos){
tempHead->ch[i] = strHead1->ch[j];
i = (i + 1) % BLOCK_SIZE;
j = (j + 1) % BLOCK_SIZE;
count++;
if(!j || !(strHead1->ch[j])){
strHead1 = strHead1->next;
}
if(!i){
tempHead = tempHead->next;
break;
}
}
if(count == pos){
strHead2 = strHead1;
strHead1 = NULL;
}
}else if(insertStrHead){
while(insertStrHead && insertStrHead->ch[k]){
tempHead->ch[i] = insertStrHead->ch[k];
i = (i + 1) % BLOCK_SIZE;
k = (k + 1) % BLOCK_SIZE;
if(!k || !insertStrHead->ch[k]){
insertStrHead = insertStrHead->next;
}
if(!i){
tempHead = tempHead->next;
break;
}
}
}else{
while(strHead2 && strHead2->ch[j]){
tempHead->ch[i] = strHead2->ch[j];
i = (i + 1) % BLOCK_SIZE;
j = (j + 1) % BLOCK_SIZE;
if(!j || !strHead2->ch[j]){
strHead2 = strHead2->next;
}
if(!i){
tempHead = tempHead->next;
break;
}
}
}
}
tempStr->length = str->length + insertStr->length;
count = (tempStr->length - 1) % BLOCK_SIZE + 1;
if(count < BLOCK_SIZE){
tempStr->tail->ch[count] = '\0';
}
ClearString_LinkedString(str);
str->length = tempStr->length;
str->head = tempStr->head;
str->tail = tempStr->tail;
free(tempStr);
return OK;
}
/** 将串str中的oldStr替换成newStr */
Status Replace_LinkedString(LString * str, LString oldStr, LString newStr){
if(IsEmpty_LinkedString(str)) return ERROR;
int pos = Index_LinkedString(str, &oldStr, 1);
while(pos){
StrDelete_LinkedString(str, pos, oldStr.length);
StrInsert_LinkedString(str, pos, &newStr);
pos += newStr.length;
pos = Index_LinkedString(str, &oldStr, pos);
}
return OK;
}
/** 返回链串是否为空 */
Status IsEmpty_LinkedString(LString * str){
if(str->head == NULL || str->tail == NULL || str->length == 0){
return TRUE;
}
return FALSE;
}
/** 清空链串 */
void ClearString_LinkedString(LString * str){
Block * block = str->head;
while(block){
Block * next = block->next;
free(block);
block = next;
}
str->head = str->tail = NULL;
str->length = 0;
}
/** 打印链串 */
void PrintLinkedString(LString * str){
Block * block = str->head;
if(block == NULL || str->tail == NULL || str->length == 0){
printf("链串为空,无法打印!\n");
return;
}
int i = 0;
while(block){//经典的链表式遍历
if(block->ch){//块不为空就打印
while(block->ch[i] != '\0' && i < BLOCK_SIZE){
printf("%c", block->ch[i++]);
}
i = 0;
}
block = block->next;
}
}
代码主要是将数据结构中串的链式存储结构用C语言表示出来,有感兴趣的同学可以看一下我的数据结构系列:紫薇星上的数据结构。