String结构模拟

我们开始模拟一下大家最熟悉的String数据结构的模拟,这个相信做java的没有不熟悉的吧.那我们开始

1.操作接口

public interface IString {

public void clear();          //将一个已经存在的串置成空串

public boolean isEmpty();    //判断当前串是否为空,为空则返回true,否则返回false

public int length();         //返回字符串的长度

public char charAt(int index);   //返回串中序号为index的字符

public IString substring(int begin, int end); //返回串中字符序号从begin至end-1的子串

public IString insert(int offset, IString str);  //在当前串的第offset个字符之前插入串str

public IString delete(int begin, int end);   //删除当前串中从序号begin开始到序号end-1为止的子串

public IString concat(IString str);  //添加指定串str到当前串尾

//将当前串与目标串str进行比较,若当前串大于str,则返回一个正整数,若当前串等于str,则返回0,若当前串小于str,则返回一个负整数。

public int compareTo(IString str);

//若当前串中存在和str相同的子串,则返回模式串str在主串中从第start字符开始的第一次出现位置,否则返回-1

public int indexOf(IString str,int start);

}

2.实现操作(顺序串的实现)

public class SeqString  implements  IString{

private char[] strvalue;            //字符数组,存放串值

private int curlen;                //当前串的长度

//构造方法1,构造一个空串

public SeqString() {

strvalue = new char[0];

curlen = 0;

}

//构造方法2,以字符串常量构造串对象

public SeqString(String str) {

if (str != null) {

char[] tempchararray = str.toCharArray();

strvalue = tempchararray;

curlen = tempchararray.length;

}

}

//构造方法3,以字符数组构造串对象

public SeqString(char[] value) {

this.strvalue = new char[value.length];

for (int i = 0; i < value.length; i++) { //复制数组

this.strvalue =
value;

}

curlen = value.length;

}

//将一个已经存在的串置成空串

public void clear() {

this.curlen = 0;

}

//判断当前串是否为空,为空则返回true,否则返回false

public boolean isEmpty() {

return curlen == 0;

}

//返回字符串长度

public int length() {

return curlen;    //区别: strvalue.length是数组容量

}

//返回字符串中序号为index的字符

public char charAt(int index) {

if ((index < 0) || (index >= curlen)) {

throw new StringIndexOutOfBoundsException(index);

}

return strvalue[index];

}

//将字符串中序号为index的字符设置为ch

public void setCharAt(int index, char ch) {

if ((index < 0) || (index >= curlen)) {

throw new StringIndexOutOfBoundsException(index);

}

strvalue[index] = ch;

}

public void allocate(int newCapacity) //扩充容量,参数指定最小容量

{

char[] temp = strvalue;                           //复制数组

strvalue = new char[newCapacity];

for (int i = 0; i < temp.length; i++) {

strvalue = temp;

}

}

//返回串中序号从begin至end-1的子串

public IString 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 = this.strvalue[i + begin];

}

return new SeqString(buffer);

}

}

//返回串中序号从begin至串尾的子串

public IString substring(int begin) {

return substring(begin,strvalue.length);

}

//在当前串的第offset个字符之前插入串str,0<=offset<=curlen

public IString insert(int offset, IString str) {

if ((offset < 0) || (offset > this.curlen)) {

throw new StringIndexOutOfBoundsException("插入位置不合法");

}

int len = str.length();

int newCount = this.curlen + len;

if (newCount > strvalue.length) {

allocate(newCount);             // 插入空间不足,需扩充容量

}

for (int i = this.curlen - 1; i >= offset; i--) {

strvalue[len + i] = strvalue;    //从offset开始向后移动len个字符

}

for (int i = 0; i < len; i++) //复制字符串str

{

strvalue[offset + i] = str.charAt(i);

}

this.curlen = newCount;

return this;

}

//删除从begin到end-1的子串, 0≤begin≤length()-1,1≤end≤length()。

public IString delete(int begin, int end) {

if (begin < 0) {

throw new StringIndexOutOfBoundsException("起始位置不能小于0");

}

if (end > curlen) {

throw new StringIndexOutOfBoundsException("结束位置不能大于串的当前长度:" + curlen);

}

if (begin > end) {

throw new StringIndexOutOfBoundsException("开始位置不能大于结束位置");

}

for (int i = 0; i < curlen - end; i++) //从end开始至串尾的子串向前移动到从begin开始的位置

{

strvalue[begin + i] = strvalue[end + i];

}

curlen = curlen - (end - begin);  //当前串长度减去end-begin

return this;

}

