我們知道矩陣是一個非常強大的數據結構,在動態規划以及各種圖論算法上都有廣泛的應用,當然矩陣有着不足的地方就是空間和時間
復雜度都維持在N2上,比如1w個數字建立一個矩陣,在內存中會占用1w*1w=1億的類型空間,這時就會遇到outofmemory。。。那么面
臨的一個問題就是如何來壓縮矩陣,當然壓縮的方式有很多種,這里就介紹一個順序表的壓縮方式:三元組。
一:三元組
有時候我們的矩陣中只有零星的一些非零元素,其余的都是零元素,那么我們稱之為稀疏矩陣,當然沒有絕對的說有多少個零元素才算稀疏。
針對上面的這個無規律的存放非零元素,三元組提出了一種方法,就是僅僅記錄矩陣中的非零元素以及它的行,列以及值N(x,y,v)構成的一個三元
組,標識一個稀疏矩陣的話,還要記錄該矩陣的階數,這樣我們就將一個二維的變成了一個一維,極大的壓縮的存儲空間,這里要注意的就是,三
元組的構建采用“行“是從上到下,“列”也是從左到右的方式構建的順序表。
1 /// <summary> 2 /// 三元組 3 /// </summary> 4 public class Unit 5 { 6 public int x; 7 public int y; 8 public int element; 9 } 10 11 /// <summary> 12 /// 標識矩陣 13 /// </summary> 14 public class SPNode 15 { 16 //矩陣總行數 17 public int rows; 18 19 //矩陣總列數 20 public int cols; 21 22 //非零元素的個數 23 public int count; 24 25 //矩陣中非零元素 26 public List<Unit> nodes = new List<Unit>(); 27 }
其實說到這里也就差不多了,我們只要知道三元組是用來做矩陣壓縮的一個順序存儲方式即可,然后知道怎么用三元組表來做一些常規的矩陣
運算,好了,既然說已經做成線性存儲了,那就做個“行列置換”玩玩。
二:行列置換
做行列置換很容易,也就是交換"非零元素"的(x,y)坐標,要注意的就是,原先我們的三元組采用的是”行優先“,所以在做轉置的時候需要
遵循"列優先“。
1 /// <summary> 2 /// 行轉列運算 3 /// </summary> 4 /// <param name="spNode"></param> 5 /// <returns></returns> 6 public SPNode ConvertSpNode(SPNode spNode) 7 { 8 //矩陣元素的x和y坐標進行交換 9 SPNode spNodeLast = new SPNode(); 10 11 //行列互換 12 spNodeLast.rows = spNode.cols; 13 spNodeLast.cols = spNode.rows; 14 spNodeLast.count = spNode.count; 15 16 //循環原矩陣的列數 (行列轉換) 17 for (int col = 0; col < spNode.cols; col++) 18 { 19 //循環三元組行的個數 20 for (int sp = 0; sp < spNode.count; sp++) 21 { 22 var single = spNode.nodes[sp]; 23 24 //找到三元組中存在的相同編號 25 if (col == single.y) 26 { 27 spNodeLast.nodes.Add(new Unit() 28 { 29 x = single.y, 30 y = single.x, 31 element = single.element 32 }); 33 } 34 } 35 } 36 37 return spNodeLast; 38 }
最后是總的代碼:

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Diagnostics; 6 using System.Threading; 7 using System.IO; 8 9 namespace ConsoleApplication2 10 { 11 public class Program 12 { 13 public static void Main() 14 { 15 Martix martix = new Martix(); 16 17 //構建三元組 18 var node = martix.Build(); 19 20 foreach (var item in node.nodes) 21 { 22 Console.WriteLine(item.x + "\t" + item.y + "\t" + item.element); 23 } 24 25 Console.WriteLine("******************************************************"); 26 27 var mynode = martix.ConvertSpNode(node); 28 29 foreach (var item in mynode.nodes) 30 { 31 Console.WriteLine(item.x + "\t" + item.y + "\t" + item.element); 32 } 33 34 Console.Read(); 35 } 36 } 37 38 public class Martix 39 { 40 /// <summary> 41 /// 三元組 42 /// </summary> 43 public class Unit 44 { 45 public int x; 46 public int y; 47 public int element; 48 } 49 50 /// <summary> 51 /// 標識矩陣 52 /// </summary> 53 public class SPNode 54 { 55 //矩陣總行數 56 public int rows; 57 58 //矩陣總列數 59 public int cols; 60 61 //非零元素的個數 62 public int count; 63 64 //矩陣中非零元素 65 public List<Unit> nodes = new List<Unit>(); 66 } 67 68 /// <summary> 69 /// 構建一個三元組 70 /// </summary> 71 /// <returns></returns> 72 public SPNode Build() 73 { 74 SPNode spNode = new SPNode(); 75 76 //遵循行優先的原則 77 spNode.nodes.Add(new Unit() { x = 0, y = 0, element = 8 }); 78 spNode.nodes.Add(new Unit() { x = 1, y = 2, element = 1 }); 79 spNode.nodes.Add(new Unit() { x = 2, y = 3, element = 6 }); 80 spNode.nodes.Add(new Unit() { x = 3, y = 1, element = 4 }); 81 82 //4階矩陣 83 spNode.rows = spNode.cols = 4; 84 85 //非零元素的個數 86 spNode.count = spNode.nodes.Count; 87 88 return spNode; 89 } 90 91 /// <summary> 92 /// 行轉列運算 93 /// </summary> 94 /// <param name="spNode"></param> 95 /// <returns></returns> 96 public SPNode ConvertSpNode(SPNode spNode) 97 { 98 //矩陣元素的x和y坐標進行交換 99 SPNode spNodeLast = new SPNode(); 100 101 //行列互換 102 spNodeLast.rows = spNode.cols; 103 spNodeLast.cols = spNode.rows; 104 spNodeLast.count = spNode.count; 105 106 //循環原矩陣的列數 (行列轉換) 107 for (int col = 0; col < spNode.cols; col++) 108 { 109 //循環三元組行的個數 110 for (int sp = 0; sp < spNode.count; sp++) 111 { 112 var single = spNode.nodes[sp]; 113 114 //找到三元組中存在的相同編號 115 if (col == single.y) 116 { 117 spNodeLast.nodes.Add(new Unit() 118 { 119 x = single.y, 120 y = single.x, 121 element = single.element 122 }); 123 } 124 } 125 } 126 127 return spNodeLast; 128 } 129 } 130 }