一.上机内容
1、实现串的模式匹配算法。
2、实现稀疏矩阵的三元组表压缩存储方法
3 *、三元组表压缩存储方法基础上实现稀疏矩阵的转置,主要涉及矩阵中每一行非零元素的个数的求解方法和转置矩阵的每一行中的第一个元素在其三元组表中的存储位置的计算。
二.代码实现
1、实现串的模式匹配算法。
1.Brute-Force模式匹配算法
/**
* 返回模式串t在主串从start开始的第一次匹配位置,匹配失败返回-1
* @param t
* @param start
* @return
*/
public int indexof_BF(IString t,int start){
// 当主串比模式串长的时候才开始比较
if (this!=null && t!= null && t.length() > 0 && this.length > t.length()) {
// i表示主串中某个子串的序号
int slen, tlen, i = start, j = 0;
// 主串的长度
slen = this.length();
// 匹配串的长度
tlen = t.length();
// i和j都在比较范围内
while ((i < slen) && (j < tlen)) {
// j为模式串当前字符的下标
if (this.charAt(i) == t.charAt(j)) {
i++;
j++;
} else {
// 继续比较主串中的下一个子串
// i-j+1就是在本次比较前,往后走一个字符
i = i - j + 1;
// 模式串下标退回0
j = 0;
}
}
// 如果匹配成功,返回子串序号
// 运行到这里,不一定是j超出了范围,还有可能是i超出了范围,i超出范围但是j没有,说明匹配失败
if (j >= t.length()) {
return i - tlen;
} else {
return -1;
}
}
return -1;
}
2.KMP模式匹配算法
/**
* next[j]函数
* @param T
* @return 返回模式串的next[j]数组
*/
public int[] getNext(IString T){
// next[]数组
int[] next = new int[T.length()];
//主串指针
int j = 1;
// 模式串指针
int k = 0;
next[0] = -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[]
* @param T
* @return
*/
private int[] getNextVal(IString T){
// nextVal数组
int[] nextVal = new int[T.length()];
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;
}
/**
* 模式匹配KMP算法
* @param T
* @param start
* @return
*/
public int index_KMP(IString T,int start){
int[] next = getNext(T);
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[i]!=T[0],那么i和j都要后移一位,这样j就变成第一位了
i++;
j++;
}else {
// 模式串后移
j = next[j];
}
}
if (j < T.length()){
// 匹配失败
return -1;
}else {
// 匹配成功
return i - T.length();
}
}
2、实现稀疏矩阵的三元组表压缩存储方法
/**
* 初始化三元组顺序表
* @param mat 一个普通的二元数组
*/
public SparseMatrix(int mat[][]){
int i,j,k = 0,count =0;
// 行数
rows = mat.length;
// 列数
cols = mat[0].length;
// 统计非零元素个数
for(i = 0;i <mat.length;i++){
for ( j = 0; j < mat[i].length; j++) {
if (mat[i][j] != 0){
count++;
}
}
}
//非零元素的个数
nums = count;
// 申请三元节点空间
data = new TripleNode[nums];
for (i = 0;i<mat.length;i++){
for (j = 0; j < mat[i].length;j++){
if (mat[i][j] != 0){
// 建立三元组
data[k] = new TripleNode(i,j,mat[i][j]);
// 计数器
k++;
}
}
}
}
3 *、三元组表压缩存储方法基础上实现稀疏矩阵的转置,主要涉及矩阵中每一行非零元素的个数的求解方法和转置矩阵的每一行中的第一个元素在其三元组表中的存储位置的计算。
1.转置
/**
* 矩阵转置
* @return
*/
public SparseMatrix transpose(){
// 创建转置矩阵对象
SparseMatrix tm = new SparseMatrix(nums);
// 行数改为列数,列数改行数,非零个数不变
tm.rows = cols;
tm.cols = rows;
tm.nums = nums;
int q = 0;
for (int col = 0 ; col < cols;col++){
for (int p = 0; p < nums;p++){
// 外层循环是按列的大小,所以这样是按列从小到大来寻找非零元素
// 遍历三元组这个一维数组
if (data[p].column == col){
// 转置
tm.data[q].row = data[p].column;
tm.data[q].column = data[p].row;
tm.data[q].value = data[p].value;
// 计数器
q++;
}
}
}
return tm;
}
2.快速转置
/**
* 矩阵快速转置算法
* @return
*/
public SparseMatrix fastTranspose(){
// 创建矩阵对象
SparseMatrix tm = new SparseMatrix(nums);
// 行数变为列数
tm.cols = rows;
// 列数变为行数
tm.rows = cols;
// 非零元素个数不变
tm.nums = nums;
int i,j = 0,k = 0;
int[] num,cpot;
if (nums > 0){
num = new int[cols];
cpot = new int[cols];
// 每列非零元素个数数组num初始化
for (i = 0; i < cols; i++) {
num[i] = 0;
}
// 计算每列非零元素个数
for (i = 0; i <nums;i++){
j = data[i].column;
num[j]++;
}
cpot[0] = 0;
for (i = 1; i < cols;i++){
cpot[i] = cpot[i-1] + num[i+1];
}
// 执行转置操作
for (i = 0; i < nums;i++){
// 扫描整个三元组顺序表
j = data[i].column;
// 该元素在tm中的位置
k = cpot[j];
// 转置
tm.data[k].row = data[i].column;
tm.data[k].column = data[i].row;
tm.data[k].value = data[i].value;
// 该列下一个非零元的存放位置
cpot[j]++;
}
}
return tm;
}