chapter 2_arrays
文章目录
一、多项式抽象数据类型
1、多项式的ADT定义
class Polynomial
{
private:
int degree; //degree<=MaxDegree
float coef[MaxDegree+1]; //系数数组
public:
Polynomial(); //构造函数
float Eval(float x); //计算多项式数值
Polynomial Add(Polynomial ploy); //多项式加法
Polynomial Mult(Polynomial poly); //多项式乘法
};
若degree<<MaxDegree,coef[ ]的大多位置不会被占用,可以做出如下改进
class Polynomial
{
private:
int degree; //degree<=MaxDegree
float *coef; //系数数组
...
};
若为稀疏多项式,则仅存储非零项,可以做出如下改进
class Term //数组元素
{
friend Polynomial;
private:
float coef; //系数
int exp; //指数
...
}
class Polynomial //数组
{
Term* termArray; //非零项数组
int terms; //非零项数
int capacity; //最大容量
...
};
2、计算多项式数值
float Polynomial::Eval(float x)
{
int temp=0;
for(int i=0;i<this->terms;i++)
{
temp+=this->termArray[i].coef*pow(x,this->termArray[i].exp);
}
return temp;
}
3、多项式加法
void Polynomial::TailInsertTerm(float coef,int exp) //尾插节点
{
if(this->terms==this->capacity){ //及时扩容
this->capacity*=2;
Term* tempTerm=new Term[this->capacity];
for(int i=0;i<this->terms;i++)tempTerm[i]=this->termArray[i];
delete[]this->termArray;
this->termArray=tempTerm;
}
this->termArray[terms].exp=exp;
this->termArray[terms++].coef=coef;
}
Polynomial Polynomial::Add(Polynomial poly)
{
Polynomial tempPoly;
int aPos=0,bPos=0; //记录this->terms与poly的下标
while(aPos<this->terms&&bPos<poly.terms)
{
if(this->termArray[aPos].exp==poly.termArray[bPos].exp){
if(this->termArray[aPos].coef+poly.termArray[bPos].coef!=0) //指数相同且系数和非0
tempPoly.TailInsertTerm(this->termArray[aPos].coef+poly.termArray[bPos].coef,this->termArray[aPos].exp);
aPos++,bPos++;
}
else if(this->termArray[aPos].exp<poly.termArray[bPos].exp) //存入指数更小的系数
tempPoly.TailInsertTerm(this->termArray[aPos].coef,this->termArray[aPos].exp),aPos++;
else
tempPoly.TailInsertTerm(poly.termArray[bPos].coef,poly.termArray[bPos].exp),bPos++;
}
while(aPos<this->terms&&tempPoly.terms<=tempPoly.capacity) //拷贝数组剩余元素
{
tempPoly.TailInsertTerm(this->termArray[aPos].coef,this->termArray[aPos].exp),aPos++;
}
while(bPos<poly.terms&&tempPoly.terms<=tempPoly.capacity) //拷贝数组剩余元素
{
tempPoly.TailInsertTerm(poly.termArray[bPos].coef,poly.termArray[bPos].exp),bPos++;
}
return tempPoly;
}
4、多项式乘法
void Polynomial::InsertTerm(float coef,int exp) //插入节点
{
if(this->terms==this->capacity){ //及时扩容
this->capacity*=2;
Term* tempTerm=new Term[this->capacity];
for(int i=0;i<this->terms;i++){
tempTerm[i]=this->termArray[i];
}
delete[]this->termArray;
this->termArray=tempTerm;
}
int idx=this->terms; //标记插入节点位置
for(int i=0;i<this->terms-1;i++){
if(this->termArray[i].exp==exp){
idx=i;break;
}
if(this->termArray[i].exp<exp&&this->termArray[i+1].exp>exp){
idx=i+1;break;
}
}
if(this->termArray[0].exp>=exp)idx=0;
if(this->termArray[terms-1].exp==exp)idx=terms-1;
if(this->termArray[idx].exp==exp){ //查找到指数相同节点
this->termArray[idx].coef+=coef;
if(this->termArray[idx].coef==0){ //若系数和为零
for(int i=idx;i<this->terms-1;i++)this->termArray[i]=this->termArray[i+1];
this->terms--;
}
}
else{ //未查找到指数相同节点
for(int i=this->terms;i>idx;i--){
this->termArray[i]=this->termArray[i-1];
}
this->termArray[idx].exp=exp;
this->termArray[idx].coef=coef;
this->terms++;
}
}
Polynomial Polynomial::Mult(Polynomial poly)
{
Polynomial tempPoly;
int coef=0,exp=0;
for(int i=0;i<this->terms;i++){
for(int j=0;j<poly.terms;j++){
coef=this->termArray[i].coef*poly.termArray[j].coef;
exp=this->termArray[i].exp+poly.termArray[j].exp;
tempPoly.InsertTerm(coef,exp);
}
}
return tempPoly;
}
二、稀疏矩阵
1、稀疏矩阵的ADT定义
class MatrixTerm //稀疏矩阵元素
{
friend SparseMatrix;
private:
int row; //行
int col; //列
int value; //元素数值
};
class SparseMatrix //稀疏矩阵
{
private:
MatrixTerm* termArray; //非零项数组
int rows; //总行数
int cols; //总列数
int terms; //非零项数
int capacity; //最大容量
public:
SparseMatrix(int r,int c,int t); //创建一个有r行c列,可以容纳t个非0项的SparseMatrix
SparseMatrix Transpose(); //矩阵转置
SparseMatrix Add(SparseMatrix matrix); //矩阵加法
SparseMatrix Mult(SparseMatrix matrix); //矩阵乘法
};
2、矩阵转置
SparseMatrix SparseMatrix::Transpose()
{
SparseMatrix temp=SparseMatrix(this->cols,this->rows,this->terms);
if(this->terms) {
int counter=0;
for(int i=0;i<this->cols;i++){
for(int j=0;j<this->terms;j++){
if(this->termArray[j].col==i){
temp.termArray[counter].row=i;
temp.termArray[counter].col=this->termArray[j].row;
temp.termArray[counter++].value=this->termArray[j].value;
}
}
}
}
return temp;
}
在terms达到rowscols的数量级时,Transpose的运行时间达到O(rowcol^2),用时过长,以下给出快速转置的方法
SparseMatrix SparseMatrix::FastTranspose()
{
SparseMatrix temp=SparseMatrix(this->cols,this->rows,this->terms);
if(terms>0){
int* rowStart=new int[this->cols]{};
int* rowSize=new int[this->cols]{};
for(int i=0;i<this->terms;i++)rowSize[this->termArray[i].col]++;
for(int i=1;i<this->cols;i++)rowStart[i]=rowStart[i-1]+rowSize[i-1];
for(int i=0;i<this->terms;i++){
temp.termArray[rowStart[this->termArray[i].col]++]=this->termArray[i];
swap(temp.termArray[rowStart[this->termArray[i].col]-1].col,temp.termArray[rowStart[this->termArray[i].col]-1].row);
}
delete[]rowSize;
delete[]rowStart;
}
return temp;
}
3、矩阵加法
void SparseMatrix::TailInsertTerm(int row,int col,int value)
{
if (this->terms == this->capacity)
{
this->capacity *= 2;
MatrixTerm* tempTerm = new MatrixTerm[this->capacity];
for (int i = 0; i < this->terms; i++) {
tempTerm[i] = this->termArray[i];
}
delete[]this->termArray;
this->termArray = tempTerm;
}
this->termArray[terms].row=row;
this->termArray[terms].col=col;
this->termArray[terms].value=value;
this->terms++;
}
SparseMatrix SparseMatrix::Add(SparseMatrix matrix)
{
if(this->rows!=matrix.rows||this->cols!=matrix.cols){
throw"Incompatible matrices";
}
SparseMatrix tempSparseMatrix{this->rows,matrix.cols,0};
int apos=0,bpos=0;
while(apos<this->terms&&bpos<matrix.terms)
{
if(this->termArray[apos].row<matrix.termArray[bpos].row){
tempSparseMatrix.InsertTerm(this->termArray[apos].row,this->termArray[apos].col,this->termArray[apos].value);apos++;
}
else if(this->termArray[apos].row>matrix.termArray[bpos].row){
tempSparseMatrix.InsertTerm(matrix.termArray[bpos].row,matrix.termArray[bpos].col,matrix.termArray[bpos].value);bpos++;
}
else if(this->termArray[apos].col<matrix.termArray[bpos].col){
tempSparseMatrix.InsertTerm(this->termArray[apos].row,this->termArray[apos].col,this->termArray[apos].value);apos++;
}
else if(this->termArray[apos].col>matrix.termArray[bpos].col){
tempSparseMatrix.InsertTerm(matrix.termArray[bpos].row,matrix.termArray[bpos].col,matrix.termArray[bpos].value);bpos++;
}
else{
tempSparseMatrix.InsertTerm(matrix.termArray[bpos].row,matrix.termArray[bpos].col,this->termArray[apos].value+matrix.termArray[bpos].value);apos++,bpos++;
}
}
while(apos<this->terms)
{
tempSparseMatrix.InsertTerm(this->termArray[apos].row,this->termArray[apos].col,this->termArray[apos].value);apos++;
}
while(bpos<matrix.terms)
{
tempSparseMatrix.InsertTerm(matrix.termArray[bpos].row,matrix.termArray[bpos].col,matrix.termArray[bpos].value);bpos++;
}
return tempSparseMatrix;
}
4、矩阵乘法
void SparseMatrix::InsertTerm(int row, int col, int value)
{
if (this->terms == this->capacity) //及时扩容
{
this->capacity *= 2;
MatrixTerm* tempTerm = new MatrixTerm[this->capacity];
for (int i = 0; i < this->terms; i++) {
tempTerm[i] = this->termArray[i];
}
delete[]this->termArray;
this->termArray = tempTerm;
}
if(row==this->termArray[terms-1].row&&col==this->termArray[terms-1].col){ //与前项位置相同
this->termArray[terms-1].value+=value;
if(!this->termArray[terms-1].value)this->terms--; //系数和为零
}
else{ //与前面项位置不同
this->termArray[terms].row = row;
this->termArray[terms].col = col;
this->termArray[terms].value = value;
this->terms++;
}
}
SparseMatrix SparseMatrix::Mult(SparseMatrix matrix)
{
if(this->cols!=matrix.rows){
throw"Incompatible matrices";
}
SparseMatrix tempSparseMatrix{ this->rows,matrix.cols,0};
matrix=matrix.FastTranspose();
for (int i = 0; i < this->terms; i++) {
for (int j = 0; j < matrix.terms; j++) {
if(this->termArray[i].col==matrix.termArray[j].col){
tempSparseMatrix.InsertTerm(this->termArray[i].row, matrix.termArray[j].row, this->termArray[i].value * matrix.termArray[j].value);
}
}
}
return tempSparseMatrix;
}
三、字符串抽象数据类型
1、字符串的ADT定义
class String
{
private:
char* str;
public:
String(char* init,int m);
bool operator==(string t); //判断*this字符串是否等于t
bool operator!(); //若*this为空返回true
int Length(); //返回字符数目
int Find(String pat); //字符串匹配
String Concat(String t); //将t连接为*this字符串的后缀
String Substr(int i,int j); //返回i到j-i+1共计j个字符串
};
2、字符串匹配
int String::Find(String pat)
{
for(int start=0;start<=Length()-pat.Length();start++){
int j;
for(j=0;j<pat.Length()&&str[start+j]==pat.str[j];j++){
if(j==pat.Length()-1){
return start;
}
}
}
return -1;
}
KMP(Knuth-Morris-Pratt)算法
当文本串与模式串不匹配时,无需从头重复遍历,可以直接跳转
时间复杂度为O(n+m),其中n是文本串(this->str)的长度,m是模式串(pat.str)的长度
/*
s ...a b c a ? ? ...
pat a b c a b c a c a b
i 0 1 2 3 4 5 6 7 8 9
f -1 -1 -1 0 1 2 3 -1 0 1
*/
void String::FailureFunction() //获取失配函数
{
this->f=new int[this->Length()];
f[0]=-1;
for(int i=1;i<this->Length();i++)
{
if(this->str[i]==this->str[f[i-1]+1]){
this->f[i]=this->f[i-1]+1;
}
else{
this->f[i]=-1;
}
}
}
int String::FastFind(String pat)
{
int posP=0,posS=0;
while(posP<pat.Length()&&posS<this->Length()){
if(this->str[posS]==pat.str[posP])
posS++,posP++;
else{
if(posP==0)
posS++;
else{
posP=pat.f[posP-1]+1;
}
}
}
if(posP=pat.Length())
return posS-posP;
return -1;
}
四、多维数组
一维数组a[m1]
Loc[i]=a+i
二维数组a[m1][m2]
Loc[i,j]=a+i* m2+j
三维数组a[m1][m2][m3]
Loc[i,j,k]=a+i* m2* m3+j* m3+k