稀疏矩阵压缩存储的C语言实现 (GCC编译)。

  1. /**
  2. * @brief C语言 稀疏矩阵 压缩 实现
  3. * @author wid
  4. * @date 2013-11-04
  5. *
  6. * @note 若代码存在 bug 或程序缺陷, 请留言反馈, 谢谢!
  7. */
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <assert.h>
  12. #include <string.h>
  13.  
  14. #define TRUE 1
  15. #define FALSE 0
  16. #define NPOS -1
  17.  
  18. typedef int ElemType;
  19.  
  20. typedef struct
  21. {
  22. int m; ///行下标
  23. int n; ///列下标
  24. ElemType elm; ///该下标所保存的元素
  25. }TTuple; ///三元组结构
  26.  
  27. typedef struct
  28. {
  29. TTuple *tup; ///三元组顺序表
  30. int row; ///矩阵行数
  31. int col; ///矩阵列数
  32. int unul; ///非 0 元素个数
  33. }TMatrix; ///稀疏矩阵结构
  34.  
  35. ///稀疏矩阵方法声明
  36. TMatrix *CreateEmptyTMatrix( int sizeM, int sizeN ); ///创建一个大小为 sizeM x sizeN 稀疏矩阵
  37. TMatrix *CreateTMatirxFrom2DArray( void *pArr2D, int sizeM, int sizeN ); ///从二维数组中创建稀疏矩阵
  38. void DestroyTMatrix( TMatrix *pMat ); ///销毁稀疏矩阵
  39. int ElemLocate( const TMatrix *const pMat, int m, int n ); ///定位矩阵下标 m, n 在稀疏矩阵中的存储位置
  40. void DisplayTMatrix( const TMatrix *const pMat ); ///输出稀疏矩阵
  41. int GetTMatrixSize( const TMatrix *const pMat ); ///输出稀疏矩阵 pMat 所占用的空间大小(字节)
  42. int AppendElem( TMatrix *const pMat, ElemType elm, int m, int n ); ///将元素 elm 添加到稀疏矩阵 m, n 位置
  43. int DeleteElem( TMatrix *const pMat, int m, int n ); ///删除稀疏矩阵中 m, n 下标指向的元素
  44. int TMatrixCopy( TMatrix *const pMatDest, TMatrix *const pMatSrc ); ///将稀疏矩阵 pMatSrc 复制到 pMatDest
  45. int Value( const TMatrix *const pMat, int m, int n, ElemType *pElm ); ///从稀疏矩阵中取下标为 m, n 元素的值
  46. void ForEach( const TMatrix *const pMat, void (*func)(ElemType *pElm) ); ///对矩阵中的每个元素依次执行 func 函数
  47.  
  48. ///稀疏矩阵方法实现
  49.  
  50. /**
  51. * @brief 创建一个大小为 sizeM x sizeN 稀疏矩阵
  52. *
  53. * @return 返回创建的稀疏矩阵的指针
  54. */
  55. TMatrix *CreateEmptyTMatrix( int sizeM, int sizeN )
  56. {
  57. ///不接受大小为0的稀疏矩阵
  58. assert( sizeM > && sizeN > );
  59.  
  60. TMatrix *pMat = (TMatrix *)malloc( sizeof(TMatrix) );
  61. pMat->tup = NULL;
  62. pMat->row = sizeM;
  63. pMat->col = sizeN;
  64. pMat->unul = ;
  65.  
  66. return pMat;
  67. }
  68.  
  69. /**
  70. * @brief 从二维数组中创建稀疏矩阵
  71. *
  72. * @param pArr2D 一个ElemType型二维数组
  73. * @param sizeM 二维数组的行数
  74. * @param sizeN 二维数组的列数
  75. *
  76. * @return 返回创建的稀疏矩阵的指针
  77. */
  78. TMatrix *CreateTMatirxFrom2DArray( void *pArr2D, int sizeM, int sizeN )
  79. {
  80. ///不接受大小为0的稀疏矩阵
  81. assert( sizeM > && sizeN > );
  82.  
  83. TMatrix *pMat = (TMatrix *)malloc( sizeof(TMatrix) );
  84.  
  85. ///初始化稀疏矩阵行数、列数
  86. pMat->row = sizeM;
  87. pMat->col = sizeN;
  88.  
  89. ///第一趟遍历, 统计非零元素个数
  90. int m = , n = ;
  91. for( m = ; m < sizeM; ++m )
  92. for( n = ; n < sizeN; ++n )
  93. if( ((ElemType *)pArr2D)[sizeM * m + n] != )
  94. ++pMat->unul;
  95.  
  96. ///申请合适长度的三元组类型的线性表
  97. pMat->tup = (TTuple *)calloc( pMat->unul, sizeof(TTuple) );
  98.  
  99. ///第二趟遍历, 存储二维矩阵中的非零元素
  100. int nPos = ;
  101. for( m = ; m < sizeM; ++m )
  102. for( n = ; n < sizeN; ++n )
  103. if( ((ElemType *)pArr2D)[sizeM * m + n] != )
  104. {
  105. pMat->tup[nPos].m = m;
  106. pMat->tup[nPos].n = n;
  107. pMat->tup[nPos].elm = ((ElemType *)pArr2D)[sizeM * m + n];
  108. ++nPos;
  109. }
  110.  
  111. return pMat;
  112. }
  113.  
  114. /**
  115. * @brief 销毁稀疏矩阵
  116. *
  117. * @param pMat 指向待销毁的稀疏矩阵
  118. */
  119. void DestroyTMatrix( TMatrix *pMat )
  120. {
  121. free( pMat->tup );
  122. free( pMat );
  123.  
  124. pMat = NULL;
  125. }
  126.  
  127. /**
  128. * @brief 定位元素下标 m, n 在稀疏矩阵中出现的位置
  129. *
  130. * @param pMat 指向待定位元素的稀疏矩阵
  131. * @param m 元素行下标
  132. * @param n 元素列下标
  133. *
  134. * @return 若存在, 返回该下标组在稀疏矩阵中出现的位置, 否则返回 NPOS
  135. *
  136. * @note 元素位置由 0 计起
  137. */
  138. int ElemLocate( const TMatrix *const pMat, int m, int n )
  139. {
  140. int i = ;
  141. for( i = ; i < pMat->unul; ++i )
  142. {
  143. if( pMat->tup[i].m == m && pMat->tup[i].n == n )
  144. return i;
  145. }
  146.  
  147. return NPOS;
  148. }
  149.  
  150. /**‘
  151. * @brief 输出稀疏矩阵
  152. *
  153. * @param pMat 指向待输出的稀疏矩阵
  154. *
  155. * @return void
  156. */
  157. void DisplayTMatrix( const TMatrix *const pMat )
  158. {
  159. int m = , n = , pos = ;
  160. for( m = ; m < pMat->row; ++m )
  161. {
  162. for( n = ; n < pMat->col; ++n )
  163. {
  164. pos = ElemLocate( pMat, m, n );
  165. if( pos != NPOS )
  166. printf( "%d ", pMat->tup[pos].elm );
  167. else
  168. printf( "%d ", );
  169. }
  170. putchar( '\n' );
  171. }
  172. }
  173.  
  174. /**
  175. * @brief 获取稀疏矩阵所占用的空间大小(字节)
  176. *
  177. * @param pMat 指向待获取占用空间的稀疏矩阵
  178. *
  179. * @return 返回该矩阵所占用的空间的大小
  180. */
  181. int GetTMatrixSize( const TMatrix *const pMat )
  182. {
  183. return pMat->unul * sizeof(TTuple);
  184. }
  185.  
  186. /**
  187. * @brief 将元素添加到稀疏矩阵的 m, n 位置
  188. *
  189. * @param pMat 指向待添加元素的稀疏矩阵
  190. * @param elm 待添加的元素
  191. * @param m 元素所在的行数
  192. * @param n 元素所在的列数
  193. *
  194. * @return 返回添加后稀疏矩阵中非 0 元素的个数
  195. */
  196. int AppendElem( TMatrix *const pMat, ElemType elm, int m, int n )
  197. {
  198. ///断言下标合法
  199. assert( m >= && m < pMat->row && n >= && n < pMat->col );
  200.  
  201. ///断言元素值合法(不接受元素值为0的元素)
  202. assert( elm != );
  203.  
  204. ///测试下标是否存在
  205. int i = , pos = ;
  206. pos = ElemLocate( pMat, m, n );
  207. if( pos != NPOS )
  208. { ///下标已存在, 覆盖原值
  209. pMat->tup[pos].elm = elm;
  210. return pMat->unul;
  211. }
  212.  
  213. ///新添加
  214. pMat->tup = (TTuple *)realloc( pMat->tup, sizeof(TTuple) * (pMat->unul + ) );
  215. pMat->tup[pMat->unul].m = m;
  216. pMat->tup[pMat->unul].n = n;
  217. pMat->tup[pMat->unul].elm = elm;
  218.  
  219. return ++pMat->unul;
  220. }
  221.  
  222. /**
  223. * @brief 删除稀疏矩阵中下标 m, n 指向的元素
  224. *
  225. * @param pMat 指向待删除元素的稀疏矩阵
  226. * @param m 元素行下标
  227. * @param n 元素列下标
  228. *
  229. * @param 若元素存在, 则返回删除后稀疏矩阵中非 0 元素个数, 否则返回NPOS
  230. */
  231. int DeleteElem( TMatrix *const pMat, int m, int n )
  232. {
  233. ///使用断言确保下标合法
  234. assert( m >= && m < pMat->row && n >= && n < pMat->col );
  235.  
  236. int pos = ElemLocate( pMat, m, n );
  237.  
  238. ///该元素是否存在
  239. if( pos == NPOS )
  240. return NPOS;
  241.  
  242. ///删除该位置上的元素以及记录
  243. for( pos; pos < pMat->unul - ; ++pos )
  244. {
  245. pMat->tup[pos].m = pMat->tup[pos+].m;
  246. pMat->tup[pos].n = pMat->tup[pos+].n;
  247. pMat->tup[pos].elm = pMat->tup[pos+].elm;
  248. }
  249.  
  250. ///缩小内容占用
  251. pMat->tup = (TTuple *)realloc( pMat->tup, sizeof(TTuple) * (pMat->unul - ) );
  252.  
  253. return --pMat->unul;
  254. }
  255.  
  256. /**
  257. * @brief 将源稀疏矩阵复制到目标稀疏矩阵中
  258. *
  259. * @param pMatDest 指向目标稀疏矩阵
  260. * @param pMatSrc 指向源稀疏矩阵
  261. *
  262. * @return 返回复制成功后目标稀疏矩阵中的非0元素数量
  263. */
  264. int TMatrixCopy( TMatrix *const pMatDest, TMatrix *const pMatSrc )
  265. {
  266. if( pMatDest->tup )
  267. free( pMatDest->tup );
  268.  
  269. ///源稀疏矩是否为空
  270. if( pMatSrc->tup )
  271. { //不为空, 复制矩阵
  272. pMatDest->tup = (TTuple *)calloc( pMatSrc->unul, sizeof(TTuple) * pMatSrc->unul );
  273. assert( pMatDest->tup );
  274. memcpy( pMatDest->tup, pMatSrc->tup, sizeof(TTuple) * pMatSrc->unul );
  275. }
  276. else pMatDest->tup = NULL;
  277.  
  278. pMatDest->row = pMatSrc->row;
  279. pMatDest->col = pMatSrc->col;
  280. pMatDest->unul = pMatSrc->unul;
  281.  
  282. return pMatDest->unul;
  283. }
  284.  
  285. /**
  286. * @brief 从稀疏矩阵中获取下标为 m, n 元素的值
  287. *
  288. * @param pMat 指向待获取元素的稀疏矩阵
  289. * @param m 元素所在位置的行下标
  290. * @param n 元素所在位置的列下标
  291. * @param pElm 接收数据元素的指针
  292. *
  293. * @return 返回该元素在稀疏矩阵中的位置
  294. *
  295. * @note 位置由 0 计起
  296. */
  297. int Value( const TMatrix *const pMat, int m, int n, ElemType *pElm )
  298. {
  299. ///使用断言确保下标合法
  300. assert( m >= && m < pMat->row && n >= && n < pMat->col );
  301.  
  302. int pos = ElemLocate( pMat, m, n );
  303. if( pos != NPOS )
  304. {
  305. *pElm = pMat->tup[pos].elm;
  306. return pos;
  307. }
  308. else
  309. {
  310. *pElm = ;
  311. return NPOS;
  312. }
  313. }
  314.  
  315. /**
  316. * @brief 对稀疏矩阵中的每个元素依次执行 func 函数
  317. *
  318. * @param pMat 指向待处理的稀疏矩阵
  319. * @param func 回调函数
  320. *
  321. * @return void
  322. */
  323. void ForEach( const TMatrix *const pMat, void (*func)(ElemType *pElm) )
  324. {
  325. int m = , n = , pos = , t = ;
  326.  
  327. for( m = ; m < pMat->row; ++m )
  328. for( n = ; n < pMat->col; ++n )
  329. {
  330. pos = ElemLocate( pMat, m, n );
  331.  
  332. if( pos != NPOS )
  333. func( &pMat->tup[pos].elm );
  334. else
  335. func( &t );
  336. }
  337. }
  338.  
  339. ///测试
  340.  
  341. /**
  342. * @brief ForEach的回调函数, 若元素为 0 则输出'x', 否则正常输出
  343. */
  344. void display( ElemType *pElm )
  345. {
  346. if( *pElm == )
  347. putchar( 'x' );
  348. else
  349. printf( "%d", *pElm );
  350. }
  351.  
  352. int main()
  353. {
  354. ///稀疏因子为 0.098 的二维数组
  355. ElemType arrMat[][] = {
  356. {, , , , , , , , , , , , , , },
  357. {, , , , , , , , , , , , , , },
  358. {, , , , , , , , , , , , , , },
  359. {, , , , , , , , , , , , , , },
  360. {, , , , , , , , , , , , , , },
  361. {, , , , , , , , , , , , , , },
  362. {, , , , , , , , , , , , , , },
  363. {, , , , , , , , , , , , , , },
  364. {, , , , , , , , , , , , , , },
  365. {, , , , , , , , , , , , , , },
  366. {, , , , , , , , , , , , , , },
  367. {, , , , , , , , , , , , , , },
  368. {, , , , , , , , , , , , , , },
  369. {, , , , , , , , , , , , , , },
  370. {, , , , , , , , , , , , , , }
  371. };
  372.  
  373. ///测试 CreateTMatirxFrom2DArray
  374. ///从二维数组 arrMat 中创建稀疏矩阵
  375. TMatrix *pMat = CreateTMatirxFrom2DArray( arrMat, , );
  376. printf( "稀疏矩阵占用空间大小: %d (byte)\n", GetTMatrixSize(pMat) );
  377.  
  378. ///测试 CreateEmptyTMatrix
  379. ///创建一个 5 x 5 大小的稀疏矩阵
  380. TMatrix *pMat2 = CreateEmptyTMatrix( , );
  381.  
  382. ///测试 TMatrixCopy
  383. ///将 pMat 复制到 pMat2
  384. TMatrixCopy( pMat2, pMat );
  385.  
  386. ///测试 DisplayTMatrix
  387. printf( "输出稀疏矩阵 pMat2:\n" );
  388. DisplayTMatrix( pMat2 );
  389.  
  390. ///测试 AppendElem
  391. printf( "将 0, 0 处元素置为 1.\n" );
  392. AppendElem( pMat2, , , );
  393.  
  394. ///测试 DeleteElem
  395. printf( "删除 0, 1 处的元素.\n" );
  396. DeleteElem( pMat2, , );
  397.  
  398. ///输出 pMat2
  399. printf( "输出稀疏矩阵 pMat2:\n" );
  400. DisplayTMatrix( pMat2 );
  401.  
  402. ///测试 Value
  403. int a = -;
  404. Value( pMat2, , , &a );
  405. printf( "位置 10, 8 处的元素为: %d\n", a );
  406.  
  407. ///测试 ForEach
  408. printf( "将稀疏矩阵中值为0的元素用x代替并全部输出:\n" );
  409. ForEach(pMat2, display );
  410.  
  411. ///销毁稀疏矩阵
  412. DestroyTMatrix( pMat );
  413. DestroyTMatrix( pMat2 );
  414.  
  415. return ;
  416. }

运行测试:

若代码存在 bug 或程序缺陷, 请留言反馈, 谢谢。                                                                                                                                                                                                                                                                                                                                                       

C语言 稀疏矩阵 压缩 实现的更多相关文章

  1. C语言 对称矩阵 压缩 实现

    对称矩阵压缩的简单实现 (GCC编译). /** * @brief C语言 对称矩阵 压缩 实现 * @author wid * @date 2013-11-03 * * @note 若代码存在 bu ...

  2. C语言Huffman压缩和解压

    符号表结构体: struct node { // 字符串形式存储的Huffman编码 char code[MAX_CODE_LENGTH]; // 这个字符在文件中出现的次数 long count; ...

  3. java实现稀疏矩阵的压缩与解压

    任务要求 把棋盘当作一个稀疏矩阵,0表示没棋,1表示黑棋,2表示蓝棋. 把该稀疏矩阵压缩以三元组形式表示并以文件形式保存,再写另一个程序读取文件中的信息把压缩后的三元组还原成原来的稀疏矩阵. 其中三元 ...

  4. C# .NET 使用第三方类库DotNetZip解压/压缩Zip rar文件

    DotNetZip on CodePlex: http://dotnetzip.codeplex.com/ 详细的可以看源代码……总之感觉比SharpZipLib好用.而且DotNetZip支持VB, ...

  5. 在Spark程序中使用压缩

    当大片连续区域进行数据存储并且存储区域中数据重复性高的状况下,数据适合进行压缩.数组或者对象序列化后的数据块可以考虑压缩.所以序列化后的数据可以压缩,使数据紧缩,减少空间开销. 1. Spark对压缩 ...

  6. C++ 特殊矩阵的压缩存储算法

    1. 前言 什么是特殊矩阵? C++,一般使用二维数组存储矩阵数据. 在实际存储时,会发现矩阵中有许多值相同的数据或有许多零数据,且分布呈现出一定的规律,称这类型的矩阵为特殊矩阵. 为了节省存储空间, ...

  7. OLAP了解与OLAP引擎——Mondrian入门

    一.  OLAP的基本概念 OLAP(On-Line Analysis Processing)在线分析处理是一种共享多维信息的快速分析技术:OLAP利用多维数据库技术使用户从不同角度观察数据:OLAP ...

  8. C++ 记事本: 从历史说起

    C 的简史 在谈论 C++ 的历史那么必须先得了解 C 的历史,那么我们先来看一段来自于 <<C专家编程>> 对 C 语言史前阶段的简单阐述: Ken Thompson(左), ...

  9. 算法设计手冊(第2版)读书笔记, Springer - The Algorithm Design Manual, 2ed Steven S.Skiena 2008

    The Algorithm Design Manual, 2ed 跳转至: 导航. 搜索 Springer - The Algorithm Design Manual, 2ed Steven S.Sk ...

随机推荐

  1. xtrabackup备份与恢复实践

    说明   xtrabackup  --percona 特点: 开源,在线备份innodb表 支持限速备份,避免对业务造成影响 支持流备 支持增量备份 支持备份文件压缩与加密 支持并行备份与恢复,速度快 ...

  2. Web前端之html_day2

    1.meta标签 1 2 3 <metacharset="UTF-8"/> <metaname="Keywords" content=&quo ...

  3. mysql事件定时

    DELIMITER $$ MONTH STARTS '2013-01-07 11:20:00' ON COMPLETION PRESERVE ENABLE DO BEGIN CALL ps(); EN ...

  4. Factstone Benchmark

    [问题描述] Amtel已经宣布,到2010年,它将发行128位计算机芯片:到2020年,它将发行256位计算机:等等,Amtel坚持每持续十年将其字大小翻一番的战略.(Amtel于2000年发行了6 ...

  5. centos7 ip地址设置

    centos7 ip地址设置 http://simonhu.blog.51cto.com/196416/1588971 CentOS系统 修改DNS 修改对应网卡的DNS的配置文件 # vi /etc ...

  6. mysql事务处理用法与实例详解

    来源:转载  MySQL的事务支持不是绑定在MySQL服务器本身,而是与存储引擎相关1.MyISAM:不支持事务,用于只读程序提高性能 2.InnoDB:支持ACID事务.行级锁.并发 3.Berke ...

  7. stm32 MDK5软件仿真之查看io口输出

    软件MDK5 stm32的pack     打开MDK,添加工程 一.首先找到Project的Options选项,里面的Debug选为Use Simulator,也就是选择软件仿真. 然后再Logic ...

  8. 获取WINDOW.OPEN url js中的get取值

    function getUrlParam(name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)( ...

  9. ios NSThred多线程简单使用

    关于NSThred开启多线程的方法 - (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg [self perfor ...

  10. LVS三种工作方式八种算法

    一.集群简介 什么是集群 计算机集群简称集群是一种计算机系统,它通过一组松散集成的计算机软件和/或硬件连接起来高度紧密地协作完成计算工作.在某种意义上,他们可以被看作是一台计算机.集群系统中的单个计算 ...