7-1 稀疏矩阵 (30 分)

 

如果一个矩阵中,0元素占据了矩阵的大部分,那么这个矩阵称为“稀疏矩阵”。对于稀疏矩阵,传统的二维数组存储方式,会使用大量的内存来存储0,从而浪费大量内存。为此,可以用三元组的方式来存放一个稀疏矩阵。

对于一个给定的稀疏矩阵,设第r行、第c列值为v,且v不等于0,则这个值可以表示为 <r,v,c>。这个表示方法就称为三元组。那么,对于一个包含N个非零元素的稀疏矩阵,就可以用一个由N个三元组组成的表来存储了。

如:{<1, 1, 9>, <2, 3, 5>, <10, 20, 3>}就表示这样一个矩阵A:A[1,1]=9,A[2,3]=5,A[10,20]=3。其余元素为0。

要求查找某个非零数据是否在稀疏矩阵中,如果存在则输出其所在的行列号,不存在则输出ERROR。

输入格式:

共有N+2行输入: 第一行是三个整数m, n, N(N<=500),分别表示稀疏矩阵的行数、列数和矩阵中非零元素的个数,数据之间用空格间隔; 随后N行,输入稀疏矩阵的非零元素所在的行、列号和非零元素的值; 最后一行输入要查询的非0数据k。

输出格式:

如果存在则输出其行列号,不存在则输出ERROR。

输入样例:

在这里给出一组输入。例如:

10 29 3
2 18 -10
7 1 98
8 10 2
2

输出样例:

在这里给出相应的输出。例如:

8 10

解题思路:实际上这道题用三元组写轻松解决,但是这里想讲的是十字链表;
十字链表的图大致如下:
(原创)数据结构之十字链表总结-冯金伟博客园
那么如何去实现呢;
看以下代码:因为下面都有注释,这里便不赘述了。
  1 #include<iostream>
  2 #include<stdio.h>
  3 using namespace std;
  4 
  5 struct OLNod{
  6     int i ;   //该非零元的行下标; 
  7     int j ;   //该非零元 的列下标; 
  8     int value ;   //该非零元的数值;
  9     struct OLNod *right ,*down ;//该非零元所在的行表和列表的后继链域; 
 10 };
 11 struct CrossL{
 12     OLNod **rhead, **sead; 
 13        //十字链表的行头指针和列头指针; 定义为指向指针的指针;
 14     int row;     //稀疏矩阵的行数; 
 15     int col;     //稀疏矩阵的列数; 
 16     int num;     //稀疏矩阵的非零个数; 
 17 };
 18 
 19 int InitSMatrix(CrossL *M)  //初始化M(CrossL)类型的变量必须初始化; 
 20 {
 21     (*M).rhead = (*M).sead = NULL;
 22     (*M).row = (*M).col = (*M).num = 0;
 23     return 1;
 24  } 
 25  
 26 int DestroysMatrix(CrossL *M)  //销毁稀疏矩阵M; 
 27  {
 28      int i ;
 29      OLNod *p,*q;
 30      for( i = 1 ; i <= (*M).row;i++)
 31      {
 32          p = *((*M).rhead+i);  //p指针不断向右移;
 33          while(p!=NULL)
 34          {
 35              q = p ;
 36              p = p ->right;
 37              delete q;   //删除q;
 38          }
 39      }
 40      delete((*M).rhead);  //释放行指针空间; 
 41      delete((*M).sead);  //释放列指针空间; 
 42      (*M).rhead = (*M).sead = NULL;   //并将行、列头指针置为空;
 43      (*M).num = (*M).row = (*M).col = 0;   //将非零元素,行数和列数置为0;
 44      return 1;
 45   } 
 46 int CreatSMatrix(CrossL *M)
 47 {
 48     int i , j  , m , n , t;
 49     int value;
 50     OLNod *p,*q;
 51     if((*M).rhead!=NULL)   
 52     DestroysMatrix(M);
 53     cin>>m>>n>>t;  //输入稀疏矩阵的行数、列数和非零元个数; 
 54     (*M).row = m; 
 55     (*M).col = n ;
 56     (*M).num = t;
 57     //初始化行链表头; 
 58     (*M).rhead = new  OLNod*[m+1];//为行头指针申请一个空间; 
 59     if(!(*M).rhead)    //如果申请不成功,则退出程序;
 60        exit(0);
 61     //初始化列链表头;
 62     (*M).sead = new OLNod*[n+1];//为列表头申请一个空间;
 63     if(!(*M).sead)    //如果申请不成功,则退出程序;
 64     exit(0);
 65     for(int k = 1 ; k <= m ; k++)
 66     {
 67         (*M).rhead[k] = NULL;//初始化行头指针向量;各行链表为空链表; 
 68      } 
 69      for(int k = 1 ; k <= n ;k++)
 70      {
 71          (*M).sead[k] = NULL;//初始化列头指针向量;各列链表为空链表; 
 72      }
 73      for(int k = 0 ; k < t ;k++)  //输入非零元素的信息; 
 74      {
 75          cin>>i>>j>>value;//输入非零元的行、列、数值; 
 76      p =  new OLNod();//为p指针申请一个空间;
 77      if(!p)    //e如果申请不成功;
 78        exit(0);  //退出程序;
 79       p->i = i;
 80       p->j = j;
 81       p->value = value;
 82       if((*M).rhead[i]==NULL)   //如果行头指针指向的为空;
 83       {
 84           //p插在该行的第一个结点处;
 85           p->right = (*M).rhead[i];  
 86           (*M).rhead[i] = p; 
 87        }else   //如果不指向空
 88        {
 89            for(q = (*M).rhead[i];q->right; q = q->right);
 90            p->right = q->right;
 91            q->right = p;
 92            
 93        }
 94        if((*M).sead[j]==NULL)//如果列头指针指向的为空;
 95        {
 96         //p插在该行的第一个结点处;
 97            p->down = (*M).sead[j];
 98            (*M).sead[j] = p;
 99        }else//如果不指向空
100        {
101            for(q = (*M).sead[j];q->down;q = q->down);
102            p->down = q->down;
103            q->down = p;
104        }
105     }
106     return 1;
107 }
108 int PrintSMatrix(CrossL *M)
109 {
110     int flag = 0;
111     int val ;//要查找的元素的值; 
112     cin>>val;  //输入要查找的s值;
113     OLNod *p;   
114     for(int i = 1 ; i <= (*M).row ;i++)   
115     {
116         for(p = (*M).rhead[i];p;p = p->right)  //从行头指针开始找,不断向右找
117         {
118             if(p->value==val)    //如果能找到
119             {
120                 cout<<p->i<<" "<<p->j;  //输出行下标和列下标
121                 flag = 1;   //标记找到该元素;
122             }
123         }
124     }
125     
126     
127     if(flag==0)    //如果找不到
128 { 129 cout<<"ERROR "; 130 } 131 132 } 133 int main() 134 { 135 CrossL A; //定义一个十字链表; 136 InitSMatrix(&A); //初始化; 137 CreatSMatrix(&A); //创建; 138 PrintSMatrix(&A); //输出; 139 DestroysMatrix(&A); //销毁; 140 return 0; 141 }