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\n"; 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 }