中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

稀疏矩陣的壓縮存儲及轉置算法

發布時間:2020-07-16 22:39:47 來源:網絡 閱讀:1675 作者:馬尾和披肩 欄目:編程語言

只怪 博主智商無下限,花了一個周末終于把系數矩陣的壓縮存儲及其轉置給弄明白了,所以今天就和大家分享一下我的學習過程啦!!!

稀疏矩陣是指矩陣中大多數元素為零的矩陣,從直觀上講,非零元素的個數低于總元素的30%時,這樣的矩陣稱為稀疏矩陣。

稀疏矩陣的壓縮存儲及轉置算法


1.稀疏矩陣的三元組組表示法

對于稀疏矩陣的壓縮存儲,采取只存儲非零元素的方法,由于稀疏矩陣中非零元素的分布沒有規律,所以呢???在存儲非零元素的時候必須給每個元素做個標記(非零元素在矩陣中所處的行號和列號)。

稀疏矩陣的壓縮存儲及轉置算法

//稀疏矩陣三元組表類型的定義
struct Triple
{
T _value;
size_t _row;
size_t _col;

Triple(size_t row=0,size_t col=0,const T& value=T())
:_value(value)
,_row(row)
,_col(col)
{}
};


(1)Triple是包含三個域的結構體類型,其元素是為了存儲非零元的三元組


2.稀疏矩陣的壓縮存儲

就上圖給出的矩陣而言,運用三元組壓縮存儲的方法存儲后的結果是醬紫滴


稀疏矩陣的壓縮存儲及轉置算法

源代碼是醬紫滴:


//用三元組表示實現稀疏矩陣的壓縮存儲
	SpareMatrix(T* a,size_t m,size_t n,const T& invalid)
		:_rowsize(m)
		,_colsize(n)
		,_invalid(invalid)
	{
		for(size_t i=0;i<m;i++)
		{
			for(size_t j=0;j<n;j++)
			{
				if(a[i*n+j]!=invalid)
				{
				_a.push_back(Triple<T>(i,j,a[i*n+j]));
				}
			}
		}
	
	}



3.稀疏矩陣的列序遞增轉置法


采用被轉置矩陣按照列序遞增的的順序進行轉置,并依此將將其送入轉置后的三元組表中,這樣子的話轉置后的三元組表恰好是以行序號為主的哦 。

具體做法:



(1)找出轉置后的第一行元素:第一遍從頭至尾掃描三元組表,找出所有_col為1的三元組,轉置后按順序放到開辟好新的三元組表中

(2)找出轉置后的第二行元素:第一遍從頭至尾掃描三元組表,找出所有_col為2的三元組,轉置后按順序放到開辟好新的三元組表中

 源代碼是醬紫滴:
//稀疏矩陣的轉置
SpareMatrix<T> Transport()
{
      SpareMatrix<T> tmp;
  tmp._rowsize = _colsize;
  tmp._colsize = _rowsize;
  tmp._invalid=_invalid;
  //給構建好的匿名對象開辟空間,但是不改變size的大小,開辟后初始化的值為原來的。
  tmp._a.reserve(_a.size());
  for(size_t i=0;i<_colsize;i++)
  {
  size_t index=0;
  for(index=0;index<_a.size();index++)
  {
   if(_a[index]._col==i)
   {
   Triple <T> tp;
   tp._row=_a[index]._col;
   tp._col=_a[index]._row;
   tp._value=_a[index]._value;
   tmp._a.push_back(tp);
   }
  }
  }
  return tmp;
  
}

注釋:雖然構建了一個 SpareMatrix<T> tmp類型的對象但是并沒有給它開辟和_a一樣大小的空間,所以要調用reserve或者resize兩個函數中任意一個即可,否則當你在運行程序的時候會奔潰哦,智商無下線的博主昨天就是犯了這個錯誤,程序跑起來的時候,老是彈出這樣的框框:

稀疏矩陣的壓縮存儲及轉置算法

最后調試了好久才發現問題所在稀疏矩陣的壓縮存儲及轉置算法氣死寶寶啦,



算法分析:

算法主要耗費在雙重循環中,其時間復雜度為o(_colsize*_a.size());


4.稀疏矩陣的一次定位快速轉置算法

 

算法思想:

(1)計算待轉置矩陣三元組表中每一列非零元素的個數,即轉置后矩陣三元組表每一行中非零元素的個數。

(2)計算待轉置矩陣每一列中第一個非零元素三元組表中的具體位置。

源代碼是醬紫滴:

/稀疏矩陣的快速轉置
SpareMatrix<T> FastTransport()
{
  SpareMatrix<T> tmp;
  tmp._rowsize = _colsize;
  tmp._colsize = _rowsize;
  tmp._invalid=_invalid;
  int* rowcounts=new int[tmp._rowsize];
  int* rowstart=new int[tmp._rowsize];
  memset(rowcounts,0,sizeof((int*)_colsize));
  memset(rowstart,0,sizeof((int*)_colsize));
  size_t index=0;
 
  //計算待轉置矩陣每一列非零元素的個數
  while(index<_a.size())
  {
  rowcounts[_a[index]._col]++;
  index++;
  }


//計算待轉置矩陣每一列第一個非零元素在三元組表中的位置
rowstart[0]=0;
for(size_t i=1;i<_colsize;i++)
{
rowstart[i]=rowstart[i-1]+rowcounts[i-1];
}

index=0;
//給_a的匿名對象開辟_a大小的空間
    tmp._a.resize(_a.size());
while(index<_a.size())
{/*
size_t rowindex=_a[index]._col;*/
int& start=rowstart[_a[index]._col];

Triple<T> tp;
tp._value=_a[index]._value;
tp._row=_a[index]._col;
tp._col=_a[index]._row;
tmp._a[start++]=tp;
index++;
}
return tmp;
}



