Cristiano的字符串(BF、KMP算法)和多维数组(矩阵压缩)的总结

一、字符串和数组的基本概念
字符串是以字符作为数据元素的线性表,是重要的非数值处理对象
数组作为一种数据结构,特点是数据元素本身可以具有某种结构,但属于同一数据类型
二、字符串
2.1 字符串的定义
字符串是0个或多个字符组成的有限序列,只包含空格的串称为空格串
2.2 字符串的比较
假设有字符串X,Y,其长度分别为n,m
当下列条件之一成立时,称X<Y
(一)n<m,且Xi = Yi (i = 1,2,3,4…)
(二)存在某个k<=min(m,n),使得Xi = Yi(i = 1,2,3,4…,k-1),且Xk<Yk
e.g: “abcd” = “abcd”;“abc”<“abcd”;“abac”<“anaec”;“abafg”<“abc”
2.3 字符串的存储结构
字符串一般采用顺序存储
2.4 字符串的模式匹配
给定两个字符串S和T,在主串S中寻找子串T的过程称为模式匹配,T称为模式
2.4.1 朴素的模式匹配算法(BF算法)
BF算法的基本思想:从主串S的第一个字符串开始和模式T的第一个字符串进行比较,若相等,则继续比较二者的后续字符;否则,从主串的第二个字符开始和模式T的第一个字符进行比较。直到所有字符串比较完毕
算法:

void connect(char s[],char t[]){
    
    
	int i=0;
	int j=0;
	while(1){
    
    
		if(s[i] == t[j]){
    
    
			i++;
			j++;
			if(t[j] == '\0'){
    
    
				cout<<"匹配成功"<<endl;
				i = i-j+1;   //找到匹配成功时在主串中的初始位置
				cout<<"主串中匹配位置为:"<<i<<endl;
				return ; 
			}
		}else if(s[i] != t[j]){
    
    
			i = i-j+1;  //回溯,回到上次匹配位置的下一个位置
			j = 0;
		}
		if(s[i] == '\0'){
    
    
			cout<<"匹配失败"<<endl;
			return ; 
		}
	}
}

时间性能的分析
(一)最好的情况下,每趟不成功的匹配都发生在模式T的第一个字符
e.g: S = “aaaaaaaaaaabc” ; T = “bc”;
时间复杂度O(m+n);
(一)最坏的情况下,每趟不成功的匹配都发生在模式T的最后一个字符
e.g: S = “aaaaaaaaaaab” ; T = “aaab”;
时间复杂度O(m×n);
2.4.2 改进的模式匹配算法(KMP算法)
KMP算法的基本思想:主串不进行回溯
BF算法的特点是主串回溯;而KMP算法的特点是主串不回溯,子串即模式串回溯
KMP算法:

void connect(char s[],char t[],int next[]){
    
    
	int i=0;
	int j=0;
	int lens = strlen(s);
	int lent = strlen(t);
	while(1){
    
    
		if(s[i] == t[j] || j == -1){
    
    
			i++;
			j++;
			if(j == lent){
    
    
				cout<<"匹配成功"<<endl;
				i = i-j+1;
				cout<<"主串中匹配位置为:"<<i<<endl;
				return ; 
			}
		}else if(s[i] != t[j]){
    
    
			j = next[j];
		}
		if(i == lens){
    
    
			cout<<"匹配失败"<<endl;
			return ; 
		}
	}
}

next数组的实现算法:

	int next[j];	
	int m = -1;    //前缀 
	int n = 0;	   //后缀 
	next[0] = -1;
	while(n<j){
    
    
		if(m == -1 || t[m] == t[n]){
    
    
			m++;
			n++;
			next[n] = m;
		}else{
    
    
			m = next[m];
		}
	}

时间性能的分析
KMP算法的时间复杂度为O(m+n)

