紫薇星上的数据结构——链串代码

这里的代码对应的是紫薇星上的数据结构(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语言表示出来,有感兴趣的同学可以看一下我的数据结构系列:紫薇星上的数据结构。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值