1. 程式人生 > >資料結構八:稀疏矩陣(涉及三元組,十字連結串列)

資料結構八:稀疏矩陣(涉及三元組,十字連結串列)

###1. 稀疏矩陣的定義
稀疏矩陣是零元素居多的矩陣,稀疏矩陣和稠密矩陣之間並沒有一個精確的界限。假設m行n列的矩陣含有t個非零元素,一般稱 δ = t m n

\delta = \dfrac{t}{mn} 為稀疏因子。一般認為 δ 0.05 \delta \le 0.05 的矩陣為稀疏矩陣。
稀疏矩陣常用的儲存方式是通過三元組來進行儲存。也就是對於每個非零元素,用三元組(行號,列號,值)來表示。接下來可以使用順序表或者連結串列的方式來儲存這些三元組,具體實現如下:
實現的時候主要注意設定指定位置(r, c)的元素值v時,應該首先查詢是否在三元組中有指定的三元組。如果存在,當v=0時,則刪除此三元組;否則,修改三元組的的非零元素值。如果不存在指定位置的三元組,當v = 0時不做任何操作,否則插入三元組。

#pragma once
#define DEFAULT_ROWS 10
#define DEFAULT_COLS 10
#define DEFAULT_SIZE 10
//三元組類
template<typename elemType>
struct Triple
{
	//資料成員
	int rows, cols;
	elemType value;

	//
	Triple();//無參建構函式
	Triple(int rs, int cs, elemType v)
	{
		rows = rs; cols = cs; value = v;
	}
};


//稀疏矩陣三元組順序表類
template<
typename elemType> class TriSparseMatirx { protected: //資料成員 Triple<elemType>* elems; int maxSize; //非零元素的最大個數 int rows, cols, num;//稀疏矩陣的行數列數以及已存入的非零元素的個數 public: TriSparseMatirx(int rs = DEFAULT_ROWS, int cs = DEFAULT_COLS, int size = DEFAULT_SIZE); ~TriSparseMatirx(); int getRows() const;//返回稀疏矩陣的行數 int getCols() const;//返回稀疏矩陣的列數 int getNum() const;//返回稀疏矩陣非零元素的個數 bool setElem(int r, int c, const elemType& v);//設定指定位置的元素 bool getElem(int r, int c, elemType& v);//獲取指定位置的元素的值 TriSparseMatirx(const TriSparseMatirx<elemType>& copy); TriSparseMatirx<elemType>& operator=(const TriSparseMatirx<elemType>& copy); }; template<typename elemType> TriSparseMatirx<elemType>::TriSparseMatirx(int rs , int cs ,int size ) { //這個地方加一下對rs,cs的判斷 rows = rs; cols = cs; maxSize = size; num = 0; elems = new Triple<elemType>[maxSize]; } template<typename elemType> TriSparseMatirx<elemType>::~TriSparseMatirx() { if (elems != NULL) delete []elems; } template<typename elemType> int TriSparseMatirx<elemType>::getRows() const { return rows; } template<typename elemType> int TriSparseMatirx<elemType>::getCols() const { return cols; } template<typename elemType> int TriSparseMatirx<elemType>::getNum() const { return num; } template<typename elemType> bool TriSparseMatirx<elemType>::setElem(int r, int c, const elemType& v) { if (r<1 || r>rows || c<1 || c>cols) { return false; } int i, j; for (j = num - 1; j >= 0 && r < elems[j].rows || r == elems[j].rows && c < elems[j].cols; j--);//查詢三元組位置 if (j>=0 && elems[j].rows == r || elems[j].cols == c) { //找到三元組 if (v == 0) { //刪除三元組 for (i = j + 1; i < num;i++) { elems[i - 1] = elems[i]; } num--; } else { elems[j].value = v; } return true; } else if(v != 0)//如果沒有找到且v不為0則插入 { if (num < maxSize) {//將三元組插入到三元組表中 for (i = num - 1; i > j;i--) { elems[i + 1] = elems[i] } //j+1為空的位置插入元素 elems[j + 1], rows = r; elems[j + 1].cols = c; elems[j + 1].value = v; num++; return true; } else { return false; } } } template<typename elemType> bool TriSparseMatirx<elemType>::getElem(int r, int c, elemType& v) { if (r<1 || r>rows || c<1 || c>cols) { return false; } int i, j; for (j = num - 1; j >= 0 && r < elems[j].rows || r == elems[j].rows && c < elems[j].cols; j--);//查詢三元組位置 if (j >= 0 && elems[j].rows == r || elems[j].cols == c) { v = elems[j].value; return true; } else { return false; } } template<typename elemType> TriSparseMatirx<elemType>::TriSparseMatirx(const TriSparseMatirx<elemType>& copy) { maxSize = copy.maxSize; elems = new Triple<elemType>[maxSize]; num = copy.num for (int i = 0; i < num;i++) { elems[i] = copy.elems[i]; } } template<typename elemType> TriSparseMatirx<elemType>& TriSparseMatirx<elemType>::operator=(const TriSparseMatirx<elemType>& copy) { if (&copy != this) { maxSize = copy.maxSize; elems = new Triple<elemType>[maxSize]; num = copy.num for (int i = 0; i < num; i++) { elems[i] = copy.elems[i]; } } return *this; }

2矩陣的轉置

如果矩陣是用二維陣列表示的,則轉置操作很簡單。轉置操作主要是將每個元素的行號和列號互換。由於在三元組表中,元素按行號或者列號排列,所以在行號或列號交換之後,還要調整元素的位置,使其仍按行序或列序進行排列。轉置的具體步驟如下:
(1)將每個非零元素對應的三元組的行號和列號進行互換。
(2)對三元組重新排序,使其中的元素按行序或者列序排列。
如果要降低演算法的時間複雜度,這時可以開闢一個新的三元組表,假設原三元組表為source,轉置後的三元組為dest,具體步驟如下:
(1)將三元組表source中的每個元素取出交換其行號和列號。
(2)將變換後的三元組存入目標dest三元組表中適當位置,使dest中的元素按照行序或者列序進行排列。