数据结构Java实现——③串


写在前面


不知不觉的就放假将近十天了,回家的日子实在是太安逸,安逸到忘记了时间,忘记了学习,昨天一不小心看了下日历才知道又虚度了十天的光阴,哎!人的惰性,实在是没什么能说的了。


闲话少说,回归正题。前天上午开始看的串,一开始觉得串挺简单的,实现的基本上都是曾经见过的字符串的方法,就当是重新学习了一下。觉得当时就能看完,然后把博客写了,算是做个总结,赶紧看完数组然后去重点学习树,哪知道。。。。


文字介绍


所谓串,“字符串”也,即字符串在一起作为一个整体,当然串也是线性表的一种,当然也有顺序存储,链式存储两种。

很显然在学习了前面那么多的“特殊的”线性表之后,对常见的两种存储方式不难理解


首先来说顺序存储,在最开始构造时,要预先的创建一个“大”数组,然后将数据存储尽量,对应顺序存储,必须要有一个记录当前实际占用“大”数组长度、也就是串本身的实际长度的变量。


       然后来说链式存储,首先链式存储肯定要用到结点对象(有指针域,有数据域),如果结点的数据域里存储的是单个字符,那么该链表称为单字符链表,否则,也就是结点的数据域内存储多个字符时,称为块链表

很显然,对于单字符链表而言,插入、删除、查询等操作比较方便,但是存储效率太低(指针所占的存储比例较大);对于块链表而言,虽然存储效率高,但是对于一些基本的操作,实现起来比较麻烦


实际应用中串的链式存储也用的比较少,因此此处仅仅给出串的顺序存储的代码实现


代码实现



1、串的抽象接口

package org.Stone6762.MString;

/**
 * @MString
 * @Stone6762
 * @Description
 */
public interface MString {

	/**
	 * @Title: clear
	 * @Description: TODO(将字符串清空)
	 */
	public void clear();

	/**
	 * @Title: isEmpty
	 * @Description: TODO(判断是否为空)
	 * @return
	 */
	public boolean isEmpty();

	/**
	 * @Title: length
	 * @Description: TODO(求字符串的长度)
	 * @return
	 */
	public int length();

	/**
	 * @Title: charAt
	 * @Description: TODO(取出字符串中的某一个下标下的字符)
	 * @param index
	 * @return
	 */
	public char charAt(int index);

	/**
	 * @Title: subString
	 * @Description: TODO(根据起始和结束的下标来截取某一个子串)
	 * @param begin要截取部分的起始部分,包括起始部分
	 * @param end截止到end,不包括end
	 * @return
	 */
	public MString subString(int begin, int end);

	/**
	 * @Title: insert
	 * @Description: TODO(根据下标将一个字符串插入到指定的位置)
	 * @param offset要插入的字符串的第一个位置
	 * @param str
	 * @return
	 */
	public MString insert(int offset, MString str);

	/**
	 * @Title: delete
	 * @Description: TODO(删除掉串中的某一部分)
	 * @param begin
	 * @param end
	 * @return
	 */
	public MString delete(int begin, int end);

	/**
	 * @Title: concat
	 * @Description: TODO(将一个字符串连接到该字符串的末尾)
	 * @param str
	 * @return
	 */
	public MString concat(MString str);

	/**
	 * @Title: compareTo
	 * @Description: TODO(两个字符串进行比较)
	 * @param str
	 * @return
	 */
	public int compareTo(MString str);

	/**
	 * @Title: indexOf
	 * @Description: TODO(在本字符串中,从begin位置开始,检索某一个字符串第一次出现的位置)
	 * @param str
	 * @param begin
	 * @return
	 */
	public int indexOf(MString str, int begin);
}


2、串的顺序存储实现



package org.Stone6762.MString.imple;

import org.Stone6762.MString.MString;

/**
 * @SeqString
 * @Stone6762
 * @Description
 */
public class SeqString implements MString {

	/**
	 * @Fields strvalue : TODO(储存串中的每一个元素)
	 */
	private char[] strvalue;

	/**
	 * @Fields curlen : TODO(记录当前的串的长度)
	 */
	private int curlen;

	/**
	 *  @Description: TODO(构造方法一,默认的)
	 * 
	 */
	public SeqString() {
		this.strvalue = new char[0];
		this.curlen = 0;
	}

	/**
	 *  @Description: TODO(构造方法二,设置顺序存储的串的最大长度)
	 * 
	 * @param maxSize
	 */
	public SeqString(int maxSize) {
		this.strvalue = new char[maxSize];
		this.curlen = 0;
	}

	/**
	 *  @Description: TODO(构造方法三、以一个字符串构造串对象)
	 * 
	 * @param str
	 */
	public SeqString(String str) {
		strvalue = str.toCharArray();
		curlen = strvalue.length;
	}

	/**
	 *  @Description: TODO(构造方法四,以一个字符数组构造串对象)
	 * 
	 * @param value
	 */
	public SeqString(char[] value) {
		this.strvalue = new char[value.length];
		for (int i = 0; i < value.length; i++) {
			strvalue[i] = value[i];
		}
		curlen = value.length;

	}