//添加指定串str到当前串尾

public IString concat(IString str) {

return insert(curlen, str);

}

//将字符c连接到到当前串尾

public IString concat(char c) {

int newCount = curlen + 1;

if (newCount > strvalue.length) {

allocate(newCount);

}

strvalue[curlen++] = c;

return this;

}

//比较串

public int compareTo(IString str) {

return compareTo((SeqString) str);

}

public int compareTo(SeqString str) {  //比较串

//若当前对象的串值大于str的串值,则函数返回一个正整数

//若当前对象的串值等于str的串值,则函数返回0

//若当前对象的串值小于str的串值,则函数返回一个负整数

int len1 = curlen;

int len2 = str.curlen;

int n = Math.min(len1, len2);

//char s1[] = strvalue;

//char s2[] = str.strvalue;

//int k = 0;

//while (k < n) {

//    char ch1 = s1[k];

//    char ch2 = s2[k];

//    if (ch1 != ch2) {

//        return ch1 - ch2;  //返回第一个不相等字符的数值差

//    }

//     k++;

//}

for (int k=0;k<n;k++)

if (strvalue[k]!=str.strvalue[k])

return(strvalue[k]-str.strvalue[k]);

return len1 - len2;   //返回两个字符串长度的数值差

}

public String toString() {

return new String(strvalue, 0, curlen);   //以字符数组strvalue构造串

}

// 模式匹配的Brute-Force 算法

//返回模式串t在主串中从start开始的第一次匹配位置,匹配失败时返回-1。

public int index_BF(SeqString t, int start) {

if (this != null && t != null && t.length() > 0 && this.length() >= t.length()) {  //当主串比模式串长时进行比较

int slen, tlen, i = start, j = 0;    //i表示主串中某个子串的序号

slen = this.length();

tlen = t.length();

while ((i < slen) && (j < tlen)) {

if (this.charAt(i) == t.charAt(j)) //j为模式串当前字符的下标

{

i++;

j++;

} //继续比较后续字符

else {

i = i - j + 1;        //继续比较主串中的下一个子串

j = 0;                //模式串下标退回到0

}

}

if (j >= t.length()) //一次匹配结束,匹配成功

{

return i - tlen;         //返回子串序号

} else {

return -1;

}

}

return -1;                     //匹配失败时返回-1

}

//若当前串中存在和str相同的子串,则返回模式串str在主串中从第start字符开始的第一次出现位置,否则返回-1

public int indexOf(IString t, int start) {

return index_KMP(t, start);

}

//KMP模式匹配算法

public int index_KMP(IString T, int start) {

//在当前主串中从start开始查找模式串T

//若找到,则返回模式串T在主串中的首次匹配位置,否则返回-1

int[] next = getNext(T);     //计算模式串的next[]函数值

int i = start;               //主串指针

int j = 0;                   //模式串指针

//对两串从左到右逐个比较字符

while (i < this.length() && j < T.length()) {

//若对应字符匹配

if (j == -1 || this.charAt(i) == T.charAt(j)) { // j==-1表示S!=T[0]

i++;

j++;         //则转到下一对字符

} else //当S不等于T[j]时

{

j = next[j];        //模式串右移

}

}

if (j < T.length()) {

return -1;                  //匹配失败

} else {

return (i - T.length());    //匹配成功

}

}

//计算模式串T的next[]函数值

private int[] getNext(IString T) {

int[] next = new int[T.length()];  //next[]数组

int j = 1;    //主串指针

int k = 0;   //模式串指针

next[0] = -1;

if (T.length()>1)

next[1] = 0;

while (j < T.length() - 1) {

if (T.charAt(j) == T.charAt(k)) {  //匹配

next[j + 1] = k + 1;

j++;

k++;

} else if (k == 0) {  //失配

next[j + 1] = 0;

j++;

} else {

k = next[k];

}

}

return (next);

}

//计算模式串T的nextval[]函数值

private int[] getNextVal(IString T) {

int[] nextval = new int[T.length()];  //nextval[]数组

int j = 0;

int k = -1;

nextval[0] = -1;

while (j < T.length() - 1) {

if (k == -1 || T.charAt(j) == T.charAt(k)) {

j++;

k++;

if (T.charAt(j) != T.charAt(k)) {

nextval[j] = k;

} else {

nextval[j] = nextval[k];

}

} else {

k = nextval[k];

}

}

return (nextval);

}

}

