背景

今天复习串这种数据结构。在这里,我们使用顺序结构数组来实现串,因为链式存储指针域4个字节,而存一个字符1个字节,这样会造成内存空间的浪费。

基本理论
  1. 首先介绍一些基本概念:
  • 串:串是由0个或多个字符组成的有限序列,又名字符串,记为S=‘ a 0 a 1 a 2 . . . a n a_0a_1a_2...a_n a0a1a2...an
  • 串的长度:串中包含字符的个数即该串的长度。
  • 空串:长度为0的串
  • 子串与主串:串中任意连续字符组成的有限序列称为该串的子串,而该串称为主串
  • 子串在主串中的位置:子串在主串第一次出现时,子串的第一个字符在主串中的位置 称为子串在主串中的位置。
  • 串相等:串长度相同且对应字符相同
  1. 接下里介绍串的基本操作

串和线性表的逻辑结构很相似,只不过串中的元素均为字符。此外,串和线性表的基本操作也有差异,线性表的基本操作是针对于单个元素的,而串的基本操作是针对于子串(多个元素)。

串的基本操作如图:
在这里插入图片描述

代码实现
  • 首先定义串的基本操作(接口):
/// <summary>
/// 串 接口
/// </summary>
public interface IString
{
    int Length { get; } // 获取字符个数
    char this[int index] { get; set; } // 获取或设置对应索引处的字符

    IString Insert(int index, IString s); // 在指定位置处插入串
    IString Remove(int startIndex, int count); // 在指定位置移除指定长度的子串
    IString SubString(int startIndex, int count); // 获取指定位置、指定长度的子串
    IString Concat(IString s); // 串连接
    IString Clone(); // 串克隆
    int FindParam(IString s); // 查找子串(串匹配)
}
  • 顺序结构数组实现串
/// <summary>
/// 顺序结构(数组)实现串
/// </summary>
public class SeqString : IString
{
    private readonly char[] _CStr; //存储字符串

    /// <summary>
    /// 获取字符个数
    /// </summary>
    public int Length
    {
        get
        {
            int i = 0;
            while (_CStr[i] != '\0')
            	i++;
            return i;
        }
    }

    /// <summary>
    /// 设置或获取对应索引处的字符
    /// </summary>
    /// <param name="index"></param>
    /// <returns></returns>
    public char this[int index]
    {
        get
        {
            if (index < 0 || index > Length - 1)
                throw new IndexOutOfRangeException();
            return _CStr[index];
        }
        set
        {
            if (index < 0 || index > Length - 1)
                throw new IndexOutOfRangeException();
            _CStr[index] = value;
        }
    }

    public SeqString()
    {
    	_CStr = new char[] { '\0' };
    }

    public SeqString(string s)
    {
        if (s == null)
            throw new ArgumentNullException();
    	int length = s.Length;
    	_CStr = new char[length + 1];

        for (int i = 0; i < length; i++)
        	_CStr[i] = s[i];
    	_CStr[length] = '\0';
    }

    public SeqString(int length)
    {
        if (length <= 0)
        	throw new ArgumentOutOfRangeException();
        _CStr = new char[length + 1];
        _CStr[length] = '\0';
    }

    /// <summary>
    /// 插入子串
    /// </summary>
    /// <param name="startIndex"></param>
    /// <param name="s"></param>
    /// <returns></returns>
    public IString Insert(int startIndex, IString s)
    {
        if (s == null)
        	throw new Exception("所插入的串为空");
        if (startIndex < 0 || startIndex > Length)
        	throw new IndexOutOfRangeException();

    	SeqString temp = new SeqString(Length + s.Length);

        for (int i = 0; i < startIndex; i++)
        {
        	temp._CStr[i] = _CStr[i];
        }
        for(int i = 0; i < s.Length; i++)
        {
        	temp._CStr[startIndex + i] = s[i];
        }
        for(int i = startIndex; i < Length; i++)
        {
        	temp._CStr[s.Length + i] = _CStr[i];
        }

    	return temp;
    }

    /// <summary>
    /// 删除子串
    /// </summary>
    /// <param name="startIndex"></param>
    /// <param name="count"></param>
    /// <returns></returns>
    public IString Remove(int startIndex, int count)
    {
        if (startIndex < 0 || startIndex > Length - 1)
        	throw new IndexOutOfRangeException();

        if (count < 0)
        	throw new ArgumentOutOfRangeException();

        int left = Length - startIndex; // 最多移除字符个数
        count = (left < count) ? left : count; // 实际移除字符个数

    	SeqString temp = new SeqString(Length - count);

        for (int i = 0; i < startIndex; i++)
        {
        	temp._CStr[i] = _CStr[i];
        }
        for (int i = startIndex; i < Length - count; i++)
        {
        	temp._CStr[i] = _CStr[i + count];
        }

    	return temp;
    }

    /// <summary>
    /// 获取子串
    /// </summary>
    /// <param name="startIndex"></param>
    /// <param name="count"></param>
    /// <returns></returns>
    public IString SubString(int startIndex, int count)
    {
        if (startIndex < 0 || startIndex > Length - 1)
        	throw new IndexOutOfRangeException();
        if (count < 0)
        	throw new ArgumentOutOfRangeException();

        int left = Length - startIndex; // 可取子串的最大长度
        count = (left < count) ? left : count; // 实际子串字符个数

    	SeqString temp = new SeqString(count);

        for (int i = 0; i < count; i++)
        {
        	temp._CStr[i] = _CStr[i + startIndex];
        }

    	return temp;
    }

    /// <summary>
    /// 两串连接
    /// </summary>
    /// <param name="s"></param>
    /// <returns></returns>
    public IString Concat(IString s)
    {
        if (s == null)
            throw new ArgumentNullException();

    	return Insert(Length, s);
    }
    public static SeqString operator +(SeqString s1, SeqString s2)
    {
        if (s1 == null || s2 == null)
            throw new ArgumentNullException();
    	return s1.Concat(s2) as SeqString;
    }

    /// <summary>
    /// 克隆串
    /// </summary>
    public IString Clone()
    {
    	SeqString temp = new SeqString(Length);

        for (int i = 0; i < Length; i++)
        {
        	temp._CStr[i] = _CStr[i];
        }

    	return temp;
    }

    /// <summary>
    /// 查找子串(暴力查找法)
    /// </summary>
    /// <param name="s"></param>
    /// <returns></returns>
    public int FindParam(IString s)
    {
        if (s == null)
        throw new ArgumentNullException();
        int i = 0;
        int j = 0;
        while (i < Length && j < s.Length)
        {
            if (_CStr[i] == s[j])
            {
                i++;
                j++;
            }
            else
            {
                i = i - j + 1;
                j = 0;
            }
        }
        if (j == s.Length)
        	return i - j;
        else
        	return -1;
    }

    public override string ToString()
    {
    	string str = string.Empty;
        for (int i = 0; i < Length; i++)
        {
            str += _CStr[i];
        }
            return str;
        }
}

综上,我们介绍完了串这种顺序结构以及它的基本操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值