算法分析:

一次定位快速轉置算法時間主要耗費在三個并列的循環中,因而時間復雜度為o(_a.size+_colsize).

 

完整的源代碼:


 

//稀疏矩陣的壓縮存儲
#include<iostream>
#include<vector>
using namespace std;
template<typename T>
//稀疏矩陣三元組表類型的定義
struct Triple
{
T _value;
size_t _row;
size_t _col;

Triple(size_t row=0,size_t col=0,const T& value=T())
:_value(value)
,_row(row)
,_col(col)
{}

};
template<typename T>
//稀疏矩陣
class SpareMatrix
{
public:

SpareMatrix()
:_rowsize(0)
,_colsize(0)
,_invalid(0)
{}
//用三元組表示實現稀疏矩陣的壓縮存儲
SpareMatrix(T* a,size_t m,size_t n,const T& invalid)
:_rowsize(m)
,_colsize(n)
,_invalid(invalid)
{
for(size_t i=0;i<m;i++)
{
for(size_t j=0;j<n;j++)
{
if(a[i*n+j]!=invalid)
{
_a.push_back(Triple<T>(i,j,a[i*n+j]));
}
}
}

}
//稀疏矩陣的轉置
SpareMatrix<T> Transport()
{
      SpareMatrix<T> tmp;
  tmp._rowsize = _colsize;
  tmp._colsize = _rowsize;
  tmp._invalid=_invalid;
  //給構建好的匿名對象開辟空間,但是不改變size的大小,開辟后初始化的值為原來的。
  tmp._a.reserve(_a.size());
  for(size_t i=0;i<_colsize;i++)
  {
  size_t index=0;
  for(index=0;index<_a.size();index++)
  {
   if(_a[index]._col==i)
   {
   Triple <T> tp;
   tp._row=_a[index]._col;
   tp._col=_a[index]._row;
   tp._value=_a[index]._value;
   tmp._a.push_back(tp);
   }
  }
  }
  return tmp;
  
}
//稀疏矩陣的快速轉置
SpareMatrix<T> FastTransport()
{
  SpareMatrix<T> tmp;
  tmp._rowsize = _colsize;
  tmp._colsize = _rowsize;
  tmp._invalid=_invalid;
  int* rowcounts=new int[tmp._rowsize];
  int* rowstart=new int[tmp._rowsize];
  memset(rowcounts,0,sizeof((int*)_colsize));
  memset(rowstart,0,sizeof((int*)_colsize));
  size_t index=0;
 
  //計算待轉置矩陣每一列非零元素的個數
  while(index<_a.size())
  {
  rowcounts[_a[index]._col]++;
  index++;
  }


//計算待轉置矩陣每一列第一個非零元素在三元組表中的位置
rowstart[0]=0;
for(size_t i=1;i<_colsize;i++)
{
rowstart[i]=rowstart[i-1]+rowcounts[i-1];
}

index=0;
//給_a的匿名對象開辟_a大小的空間
    tmp._a.resize(_a.size());
while(index<=_a.size())
{/*
size_t rowindex=_a[index]._col;*/
int& start=rowstart[_a[index]._col];

Triple<T> tp;
tp._value=_a[index]._value;
tp._row=_a[index]._col;
tp._col=_a[index]._row;
tmp._a[start++]=tp;
index++;
}
return tmp;
}
void display()
{
   size_t index=0;
for(size_t i=0;i<_rowsize;i++)
{
for(size_t j=0;j<_colsize;j++)
{
   if(index<_a.size() && _a[index]._row==i && _a[index]._col==j)
   {
        cout<<_a[index++]._value<<" ";
   }
   else
   {
   cout<<_invalid<<" ";
   }
}
cout<<endl;
}
cout<<endl;
}


protected:
vector<Triple <T> > _a;
size_t _rowsize;
size_t _colsize;
T _invalid;

};

void test()
{
    int a[4][4]={{1,0,0,0},
                 {2,2,0,0},
                 {0,1,3,0},
                 {1,0,0,4}};
SpareMatrix<int>sm1((int*)a,4,4,0);
sm1.display();

SpareMatrix<int> sm2=sm1.Transport();
sm1.display();

SpareMatrix<int> sm3=sm1.FastTransport();
sm1.display();
}
int main()
{
test();
getchar();
return 0;
}





















向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

长岭县| 奎屯市| 无极县| 贡觉县| 白银市| 蛟河市| 宾川县| 遂平县| 长治市| 普兰店市| 固阳县| 田阳县| 宿州市| 古浪县| 武陟县| 施秉县| 彭阳县| 松桃| 汶上县| 德保县| 台江县| 盘锦市| 垫江县| 镇宁| 宜城市| 莒南县| 明溪县| 桐城市| 南丰县| 淮南市| 凤山市| 平武县| 平阴县| 仪征市| 卓尼县| 都昌县| 特克斯县| 宿迁市| 县级市| 和林格尔县| 宜昌市|