数据结构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;}@Overridepublic void clear() {this.curlen = 0;}@Overridepublic boolean isEmpty() {return this.curlen == 0;}@Overridepublic int length() {return this.curlen;}@Overridepublic 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];}}@Overridepublic 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);}}@Overridepublic 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;}@Overridepublic 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;}@Overridepublic 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;}@Overridepublic 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;}@Overridepublic int indexOf(MString str, int begin) {return 0;}}

后记

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

真正的寂寞是在人群中,当你面对许多熟悉的脸,

数据结构Java实现——③串

相关文章:

你感兴趣的文章:

标签云: