亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C++實現稀疏矩陣的壓縮存儲實例

2020-01-26 14:05:33
字體:
來源:轉載
供稿:網友

什么是稀疏矩陣呢,就是在M*N的矩陣中,有效值的個數遠小于無效值的個數,并且這些數據的分布沒有規律。在壓縮存儲稀疏矩陣的時候我們只存儲極少數的有效數據。我們在這里使用三元組存儲每一個有效數據,三元組按原矩陣中的位置,以行優先級先后次序依次存放。下面我們來看一下代碼實現。

#include<iostream> #include<vector> #include<assert.h> using namespace std;  template<class T> class SparseMatrix {   //三元組   template<class T>   struct Trituple   {     Trituple()//給一個默認構造函數     {}     Trituple(size_t row, size_t col, const T& data)       :_row(row)       ,_col(col)       ,_data(data)     {}     size_t _row;     size_t _col;     T _data;   }; public:   //稀疏矩陣的壓縮存儲   SparseMatrix()   {}   SparseMatrix(int* arr, size_t row, size_t col, const T& invalid)     :_row(row)     ,_col(col)     ,_invalid(invalid)   {     for(int i = 0; i < row; i++)     {       for(int j = 0; j < col; ++j)       {         if(arr[i*col+j] != invalid)//將有效值存儲在一個一維數組中         _sm.push_back(Trituple<T>(i,j,arr[i*col+j]));//將三元組的無名對象push進去       }     }     }   //訪問稀疏矩陣中row行col中的元素   T& Acess(int row, int col)   {     //1、     /*for(int idx = 0; idx < _sm.size(); idx++)//遍歷一遍     {       if(_sm[idx]._row == row && _sm[idx]._col == col)//當前行列與我們要訪問那個元素行列相同時返回這個有效值         return _sm[idx]._data;     }     return _invalid;*/ //否則返回無效值     //2、     vector<Trituple<T>>::iterator it = _sm.begin();//定義一個迭代器,指向起始位置     while(it != _sm.end())//未到最后一個元素時     {       if(it->_row == row && it->_col == col)//行列相等輸出值         return it->_data;       ++it;//迭代器向后移動     }     return _invalid;   }   //還原稀疏矩陣   template<typename T>   friend ostream& operator<<(ostream& _cout, SparseMatrix<T>& s)//重載<<   {     size_t idex = 0;     for(size_t i = 0; i < s._row; i++)     {       for(size_t j = 0; j < s._col; j++)       {         if(idex < s._sm.size()/*防止數組越界*/ && s._sm[idex]._row == i && s._sm[idex]._col == j)         {           _cout<<s._sm[idex]._data<<" ";           ++idex;         }         else           _cout<<s._invalid<<" ";                }       _cout<<endl;     }     return _cout;   }   //實現稀疏矩陣的逆置 時間復雜度O(M*N)(M為元素個數N為矩陣列數)   SparseMatrix<T> Transport()   {     SparseMatrix<T> sm;     sm._row = _col;     sm._col = _row;     sm._invalid = _invalid;     for(size_t i = 0; i < _col; i++)     {       vector<Trituple<T>>::iterator it = _sm.begin();       while(it != _sm.end())       {         if(it->_col == i)//從原矩陣第0列開始,將每列中的有效值依次放入新的稀疏矩陣           sm._sm.push_back(Trituple<T> (i, it->_row, it->_data));         ++it;       }     }     return sm;   }   //實現稀疏矩陣的快速轉置 時間復雜度O(N)+O(M)   SparseMatrix<T> FastTransport()   {     SparseMatrix<T> sm;     sm._col = _row;     sm._row = _col;     sm._invalid = _invalid;     sm._sm.resize(_sm.size());//開辟空間     //1、統計原矩陣中每一列有多少個有效元素     int* pCount = new int[_col];//開辟原矩陣中列個數的空間     memset(pCount, 0, _col*sizeof(pCount[0]));     for(int i = 0; i < _sm.size(); i++)       pCount[_sm[i]._col]++;     //2、原矩陣每一列在新矩陣中的起始位值     int* pAddr = new int[_col];     memset(pAddr, 0, _col*sizeof(pAddr[0]));     for(int i = 1/*從1開始,第一個位置起始為0已經放入*/; i < _sm.size(); i++)     {       pAddr[i] = pAddr[i - 1] + pCount[i - 1];//前一個起始位值+前一列有效元素個數     }     //3、放置元素到新空間     for(int i = 0; i < _sm.size(); i++)     {       int& addr = pAddr[_sm[i]._col];       sm._sm[addr] = Trituple<T>(_sm[i]._col,_sm[i]._row,_sm[i]._data);       addr++;     }     return sm;   }   //實現稀疏矩陣的加法操作1   /*SparseMatrix<T> operator+(const SparseMatrix<T>& sp)   {     int i = 0, j = 0, k = 0;     T v;     SparseMatrix<T> s;     if(this->_col != sp._col || this->_row != sp._row)       exit(1);     s._row = sp._row;     s._col = sp._col;     s._invalid = sp._invalid;     while(i < this->_sm.size() && j < sp._sm.size())     {       if(this->_sm[i]._row == sp._sm[j]._row)       {         if(this->_sm[i]._col < sp._sm[j]._col)         {           s._sm.push_back(Trituple<T>(this->_sm[i]._row, this->_sm[i]._col, this->_sm[i]._data));           i++;           k++;         }         else if(this->_sm[i]._col > sp._sm[j]._col)         {           s._sm.push_back(Trituple<T>(sp._sm[j]._row, sp._sm[j]._col, sp._sm[j]._data));           j++;           k++;         }         else         {           v = this->_sm[i]._data + sp._sm[j]._data;           if(v)           {             s._sm.push_back(Trituple<T>(sp._sm[j]._row, sp._sm[j]._col, v));             k++;           }           i++;           j++;         }       }       else if(this->_sm[i]._row < sp._sm[j]._row)       {         s._sm.push_back(Trituple<T>(this->_sm[i]._row, this->_sm[i]._col, this->_sm[i]._data));         i++;         k++;       }       else       {         s._sm.push_back(Trituple<T>(sp._sm[j]._row, sp._sm[j]._col, sp._sm[j]._data));         j++;         k++;       }     }     return s;   }*/   //實現稀疏矩陣的加法操作2   SparseMatrix<T> operator+(const SparseMatrix<T>& sp)   {     assert(_row == sp._row && _col == sp._col);//檢測兩個相加的矩陣行列是否相等     SparseMatrix<T> ret;     ret._row = _row;     ret._col = _col;     ret._invalid = _invalid;     int iLidx = 0, iRidx = 0;//定義兩個索引          while(iLidx < _sm.size() && iRidx < sp._sm.size())     {       size_t AddrLeft = _sm[iLidx]._row*_col+_sm[iLidx]._col;//左邊矩陣的起始位值       size_t AddrRight = sp._sm[iRidx]._row*sp._col+sp._sm[iRidx]._col;//右邊矩陣起始位值       if(AddrLeft < AddrRight)//左<右,將左邊有效值放入和矩陣中,左邊的索引加加       {         ret._sm.push_back(Trituple<T>(_sm[iLidx]._row, _sm[iLidx]._col, _sm[iLidx]._data));         iLidx++;       }       else if(AddrLeft > AddrRight)       {         ret._sm.push_back(Trituple<T>(sp._sm[iRidx]._row, sp._sm[iRidx]._col, sp._sm[iRidx]._data));         iRidx++;       }       else//當左邊等于右邊判斷相加后和是否為0,不為0放入       {         Trituple<T> temp(_sm[iLidx]);         temp._data += sp._sm[iRidx]._data;         if(temp._data)         {           ret._sm.push_back(temp);           iLidx++;           iRidx++;         }       }     }     while(iLidx < _sm.size())//左邊還有剩余則放入剩余元素     {       ret._sm.push_back(Trituple<T>(_sm[iLidx]._row, _sm[iLidx]._col, _sm[iLidx]._data));       iLidx++;     }     while(iRidx < sp._sm.size())     {       ret._sm.push_back(Trituple<T>(sp._sm[iRidx]._row, sp._sm[iRidx]._col, sp._sm[iRidx]._data));       iRidx++;     }     return ret;   } private:   size_t _row;   size_t _col;   vector<Trituple<T>> _sm;   T _invalid;//無效值 };  int main() {   int arr[6][5] = {     {1,0,3,0,5},     {0,0,0,0,0},     {0,0,0,0,0},     {1,0,3,0,5},     {0,0,0,0,0},     {0,0,0,0,0}};   int arr1[6][5] = {     {1,0,3,0,5},     {0,0,0,0,0},     {0,0,2,4,0},     {1,0,3,0,5},     {0,0,0,1,0},     {0,0,0,0,1}};   SparseMatrix<int> s((int*)arr,6,5,0);   SparseMatrix<int> s1((int*)arr1,6,5,0);   cout<<"訪問三行四列元素"<<endl;   cout<<s.Acess(3,4)<<endl;   cout<<s<<endl;   cout<<"快速轉置"<<endl;   cout<<s.FastTransport();   cout<<endl;   cout<<"矩陣s:"<<endl;   cout<<s<<endl;   cout<<"矩陣s1:"<<endl;   cout<<s1<<endl;   cout<<"s+s1求和:"<<endl;   cout<<s1+s<<endl;   system("pause");   return 0; } 