	public char[] getStrvalue() {
		return strvalue;
	}

	public int getCurlen() {
		return curlen;
	}

	@Override
	public void clear() {
		this.curlen = 0;
	}

	@Override
	public boolean isEmpty() {
		return this.curlen == 0;
	}

	@Override
	public int length() {
		return this.curlen;
	}

	@Override
	public char charAt(int index) {
		if (index < 0 || index >= this.curlen) {
			throw new StringIndexOutOfBoundsException();
		}
		return strvalue[index];
	}

	/**
	 * @Description: TODO( 扩充串存储空间容量,参数指定容量 )
	 * @param newCapacity
	 */
	public void allocate(int newCapacity) {
		/*
		 * 先将原来的数据进行保存,然后根据参数创建一个目标大小的存储空间 最后将保存的数据存储到新的空间中
		 */
		char[] tempCArry = this.strvalue;
		strvalue = new char[newCapacity];
		for (int i = 0; i < tempCArry.length; i++) {
			strvalue[i] = tempCArry[i];
		}
	}

	@Override
	public MString subString(int begin, int end) {
		/*
		 * 首先要判断想要截取的下标的合法性(不能越界,开始不能大于结束) 然后直接根据下标找到目标字符数组,然后根据字符数组创建一个顺序存储的串
		 */
		if (begin < 0) {
			throw new StringIndexOutOfBoundsException("起始位置不能小于0");
		}
		if (end > curlen) {
			throw new StringIndexOutOfBoundsException("结束位置不能大于串本身的长度" + curlen);
		}
		if (begin > end) {
			throw new StringIndexOutOfBoundsException("起始位置不能大于中止位置");
		}
		if (begin == 0 && end == curlen) {
			return this;
		} else {
			char[] buffer = new char[end - begin];
			for (int i = 0; i < buffer.length; i++) {
				buffer[i] = this.strvalue[i + begin];
			}
			return new SeqString(buffer);
		}
	}

	@Override
	public MString insert(int offset, MString str) {
		/*
		 * 首先判断插入位置的合法性(小于0或大于原本串的长度) 然后判断是否能够存储,不能就扩充
		 * 最后,先将要插入部分的字符向后移,再将要插入的字符插入即可
		 */
		if (offset < 0 || offset > curlen) {
			throw new StringIndexOutOfBoundsException("");
		}
		int strlen = str.length();
		int newlength = strlen + curlen;
		if (newlength > this.strvalue.length) {
			allocate(newlength);
		}
		// 将offset后的元素都后移strlen位
		for (int i = curlen - 1; i >= offset; i--) {
			strvalue[strlen + i] = strvalue[i];
		}
		// 插入
		for (int i = 0; i < strlen; i++) {
			strvalue[offset + i] = str.charAt(i);
		}
		this.curlen = newlength;
		return this;
	}

	@Override
	public MString delete(int begin, int end) {

		/*
		 * 首先将判断下标的合法性,起始不能小于0,结束不能超出当前串的长度,起始不能大于结束
		 * 然后将end以后(包括end)的字符都向前移动到起始的位置。
		 */
		if (begin < 0) {
			throw new StringIndexOutOfBoundsException("起始位置不能小于0");
		}
		if (end > curlen) {
			throw new StringIndexOutOfBoundsException("结束位置不能大于串本身的长度" + curlen);
		}
		if (begin > end) {
			throw new StringIndexOutOfBoundsException("起始位置不能大于中止位置");
		}
		for (int i = end; i < curlen; i++) {
			this.strvalue[begin + i] = this.strvalue[i];
		}
		curlen = curlen - (end - begin);
		return this;
	}

	@Override
	public MString concat(MString str) {
		/*
		 * 首先判断是否能够存储
		 */
		int newlen = str.length() + curlen;
		if (newlen > strvalue.length) {
			allocate(newlen);
		}
		for (int i = 0; i < str.length(); i++) {
			strvalue[curlen + i] = str.charAt(i);
		}
		return this;
	}

	@Override
	public int compareTo(MString str) {
		/*
		 * 首先以一个长度小的为基准,遍历比较,一旦出现不相等,返回比较值。 如果长度相同的部分都相等,返回长度比较值
		 */
		int len1 = curlen;
		int len2 = str.length();
		int n = Math.min(len1, len2);

		char[] cArry1 = strvalue;
		char[] cArry2 = ((SeqString) str).strvalue;
		int i = 0;
		char c1, c2;
		while (i < n) {
			c1 = cArry1[i];
			c2 = cArry2[i];
			if (c1 != c2) {
				return c1 - c2;
			}
			i++;
		}
		return len1 - len2;
	}

	@Override
	public int indexOf(MString str, int begin) {

		return 0;
	}	
}



后记


        能细心看代码的就会发现,上面的串的顺序存储中,串匹配(检索)的函数没有实现,这就是我说的为什么到现在才总结的原因,因为这才是串的知识点中的难度,也是不容易理解的地方,我就卡在了这里,一直卡到了总结前才算是明白了七八分。此处不对匹配进行分析,因为匹配比较难,我会拿出来单独的分析



  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值