算法入门之串的顺序存储表示
2011-11-10 16:52 java线程例子 阅读(260) 评论(0) 编辑 收藏 举报
串,即字符串。计算机上的非数值处理的对象基本上是字符串数据。但是,由于现在我们使用的计算机硬件结构主要是反映数值计算的需要的,在处理字符串数据时比处理整数和浮点数要复杂的多。而且,对于不同类型程序,所处理的字符串具有不同的特点,要有效地实现字符串的处理,就必须根据具体情况使用合适的存储结构。串的存储表示主要有:1.定长顺序存储表示; 2. 堆分配存储表示; 3.块链存储表示。
以下介绍比较简单的定长顺序存储表示。
串定长顺序存储表示,说白了,就是用以个固定长度字符数组来存放。
1.定义“头部”
#define MAXSTRLEN 255 //所能定义的最大串长 typedef unsigned char SString[MAXSTRLEN + 1]; //数组中下标0的位置,用来存放,当前串的长度
2.初始化
Status InitStr(SString &T) { T[0] = 0;//初始化唯一要做的事。定义串当前长度为0。 return OK; }3.把一个字符数组赋给SString。。
Status StrAssign(SString &T, char *chars) { int len = strlen(chars); if (len > MAXSTRLEN) return ERROR; T[0] = len; for (int i = 0; i < len; i++) { T[i + 1] = chars[i]; } return OK; }
也许看到在这,你会问,SString本身是一个字符数组,为什么又要用一个字符数组去赋给SString?
其实不然,SString相对与字符数组,已经有所不同了,它以数组中下标0的位置存放串当前的实际长度。PASCAL语言中就是使用这个串类型的表示方法。
而对于char *chars = "12345",要像把它赋给另一个字符数组如char chars1[n],那么这里的n值必须大于等于6。因为C语言在字符串末位加了'\0'作为结束标志符。但是有的编译器如gcc不检测这错误。
4.串的比较
Status StrCompare(SString S, SString T) { for (int i = 1; i <= S[0] && i <= T[0]; i++) { if (S[i] != T[i]) { return S[i] - T[i]; //返回第一组不同的字符间的差 } } return T[0] - S[0];//若其中一个字符串刚好是另一个的子串,返回两字符串之间的长度差。 }
5.从S下标为pos开始,取长度len的子串Sub。
Status SubString(SString S, SString &Sub, int pos, int len) { if (pos < 1 || pos > S[0] || len < 1 || len > S[0] - pos + 1) return ERROR; Sub[0] = len; for (int i = 1; i <= len; i++) { Sub[i] = S[pos + i - 1]; } return OK; }
6.串的合并:S1,S2合并为S
Status Contact(SString &S, SString S1, SString S2) { int i = 0; int j = 0; if (S1[0] + S2[0] <= MAXSTRLEN) //第一种情况,两串长度的和小于所定义的串的最大存储长度 { S[0] = S1[0] + S2[0]; for (i = 1; i <= S1[0]; ++i) S[i] = S1[i]; for (j = 1; j <= S2[0]; ++i, ++j) S[i] = S2[j]; return OK; } else if (S1[0] < MAXSTRLEN) //第二种情况,S1能完全存入S,S2可能被截断或者一个都不存入 { S[0] = MAXSTRLEN; for (i = 1; i <= S1[0]; i++) { S[i] = S1[i]; } for (j = 1; i <= MAXSTRLEN; ++i, ++j) S[i] = S2[j]; return OK; } else) //第三种情况,连S1也被截断 { S[0] = MAXSTRLEN; for (i = 1; i <= MAXSTRLEN; i++) { S[i] = S1[i]; } return OK; } }
7.模式匹配的一种改进算法:KMP算法
void get_next(SString T, int next[]) { int i = 1; next[1] = 0; int j = 0; while (i < T[0]) { if (j == 0 || T[i] == T[j]) { ++i; //执行先++j,再执行next[i] = j。 ++j; //因为是在串中第j+1字符前有长度为j的最长子串,与从首字符起长度为j的子串相等。 next[i] = j; //注意其上的前提是已经T[i] == T[j]。 } else j = next[j]; } }
//S为主串,T为要查找的模式串 Status Index_KMP(SString S, SString T, int pos) { int *next = new int(); get_next(T, next); int i = pos, j = 1; //i为T开始匹配的位置 , while (i <= S[i] && j <= T[0]) { if (j == 0 || S[i] == T[j]) { ++i; ++j; } else j = next[j]; //j != 0 且 S[i] != T[j],S[i]与T[next[j]]比较 } if (j > T[0]) return i - T[0]; //匹配成功 else return 0; }