数据结构之“串”

3 篇文章 0 订阅
1 篇文章 0 订阅

字符串一般简称为串,在我们的编程中使用非常广泛。

一、串类型的定义
串(string)(或字符串)是由零个或过个字符组成的有限序列。
1.基本概念
串的长度:串中字符的数目
空串:零个字符的串
空格串:串中只有一个空格字符的串
子串:串中任意个连续的字符组成的子序列
二、串的实现
1.串的抽象数据类型
这里介绍的顺序存储的串,这个比较容易理解。下面在String.h头文件中给出串的定义:
#ifndef STRING_H_
#define STRING_H_
#define SIZE 10         //最大串长

typedef struct String
{
    char elem[SIZE];    //存放串的数组
    int length;         //有效串长
}String;

void StrAssign(String *s, const char *chars);   //串赋值
void StrCpy(String *dest, const String *src);   //串拷贝
bool IsEmpty(const String *s);  //判断串是否为空
void Clear(String *s);          //清空串
int  GetLength(const String *s);    //获取串的长度
bool SubString(String *sub, const String *s, int pos, int len);//获取子串
int  BF(const String *s, const String *sub, int pos);//串匹配
bool Replace(String *s, const String *t, const String *v, int pos);//用v替换从pos开始的t
bool ReplaceAll(String *s, const String *t, const String *v);//全部替换
bool Insert(String *s, int pos, const String *t);//在pos位置插入串t
bool DeletePos(String *s, int pos, int len);//删除pos位置后的len个字符
bool Delete(String *s, int pos, String *t);//删除串s中pos位置后的串t
void Show(const String *s); //打印串s
void Detroy(String *s);     //销毁串s
#endif
2.串的操作
在String.c文件中给出串操作的代码实现:
#include <stdio.h>
#include "String.h"
#include <string.h>

int main(void)
{
    String str;
    StrAssign(&str, "hellowlor");
    Show(&str);
    String str1;
    StrAssign(&str1, "lo");
    //Delete(&str, 0, &str1);
    //Show(&str);
    String str2;
    StrAssign(&str2, "lo");
    ReplaceAll(&str, &str1, &str2);
    Show(&str);
    //String str1;
    //StrAssign(&str1, "wo");
    //Show(&str1);
    //int pos = BF(&str, &str1, 0);
    //printf("%d\n", pos);

    //Insert(&str, 3, &str1);
    //Show(&str);
    //DeletePos(&str, 8, 3);
    //Show(&str);
    return 0;
}

//串赋值,将常量串chars赋给s
void StrAssign(String *s, const char *chars)
{
    if (NULL == s || chars == NULL)
    {
        return;
    }
    int len = strlen(chars);
    if (len > SIZE)
    {
        return;
    }
    for (int i = 0; i < len; ++i)
    {
        s->elem[i] = chars[i];
    }
    s->length = len;
}

//串拷贝,将串src中的内容拷贝到dest中
void StrCpy(String *dest, const String *src)
{
    if (NULL == dest || NULL == src)
    {
        return;
    }
    int len = GetLength(src);

    for (int i = 0; i < len; ++i)
    {
        dest->elem[i] = src->elem[i];
    }
    dest->length = len;
}

//判断串是否为空
bool IsEmpty(const String *s)
{
    return s->length == 0;
}

//清空串,因为这里是顺序存储,所以直接将有效串长置为0即可
void Clear(String *s)
{
    s->length = 0;
}

//获取有效串长
int GetLength(const String *s)
{
    return s->length;
}

//从主串spos位置后去len个字符组成子串并赋值给sub
bool SubString(String *sub, const String *s, int pos, int len)
{
    if (pos < 0 || len < 0 || (pos + len > SIZE))
    {
        return false;
    }
    for (int i = 0; i < len; ++i)
    {
        sub->elem[i] = s->elem[pos + i];
    }
    sub->length = len;
    return true;
}

//男朋友匹配算法,从pos位置开始在s中查找第一个sub串的位置
int BF(const String *s, const String *sub, int pos)
{
    if (NULL == s || NULL == sub || pos < 0 || pos >= s->length)
    {
        return -1;
    }
    int i, j;
    for (i = pos; i < s->length; ++i) //i指向主串中匹配的起始位置
    {
        for (j = 0; j < sub->length; ++j)
        {
            if (s->elem[i + j] != sub->elem[j])
            {
                break;
            }       
        }
        //说明上面的for循环执行完以后已经在主串中找到完全匹配的子串
        if (j == sub->length)   
        {
            return i;
        }
    }
    return -1;
}

//用v替换主串s中从pos位置开始的串t
bool Replace(String *s, const String *t, const String *v, int pos)
{
    int iPos = BF(s, t, pos);   //先在s中找到待替换子串的位置
    if (iPos == -1)
    {
        return false;
    }
    //先删t,再插入v
    Delete(s, iPos, (String*)t);    
    Insert(s, iPos, v);

    return true;
}

//用v替换主串s中的所有子串t
bool ReplaceAll(String *s, const String *t, const String *v)
{
    int iPos = BF(s, t, 0);
    if (iPos == -1)
    {
        return false;
    }
    while (iPos != -1)
    {
        Delete(s, iPos, (String*)t);
        Insert(s, iPos, v);
        //这里之所以要加上v->length,就是防止v和t相等的情况下造成的死循环
        iPos = BF(s, t, iPos + v->length); 
    }
    //先删t,再插入v

    return true;
}

//在主串s中的pos位置插入子串t
bool Insert(String *s, int pos, const String *t)//在pos位置插入t
{
    if (pos < 0 || pos >= SIZE)
    {
        return false;
    }
    //如果待插入的子串的串长和主串的串长加起来超过了最大长度,则依次挤出超出的字符
    if (s->length + t->length > SIZE)//
    {
        for (int i = s->length - t->length + 1; i >= pos; --i) 
        {
            s->elem[i + t->length] = s->elem[i];
        }
    }
    else
    {
        for (int i = s->length - 1; i >= pos; --i)  //向后挪t->length个位置
        {
            s->elem[i + t->length] = s->elem[i];
        }
    }
    for (int i = 0; i < t->length; ++i)
    {
        s->elem[pos + i] = t->elem[i];
    }
    //更新插入子串后的主串串长
    s->length = s->length + t->length > SIZE ? SIZE : s->length + t->length;
    return true;
}

//删除主串s中从pos位置开始的len个字符
bool DeletePos(String *s, int pos, int len)
{
    if (pos < 0 || pos >= SIZE || pos + len > s->length)
    {
        return false;
    }
    for (int i = pos + len; i <= s->length; ++i)
    {
        s->elem[i - len] = s->elem[i];
    }
    s->length -= len;
    return true;
}

//删除主串s中从pos位置后的子串t
bool Delete(String *s, int pos, String *t)
{
    int index = BF(s, t, pos);
    if (index < 0)
    {
        return false;
    }
    DeletePos(s, index, t->length);
    return true;
}

//打印串s
void Show(const String *s)
{
    for (int i = 0; i < s->length; ++i)
    {
        //注意这里只能单个字符打印,不能直接使用%s打印,因为串中没有结尾标志
        printf("%c", s->elem[i]);   
    }
    printf("\n");
}

void Detroy(String *s)
{
    Clear(s);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值