小结:还有能不能用链表实现呢?当然这样不是很好,但是可以锻炼思维和动手能力

String结构模拟

时间: 2024-10-05 04:58:48

String结构模拟的相关文章

顺序存储结构模拟

我们过去介绍的数据结构都不是线性存储的结构,我们今天就来模拟一个最简单的数据结构基于数组构建存储连续的数据结构. 1.线性表顺序存储结构的接口 /** * 指的是用一段地址连续的存储单元一次存储线性表的数据元素 * @ClassName: ISeqList */ public interface ISeqList<T> { /** * 获得元素 * @param i 需要获得的第i个元素 * @return */ public T getElem(int i); /** * 插入元素 * @p

Queue结构模拟

接着我们介绍queue数据结构,我们通过对简单的数据结构的模拟后是不是感觉自己的内功提高的呀,那有人会问什么是内功呢?其实我觉得就是一个思维意识,换句话来说就是你站得更好的.这样的话,我觉得我们的工作更加有意义,我们以分享,交流,责任为目标学习分享技术. 1.基础的节点对象Node public class Node { private Object data;// 存放值 private Node next;// 下一个节点 public   Node(){} public Node(Obje

Stack结构模拟

我们接着就开始模拟stack数据结构,发觉敲多的头昏,坚持分享 1.基础结构对象Node public class Node { private Object data;// 存放值 private Node next;// 下一个节点 public   Node(){} public Node(Object data) {// 构造值为data的结点 this(data,null); } public Node(Object data, Node next) { this.data = dat

LabVIEW设计模式系列——case结构模拟事件结构

标准:1.所有按钮的机械动作必须都用释放时触发或者单击时触发,这是为了保证仅仅触发一次动作. 标准:1.使用简单的case结构模拟事件结构.

csu - 1536: Bit String Reordering (模拟)

http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1536 不知道为何怎么写都写不对. 这题可以模拟. 虽然题目保证一定可以从原串变成目标串,但是不一定可以变成两种目标串. 所以需要判断下.统计原串中0和1的个数,然后计算目标串中0可能的个数,1可能的个数. 计算交换次数就是从后面找一个跟当前不一样的数字交换到前面来即可. 1 #include<iostream> 2 #include<cstdio> 3 #include<cs

CodeForces 545B Equidistant String (模拟)

[题目链接]:click here~~ [题目大意]: 题意:求一个字符串,使得它与S,T,相似度相差相等. [思路]:就是找出S,T之间的相差个数,相差为奇数,输出impossible.输出为偶数的话不同的前半部分输出S后半部分输出T就好了. 代码: /* * Problem: CodeForces 545B * Running time: 0MS * Complier: G++ * Author: herongwei * Create Time: 8:11 2015/9/17 星期四 */

CodeForce-797C Minimal string(贪心模拟)

Minimal string CodeForces - 797C Petya 收到一个长度不超过 105 的字符串 s.他拿了两个额外的空字符串 t 和 u 并决定玩一个游戏.这个游戏有两种合法操作: 将 s 串的第一个字符移动到字符串 t 的末尾. 将 t 串的最后一个字符移动到字符串 u 的末尾. Petya 希望将 s 和 t 都变为空串并且使得串 u 字典序最小. 你需要写一个代码求出最小的字典序. Input 第一行包含一个非空串 s (1?≤?|s|?≤?105),只包含小写字母.

hdu 5202 Rikka with string(模拟)

Rikka with string Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 625    Accepted Submission(s): 244 Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situation

Binary Tree Postorder Traversal(各种非递归实现,完美利用栈结构模拟)

1.后序遍历的非递归实现.(左右根) 难点:后序遍历的非递归实现是三种遍历方式中最难的一种.因为在后序遍历中,要保证左孩子和右孩子都已被访问并且左孩子在右孩子前访问才能访问根结点,这就为流程的控制带来了难题.下面介绍两种思路. 思路:有个关键的就是unUsed这个标识符. 当unUsed=1时,表示该节点未遍历过,即以该节点为根节点的左右孩子不曾遍历. 当unUsed=0时,表示该节点的左右孩子都已经被访问过. 由于入栈的顺序和出栈的顺序相反,所以若unUsed=1,则左根右节点依次入栈,且根节