数组和广义表,稀疏矩阵

考点:广义表的长度和深度,稀疏矩阵的相关操作

广义表:LA=(A1,A2,…,An),LA为表名,n为表长,其中Ai可以是单个元素,亦可以是广义表,分别称为 原子和子表。A1为表头,(A2,…An)为表尾

1:广义表表长:原子的个数(此时要把最大子表广义归结为原子)
2:广义表深度:括弧的重数,空表深度为1
3:已知广义表A=((a,b,c),(d,e,f)),从表中取e的运算:
分解:tail(A)=((d,e,f)),head(tail(A))=(d,e,f),
tail(head(tail(A)))=(e,f),head(tail(head(tail(A))))=e

考的不多,代码就不写了呀
稀疏矩阵

1:定义:σ=tu /(mu*nu),σ<=0.05,tu为非零元个数,mu为行数,nu为列数

 #define MAXSIZE 12500
 #define MAXRC   500
 #define Error   -1
 
 #define ok      0
 #define N       5
 #define a       4
 #define b       5
 #define c       3
 typedef int Elemtype;
 typedef int Status;
 Elemtype i=0,j=0,e=0; //全局变量 为将来替换 a b c做准备 
 typedef  struct {
 	int i,j;//行列下标 
 	int e;
 }Triple;//三元组结构体
 
 typedef struct{
 	Triple data[MAXSIZE+1];
 	int rpos[MAXRC];/*用来保存第i行中第一个非0元在三元组的序号*/ 
 	int mu,nu,tu;//行号 列号的个数, 非0元个数 
 }RLMatrix; 
//因为严蔚敏奶奶版的数组下标是从1开始的故而重设了行下标全为0的第一行和列下标=0第一列
Elemtype M[a][b]={{0,0,0,0,0},{0,3,0,0,5},{0,0,-1,0,0},{0,2,0,0,0}};
Elemtype NN[b][c]={{0,0,0},{0,0,2},{0,1,0},{0,-2,4},{0,0,0}};
//------------普通矩阵转换成三元组(同时还要建立rpos矩阵)----------------//
Status OrdinaryMatrix2RLMatrix(Elemtype Ordinary[i][j],RLMatrix *A){
	int l=1,m=1,k=1;
       (*A).mu=0;(*A).nu=0;(*A).tu=0;
            //第0行第一个非0元的序号 
	   for(l=1;l<i;l++)//统计行总数  不为空 
	   {printf("\n");
	    (*A).mu=l;
	    (*A).rpos[l]=k; //第l行第一个非0元在三元组排列的序号 
		   for(m=1;m<j;m++) {
		   	(*A).nu=m;
		   if(Ordinary[l][m]!=0){
		   (*A).data[k].e=Ordinary[l][m];
		   (*A).data[k].i=l;//
		   (*A).data[k].j=m;
		   printf("该矩阵.data[%d].%d.%d=%d\n",k,(*A).data[k].i,(*A).data[k].j,(*A).data[k].e); 
		   k++;
		     } 
		   }
		   printf("rpos[%d]=%d\n",l,(*A).rpos[l]);
        }
        (*A).tu=k-1;   
        printf("A.mu=%d A.nu=%d A.tu=%d",(*A).mu,(*A).nu,(*A).tu);
	return ok;
}

M Matrix的三元组表示
在这里插入图片描述在这里插入图片描述N矩阵的三元组
在这里插入图片描述稀疏矩阵的乘法: rpos[]数组很重要

Status MultSMatrixTEST(RLMatrix *M,RLMatrix *N1,RLMatrix *Q){//Q=M*N
        int tp=0,t=0,mrow=0,nrow=0,Qcol=0,p=0,q=0;
        (*Q).rpos[a*c],Elemtype ctemp[a*c]={0};
        if((*M).nu!=(*N1).mu) return Error; //不满足矩阵的乘法原则
        for(mrow=1;mrow<=(*M).mu;mrow++){//找到每一行的非0元来做乘法
           ctemp[mrow]=0;//设当前行的累加器清零  比如说一个行内有两个非0元 做矩阵乘法就需要先乘后加
           (*Q).rpos[mrow]=(*Q).tu+1;//记录Q每一行第一个非0元在Q.data的位置
           if(mrow<(*M).mu) tp=(*M).rpos[mrow+1];//1
           else tp=(*M).tu+1;//2  (1,2,3)的作用是:(*M).rpos[mrow+1]-(*M).rpos[mrow]=找齐当前行非0元的个数
           for(p=(*M).rpos[mrow];p<tp;p++){//3 for来遍历一行的每一个非零元
               nrow=(*Q).data[p].j;//M的j等于N的i
               if(nrow<(*N1).mu) t=(*N1).rpos[nrow+1];//1
               else t=(*N1).tu+1;//2  1,2,3//找齐M的列对应在N的行号
               for(q=(*N1).rpos[nrow];q<t;q++){//3 该列每一个非零元
               	Qcol=(*N1).data[q].j;//乘积元素在Q的列号
			    printf("Qcol=%d",Qcol);
				ctemp[Qcol]+=(*M).data[p].e*(*N1).data[q].e;	
				printf("\nM.data[%d].%d.%d.%d*N1.data[%d].%d.%d.%d=ctemp[%d]=%d\n",p,(*M).data[p].i,(*M).data[p].j,(*M).data[p].e,q,(*N1).data[q].i,(*N1).data[q].j,(*N1).data[q].e,Qcol,ctemp[Qcol]);
               }//for q
           }//for p
    printf("\n--------------分割线-----------\n");
    for(Qcol=1;Qcol<=(*Q).nu;++Qcol){//save 该非0元
	    if(ctemp[Qcol]) {//总共就存在这么多个
		   if(++(*Q).tu>MAXSIZE) return Error;
		   (*Q).data[(*Q).tu].e=ctemp[Qcol]; 
	    	 (*Q).data[(*Q).tu].i=mrow; 
			 (*Q).data[(*Q).tu].j=Qcol;
			 printf("Q.data[%d].%d.%d=%d\n",(*Q).tu,mrow,Qcol,(*Q).data[(*Q).tu].e);
		    }   
          }
       }//for mrow
return ok;
}