三、多维数组
3.1 数组的定义
数组是由类型相同的数据元素构成的有序集合,每一个数据元素成为一个数组元素
二维数组,如:a[x][y] 其中x表示行的数量,y表示列的数量
3.2 矩阵压缩
矩阵压缩的基本思想:①为多个值相同的元素只分配一个存储空间;②对零元素不分配存储空间
3.2.1 对称矩阵的压缩
令i,j分别为在矩阵中对应的位置,k为每个矩阵元素在一维数组中对应的元素下标
若是下三角矩阵,则:k = i*(i - 1)/2+j-1;
若为上三角矩阵,则:k = j*(j - 1)/2+i-1;
3.2.2 三角矩阵的压缩
令i,j分别为在矩阵中对应的位置,k为每个矩阵元素在一维数组中对应的元素下标
若是下三角矩阵,则:k = i*(i - 1)/2+j-1(i<=j时),k = n*(n+1)/2 (i>j);
若为上三角矩阵,则:k = j*(j - 1)/2+i-1(i<=j时),k = n*(n+1)/2 (i>j);
3.2.3 对角矩阵的压缩
令i,j分别为在矩阵中对应的位置,k为每个矩阵元素在一维数组中对应的元素下标
则:k = 2*i+j-3;
3.2.4 稀疏矩阵的压缩存储
3.2.4.1 三元组顺序表
思路:
1、首先创建一个结构体,用于存储每个非零矩阵元素的下标和数值

typedef struct element{
    
    
	int row,col;              //三元组的行号、列号 
	int item;                 //三元组的值 
}Element;

2、再创建一个结构体数组,每个数组元素包含了row,col和item值,存入数据元素的代码:

void TripleMatrix::setItem(int row,int col,int item){
    
    
	if(item == 0){
    
    
		cout<<"不用存入"<<endl;
		return;
	}else if(tu>=(mu*nu)){
    
    
		cout<<"矩阵已满"<<endl;
		return;
	}else{
    
    
		int i = 0;
		if(tu==0){
    
                       //初始时,对第一个元素赋值 
			data[tu].row = row;
			data[tu].col = col;
			data[tu].item = item;
			tu++;
		}else{
    
    
			while(i<tu){
    
                      //循环判断,找到合适的位置插入到其中 
				if(data[i].row<row )      //跟当前位置的元素比较,如果要插入的元素的row比当前的要小,则退出,插入到这个位置;否则就加一   
					i++;
				else if(data[i].row == row && data[i].col < col) //如果要插入的元素的row与当前的row相同,比较col的值,如果小一些,则退出;否则就加一 
					i++;
				else
					break;
			}
			if((data[i].col == col) && (data[i].row == row))  //如果row与col的值相同,则覆盖 
				data[i].item = item;
			else{
    
    
				for(int j=tu;j>i;j--)
					data[j] = data[j-1];
				data[i].row = row;
				data[i].col = col;
				data[i].item = item;
				tu++;
			}
		}
	}
}

3.2.4.2 十字链表法

3.2.5 矩阵的加法

bool MatrixAdd(TripleMatrix a,TripleMatrix b,TripleMatrix& c){
    
    
	if(a.mu != b.mu || a.mu != c.mu ||a.nu != b.nu ||a.nu != c.nu ){
    
    
		return false;
	}else{
    
    	
		for(int i=1;i<=a.mu;i++){
    
    
			for(int j=1;j<=a.nu;j++){
    
    
				int item = a.getItem(i,j) + b.getItem(i,j);
				if(item!=0)
					c.setItem(i,j,item);
			}
		}
		c.printTripleMatrix();
		return true;
	}
} 

3.2.6 矩阵的乘法

bool MatrixMulty(TripleMatrix a,TripleMatrix b,TripleMatrix& c){
    
    
	int item = 0; 
	if(a.mu != b.nu || a.mu != c.mu ||a.nu != b.mu ||b.nu != c.nu ){
    
    
		//矩阵 c 的行数由矩阵 a 的行数决定  矩阵 c 的列数由矩阵 b 的列数决定  
		return false;
	}else{
    
    			
		for(int i=1;i<=a.mu;i++){
    
     // 控制矩阵a的行数的变化 
			for(int j=1;j<=b.nu;j++){
    
      //控制矩阵b的列数的变化 
				for(int z=1;z<=b.mu;z++){
    
      //矩阵a的每一行的列元素  以及控制矩阵b的每一列的行元素 
					item = item + a.getItem(i,z) * b.getItem(z,j);
				}
				if(item!=0)
					c.setItem(i,j,item);
				item = 0;
			}	
		
		}
		c.printTripleMatrix();
		return true;
	}
} 

猜你喜欢

转载自blog.csdn.net/Cristiano_san/article/details/106842651