一.串
1.基本概念
串:是由 0 个或多个字符组成的有限序列。
零个字符的串称为空串,通常用符号“ ”来表示,它的长度为零。
串的逻辑结构:和线性表极为相似。区别:串的数据对象约定是字符集。
串的基本操作:和线性表有很大差别。线性表的基本操作:以“单个元素”为操作对象;串的基本操作:以“串的整体”作为操作对象。
判断两个串是否相等:只有当两个串的长度相等,并且各个对应位置的字符都相等时才相等。
2.串的顺序存储和实现
先说说顺序存储;
串的顺序存储结构是用数组来存储串中的字符序列的。
在串的顺序存储中,一般有三种方法表示串的长度:
⑴ 用一个变量来表示串的长度
(2)在串尾存储一个特殊字符作为串的终结符
(3)用数组的0号单元存放串的长度
再说说串的实现;
1.串的初始化;
// 无参构造方法
public string ( ) { }//构造一个空串
// 有参构造方法
public string(int n) { // 构造一个能保存n个字符的串
this.maxSize =n;
this.chars = new char[n];
this.length = 0;
}
2.串的比较;
public int compare(string t) {
//将当前串与串t进行比较。若相等,则返回值=0;大于返回1,;小于返回-1;
int i=0;
while(this.chars[i]= =t.chars[i] && i<this.length &&i<t.getLength())
{ i++; }
if(i==this.length && i==t.length)
return 0;
else if(i==t.getLength() && i<this.length)
return 1;
else
return -1;
}
对于字符串s1和s2,比较大小的话,可以直接使用**s1.compareTo(s2)**来比较大小
3.串连接
public void concat(string t)
{
if(this.maxSize < this.length+ t.getLength( ))
{
//当前串容量不够,暂存到数组a
this.maxSize = this.length + t.getLength();
this.chars = new char[this.maxSize];
//恢复当前串的原始状态
}
for(int i= 0;i<t.getLength();i++)
{ this.chars[this.length]=t.chars[i];
this.length++;
}
}
s1.concat(s2);//将字符串s2的字符添加到s1的末尾;
4.求子串;
public string subString(int pos, int len)
{
if(pos+len>=this.length)
return null;
string a = new string(len);
for(int i=0; i<len; i++)
{
a.chars[i] = this.chars[pos+i];
a.length ++;
}
return a;
}
5.复制串;
public void copy(string t) // 将串t复制给当前串
{ if(this.maxSize<t.maxSize)
{
this.maxSize = t.maxSize;
this.chars = new char[this.maxSize];
}
this.length=0; //初始化当前串的长度
for(int i=0; i<t.getLength();i++)
{
this.chars[i]=t.chars[i];
this.length++;
}
}
下面为我对串的补充操作;
设s1,s2为两个字符串;
-
s1.compareTo(s2) //比较大小
-
s1.length(); //求字符串长度
-
s1.charAt(index); // 查找下标为index的字符
-
s1.equals(s2) // 判断字符串内容是否相等
-
s1.substring(index) // 截取从当前串的第index个字符到最后一个字符并输出
-
s1.substring(index1,index2) //截取当前串的index1位置到index2位置的字符输出
-
s1.indexOf(“s2”) //寻找s2的字符是否存在,存在输出s2的头字符在s1中的index,不存在则输出-1.
-
s1.trim() //删除字符串两端的空格
-
s1.replace(a,b) // 将字符串中所有a换成b
-
s1.toLowerCase // s1中所有字符换成小写
-
s1.toUpperCase // 换成大写
-
s1.toCharArray() // 字符串转换为字符数组
-
s1.concat(s2) // s2的字符添加到s1的末尾
3.BF算法与KMP算法
这里算是一个小重点了,具体总结一下;
先说BF算法;基本思想是将当前串的第一个字符与子串的第一个字符进行比较,相同后,再比较第二个字符,若第二个字符不同,则比较当前串的第二个字符与子串的首字符。BF算是一种蛮力算法,时间复杂度是O(n*m)。
具体代码:
public int index(string t)
{
if(this.length < t.getLength())
return -1;
int a=-1;
for(int i=0; i< this.length;i++)
{ int j=0;
//在当前串中从位置i开始查找子串t
if(j==t.getLength())
{ a=i; break; }
}
return a;
}
接下来说说KMP算法;
刚开始我也不太懂,然后去看了几位博主的KMP算法详解,有点感觉,在这里总结一下,如果看不懂我写的可以去我转载的博文里看看。
假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置。
若j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++,继续匹配下一个字符;
若j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]。此举意味着失配时,模式串P相对于文本串S向右移动了j - next [j] 位。
对于这个next[]数组,就是模式串p的最大前缀后缀结果整体右移一位,然后第一位变成-1。
代码表示
//此代码转自https://www.cnblogs.com/imzhr/p/9613963.html
public class KMP {
/**
* 求出一个字符数组的next数组
* @param t 字符数组
* @return next数组
*/
public static int[] getNextArray(char[] t) {
int[] next = new int[t.length];
next[0] = -1;
next[1] = 0;
int k;
for (int j = 2; j < t.length; j++) {
k=next[j-1];
while (k!=-1) {
if (t[j - 1] == t[k]) {
next[j] = k + 1;
break;
}
else {
k = next[k];
}
next[j] = 0; //当k==-1而跳出循环时,next[j] = 0,否则next[j]会在break之前被赋值
}
}
return next;
}
/**
* 对主串s和模式串t进行KMP模式匹配
* @param s 主串
* @param t 模式串
* @return 若匹配成功,返回t在s中的位置(第一个相同字符对应的位置),若匹配失败,返回-1
*/
public static int kmpMatch(String s, String t){
char[] s_arr = s.toCharArray();
char[] t_arr = t.toCharArray();
int[] next = getNextArray(t_arr);
int i = 0, j = 0;
while (i<s_arr.length && j<t_arr.length){
if(j == -1 || s_arr[i]==t_arr[j]){
i++;
j++;
}
else
j = next[j];
}
if(j == t_arr.length)
return i-j;
else
return -1;
}
public static void main(String[] args) {
System.out.println(kmpMatch("abcabaabaabcacb", "abaabcac"));
}
}
二,矩阵
1.对称矩阵
若n阶矩阵A中的元素满足下述性质:
a[i][j]=a[j][i] 1≦i,j≦n ,则称A为n阶对称矩阵。
2.三角矩阵
主对角线以上全是常数c,叫做下三角矩阵
反之,叫做上三角矩阵。
3.稀疏矩阵
假设m行n列的矩阵含t个非零元素,则非零元素的比例δ=t/(m×n) 称为稀疏因子,通常认为δ≦0.05的矩阵为稀疏矩阵。
三,广义表
广义表是n≥1个元素 a1, a1, …, an 的有限序列,其中每一个ai 或者是原子,或者是一个子表。
表头:若 LS 非空 (n≥1 ),则第一个元素 a1 就是表头。记作 Head(LS) = a1。
注:表头可是原子,也可是子表。
表尾:除表头之外的其它元素组成的表。记作 Tail(LS) = (a2, …, an) 注意空表。
注:表尾不是最后一个元素,而是一个子表。
广义表的性质
- 广义表中的数据元素有相对次序。
- 广义表的长度定义为最外层所包含元素的个数;如:C=(a, (b, c)) 是长度为 2 的广义表。
- 广义表的深度定义为该广义表展开后所含括号的重数;A = (b, c) 的深度为 1,B = (A, d) 的深度为 2,C = (f, B, h) 的深度为 3。
- 广义表可以为其他广义表共享;如:广义表 D 就共享表 A、B、C。在 D中不必列出 A、B、C的值,而是通过名称来引用。
- 广义表可以是递归的表。
如:E=(a, E)=(a, (a, (a, …)))
注意:递归表的深度是无穷值,长度是有限值。 - 广义表是多层次结构,广义表的元素可以是单元素,
也可以是子表,而子表的元素还可以是子表,…。