void test(){
       	TSMatrix A;
  	TSMatrix T;
  	RLMatrix M1;
  	RLMatrix N1;
  	RLMatrix Q; 
 
  		

//   
    printf("NN矩阵如下:\n");
	for(i=0;i<b;i++){
  		for(j=0;j<c;j++)
  	    printf("%2d",NN[i][j]);
  	    printf("\n");
	  }   
	OrdinaryMatrix2RLMatrix(NN,&N1);//M-->M1普通矩阵转化成三元组M1 
	
	printf("\nM矩阵如下:\n");
	for(i=0;i<a;i++){
  		for(j=0;j<b;j++)
  	    printf("%2d",M[i][j]);
  	    printf("\n");
	  }   
	OrdinaryMatrix2RLMatrix(M,&M1);
//	printf("\n--------------------Q-----------------\n");
	MultSMatrixTEST(&M1,&N1,&Q);
}

矩阵加法不宜使用三元组结构,故而使用十字链表;为什么不宜呢?譬如把B三元组矩阵加入到A三元组矩阵,那么就会破坏A三元组矩阵的结构(A矩阵的0元在A三元组表示里面是没有位置的)
在这里插入图片描述

typedef struct OLNode{
 	int i,j;
 	Elemtype e;
 	struct OLNode *right ,*down;//该非0元所在行表和列表的后继链域 
 	
 }OLNode,*OLink;//头结点,头指针 
 
 typedef struct{
 	OLink *chead,*rhead;//行和列链表 头指针向量基地址 由createSMatrix分配
	int mu,nu,tu;//稀疏矩阵的行列非0元的总个数 
 }CrossList; 
 Status CreateSMatrix_OL(CrossList *M){//M只有行指针和列指针 
	int k=0;
     i=1;
    OLink p=NULL,q=NULL;//q是工具结点
     p = (OLink) malloc (sizeof(OLNode));
     q = (OLink) malloc (sizeof(OLNode)); //开辟内存   
    printf("\n输入M的行数,列数 非0元个数\n");
	scanf("%d,%d,%d",&(M->mu),&(M->nu),&(M->tu));//M的行数,列数 非0元个数
	printf("\ntesting");
	M->rhead=(OLink *)malloc((M->mu+1)*sizeof(OLink));//开辟那么大的的内存 
	M->chead=(OLink *)malloc((M->nu+1)*sizeof(OLink));

    for(k=1;k<=M->mu;k++)M->rhead[k]=NULL;//初始化行列头指针向量,各行列链表为	
	for(k=1;k<=M->nu;k++)M->chead[k]=NULL;
	printf("\n输入行列非0元值:\n");
	for(scanf("%d,%d,%d",&i,&j,&e);i!=0;scanf("%d,%d,%d",&i,&j,&e)){
		printf("\n输入行列非0元值:\n");
		if(!(p=(OLNode *)malloc(sizeof(OLNode)))) return Error;
		p->i=i,p->j=j,p->e=e;
		p->down=NULL,p->right=NULL;
		if(M->rhead[i]==NULL||M->rhead[i]->j>j){//开头第一个 或者是同行的 但是前一个插入得比较右边 
			p->right=M->rhead[i];//先指向空 
			M->rhead[i]=p;//M的头指针指向p 
		}
		else {
			for(q=M->rhead[i];(q->right)&&q->right->j<j;q=q->right) ;//M->rhead[i]是上一个行指针所指结点 q->right是应到结点,q是上一结点  (向右攀爬) 
		    p->right=q->right;
			q->right=p;//p是新结点 q->right是指定位置  
 
		}
	//--------down是用来处理行的,因为对于十字链表来说列已经确定了	
		if(M->chead[j]==NULL||M->chead[j]->i>i){//开头or同列 或者前一个比较下边 
			p->down=M->chead[j];//p->down 先指向空 
			M->chead[j]=p;//指向 新节点 
		} 
		else{
			for(q=M->chead[j];(q->down)&&q->down->i<=i;q=q->down);//M->chead[i]是上一个列指针所指结点 q->down是应到结点,q是上一结点  (向下攀爬) 
			p->down=q->down;
			q->down=p;//p是新结点 q->down是指定位置 
			 	
		} 	
	}
} 
Status  RowVisitCrossList(CrossList *M){//用行来遍历十字链表
      int i=0;OLNode *p=NULL;//定义结构体指针
	  p=(OLink)malloc(sizeof(OLNode)) ;
	  for(i=1;i<=M->mu;i++){
	  	p=M->rhead[i];
	  	while(p!=NULL){
	  		printf("当前正在遍历第%d行第%d列的元素:%d\n",p->i,p->j,p->e);
	  		p=p->right;
		  }
		  printf("\n");
	  }
	
}
Status ColVisitCrossList(CrossList *M){//用列来遍历十字链表
	int j=0;
	OLink p=NULL;
	p=(OLNode *)malloc(sizeof(OLNode));///分配地址 
	for(j=1;j<=M->nu;j++){
		p=M->chead[j];
		while(p!=NULL){
			printf("当前正在遍历第%d行第%d列的元素:%d\n",p->i,p->j,p->e);
			p=p->down;
		}
		printf("\n");
	}
}
Status MatrixAdd(CrossList *M,CrossList *S){//将M元素加入S里面 
	  int i=0;OLNode *p=NULL,*q=NULL;//定义结构体指针
	  p=(OLink)malloc(sizeof(OLNode)) ;
	  q=(OLink)malloc(sizeof(OLNode)) ;
	  for(i=1;i<=M->mu;i++){//行遍历那就 用列来做加法 
	  	p=M->rhead[i];
	  	while(p!=NULL){ 
	  		printf("当前正在遍历M的第%d行第%d列的元素:%d\n",p->i,p->j,p->e);

			printf("S->rhead[p->i]->i=%d,S->chead[p->j]->j=%d\n",S->rhead[p->i]->i,S->chead[p->j]->j);
		if(S->rhead[p->i]->i==p->i&&S->chead[p->j]->j==p->j){
			   for(q=S->chead[p->j];(q->down)&&q->down->i<=p->i;q=q->down);
			    q->e+=p->e;///主要解决指针不下移动问题 chead[p->j]andq->down->i<=p->i 
			    printf("AllADD\n");
			}
		else{
				if(S->rhead[p->i]==NULL||S->rhead[p->i]->j>p->j){//开头第一个 或者是同行的 但是前一个插入得比较右边 
			p->right=M->rhead[i];//先指向空 或者指向先前比较右边的那个 
			S->rhead[p->i]=p;//M的头指针指向p  
		        }
				else {//按正常顺序 左边--》右边 
					for(q=M->rhead[p->i];(q->right)&&q->right->j<p->j;q=q->right) ;//M->rhead[i]是上一个行指针所指结点 q->right是应到结点,q是上一结点  (向右攀爬) 
					p->right=q->right;//此时是q->right为NULL   让新的结点右域指向空 
					q->right=p;//p是新结点 q->right是指定位置(结点连接) 
					}
				//--------down是用来处理行的,因为对于十字链表来说列已经确定了	
				if(S->chead[p->j]==NULL||S->chead[p->j]->i>p->i){//开头or同列 或者前一个比较下边 
						p->down=S->chead[p->j];//p->down 先指向空  或者指向先前(比较下的)那个 
						S->chead[p->j]=p;//指向 新节点 
					} 
				else{
					for(q=S->chead[p->j];(q->down)&&q->down->i<=p->i;q=q->down);//S->chead[i]是上一个列指针所指结点 q->down是应到结点,q是上一结点  (向下攀爬) 
					p->down=q->down;//新结点指向空 
					q->down=p;//p是新结点 q->down是指定位置(结点连接) 
	
					}     
		  }
		  p=p->right;
		  printf("\n");
	  }
   }
}

void test(){
   CrossList M;
   CrossList S;
  CreateSMatrix_OL(&M);
  CreateSMatrix_OL(&S);
  printf("\n--------------M的元素如下-----------\n");
  ColVisitCrossList(&M);
  printf("\n--------------S的元素如下-----------\n");
  ColVisitCrossList(&S);
  printf("\n------------------------------------\n");
  MatrixAdd(&M,&S);
  printf("\n----------下面遍历改变后的S----------\n");
  RowVisitCrossList(&S); 

}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值