運行結果截圖:

在上面的代碼中用到C++模板、標準庫中vector容器,以及迭代器實現了一些基本的操作,如訪問稀疏矩陣中某個元素,輸出稀疏矩陣、稀疏矩陣的轉置以及快速轉置還有兩個稀疏矩陣的加法。

快速轉置操作的基本思路是:

(1)統計原矩陣中每一列有多少個有效元素;

(2)原矩陣中每一列在新矩陣中的起始地址;

(3)放置元素到新空間中。

還需注意的是,在我們打印這個稀疏矩陣時雖然也可以直接調用訪問元素的Acess接口,但是每次進去之后都得遍歷一遍,時間復雜度較高,所以我們不采取這種辦法,而是比較當前行列的值,若相等輸出有效元素,不等則輸出無效元素0。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品美女久久久免费| 成人激情电影一区二区| 国产成人亚洲精品| 久久精品精品电影网| 欧美国产日韩一区二区在线观看| 欧洲日本亚洲国产区| 韩国三级日本三级少妇99| 成人福利在线视频| 91在线观看免费高清完整版在线观看| 国产精品久久久久久久电影| 日韩一二三在线视频播| 97色在线观看免费视频| 亚洲午夜女主播在线直播| 久久久久久久久久国产精品| 国产精品国产三级国产专播精品人| 欧美性生交xxxxx久久久| 欧美激情第一页xxx| 亚洲日韩中文字幕在线播放| 国产91色在线免费| 日韩精品一区二区三区第95| 国产精品视频自拍| 欧美老妇交乱视频| 欧美日韩国产精品一区二区不卡中文| 日韩欧美aaa| 欧美日韩性视频在线| 欧美黄网免费在线观看| 亚洲国产精品专区久久| 色综合伊人色综合网站| 久久久久久久久久久久av| 久久全球大尺度高清视频| 欧美日韩国产在线| 亚洲欧美激情视频| www国产精品视频| 亚洲欧美一区二区三区在线| 中文字幕亚洲综合久久筱田步美| 日韩在线小视频| 国产成人avxxxxx在线看| 色悠悠久久久久| 97久久超碰福利国产精品…| 久久久精品久久久| 欧美精品18videosex性欧美| 欧美精品做受xxx性少妇| 亚洲成人在线视频播放| 久久躁日日躁aaaaxxxx| 国产综合视频在线观看| 欧美精品久久久久a| 亚洲精品国产免费| 国产精品十八以下禁看| 成人久久精品视频| 人人做人人澡人人爽欧美| 亚洲精品按摩视频| 亚洲精品久久久一区二区三区| 精品在线观看国产| 亚洲男人天堂九九视频| 国产精品第一第二| 中文欧美在线视频| 欧美激情精品久久久久久| 奇米影视亚洲狠狠色| 日本不卡视频在线播放| 亚洲美女av黄| 久久久久久久久久久人体| 青青a在线精品免费观看| 精品久久久久久| 欧美性生交xxxxxdddd| 国产亚洲成av人片在线观看桃| 国产日韩av高清| xxxxxxxxx欧美| 国产精品av在线播放| 欧洲成人午夜免费大片| 亚洲激情久久久| 亚洲第一av在线| 97国产一区二区精品久久呦| 久久久精品在线观看| 欧美超级免费视 在线| 国产精品高潮粉嫩av| 国产视频精品在线| 国产成人啪精品视频免费网| 中文字幕精品影院| 38少妇精品导航| 久久久久久久一| 成人av资源在线播放| 久久国产精品99国产精| 久久久99久久精品女同性| 欧美日韩国产麻豆| 91视频8mav| 亚洲欧美资源在线| 欧美成人合集magnet| 亚洲最大成人网色| 欧美精品videossex性护士| 中文字幕亚洲一区| 午夜精品久久久99热福利| 国产最新精品视频| 国内精品久久久久久久| 国产成人黄色av| 成人高h视频在线| 国产精品九九久久久久久久| 久久亚洲精品小早川怜子66| 日韩中文字幕国产| 国内精品国产三级国产在线专| 亚洲精品乱码久久久久久按摩观| 91精品成人久久| 亚洲电影成人av99爱色| 国产精品美女免费看| 亚洲精品福利在线观看| 一区二区三区亚洲| 日韩av三级在线观看| 九九热这里只有精品免费看| 黑人精品xxx一区一二区| 91久久精品美女高潮| 久久久成人精品| 欧美黑人xxxⅹ高潮交| 国产亚洲视频中文字幕视频| 精品高清美女精品国产区| 国产一区二区三区在线看| 91禁外国网站| 欧美日韩亚洲一区二区三区| 国产精品爽爽爽爽爽爽在线观看| 久久偷看各类女兵18女厕嘘嘘| www.久久撸.com| 国产精品www色诱视频| 国产精品三级美女白浆呻吟| 国产精品自拍偷拍视频| 欧美激情视频在线观看| 永久免费毛片在线播放不卡| 欧美性猛交xxxx免费看| 久久精品国产亚洲精品| 在线性视频日韩欧美| 欧洲成人午夜免费大片| 日韩毛片中文字幕| 欧美理论电影在线观看| 中文字幕亚洲欧美| 亚洲女人天堂色在线7777| 色视频www在线播放国产成人| 国产激情综合五月久久| 精品久久在线播放| 亚洲欧美激情四射在线日| 亚洲女人被黑人巨大进入al| 中国人与牲禽动交精品| 中文字幕亚洲综合久久筱田步美| 欧美精品videossex88| 91午夜理伦私人影院| 欧美日韩国产丝袜美女| 欧美第一黄网免费网站| www.欧美免费| 欧美精品在线免费观看| 亚洲国语精品自产拍在线观看| 国产精品爽爽爽爽爽爽在线观看| 日韩中文字幕在线免费观看| 亚洲最大福利网| 亚洲人免费视频| 一本一本久久a久久精品综合小说| 久久99久久99精品中文字幕| 国产视频综合在线| 亚洲欧美一区二区三区久久| 68精品国产免费久久久久久婷婷| 国产精品久久久久久久久久免费| 久久久999精品视频| 伊人青青综合网站| 欧美高清videos高潮hd| 欧美成人自拍视频| 亚洲欧美日韩精品久久| 日韩av一区在线| 国产精品视频永久免费播放| 亚洲人成欧美中文字幕|