线性代数4:稀疏矩阵的十字链表表示法

来源:互联网 发布:windows许可证激活工具 编辑:程序博客网 时间:2024/04/28 02:15

    十字链表为稀疏矩阵的没一行单独设置一个链表,同时也为每一列单独设置一个链表。这样稀疏矩阵的每一个非零元素就同时在两个链表中,即每一个非零元素同时包含在所在行的行链表中和所在列的列连表中。这就大大降低了链表的长度,方便了算法中行方向和列方向的搜索

,因而大大降低了算法的时间复杂度。

 

其中i,j,value分别代表非零元素所在的行号,列号和相应的元素值;down和right分别称为向下指针和向右指针,分别用来连接同列中和同行中的下一个非零元素点。也就是说,稀疏矩阵中同一列的所有非零元素通过down指针链接成一个列链表,同一行中所有非零元素通过right指针链接成一个行链表。对稀疏矩阵的每个非零元素来说,它既是某个行链表中的一个节点也是摸个列链表中的一个节点。每个非零元素好比是在十字路口由此称为十字链表。

 

 

十字链表中设置行头结点,列头结点和链表头结点。他们采用和非零元素节电类似的结构,如下图所示。

 

 

 

其中行头结点和列头节点的i,j域值均为0;行头结点的right指针指向该行链表的第一个节点,它的down指针为空;列头结点的down指针指向该列链表的第一个节点,

它的right域为空,行头结点和列头结点必须顺序链接,这样,当需要逐行(列)搜索时,才能一行(列)搜索完后顺序搜索下一行(列),行头结点和列头结点均用link指针完成顺序链接。对比行头结点和列头结点可以看到,行头结点中未用down指针,列头结点中未用right指针,link指针完成行或列头节点的顺序连接,i和j域未用。因此行和列的头结点可以合用,即第i行和第i列头结点公用一个头结点。称这些合并后的头结点为行列头结点,行列头结点数目为行数m和列数n的最大值。十字链表头指针head指向链表头结点,链表头结点的i,j域分别存放稀疏矩阵的行数m和列数n,链表头结点的link指针指向行列头结点链表中的

第一个行列头结点。由于矩阵运算中常常是一行(列)操作完成后进行下一行(列)的操作,所以十字链表中的所有单链表均连接成循环链表。

这样就可方便的完成一行(列)操作后又回到该行列头结点,由link指针进入下一个行列头结点,重新开始下一行(列)的相同操作。


设系数矩阵是:
               |1  0  0  2|
B 3*4  =  |0  0  3  0|
               |0  0  0  4|

 
则对应的十字链表如图所示。为清楚说明把每个行列头结点分别画成两个,而实际上,行头结点hi(0<= i <= 4)与列头结点hi存在一个这样的节点。

 

 

十字链表节点结构和头结点的数据结构可以定义如下:


/*十字链表表示的基本数据结构*/

 

从data结构到十字链表的转换是:
---------------------------------------------------------------------------------------------------------------------
/*返回一个指向十字链表数据结构的头结点的指针

head_array已经申请了内存  :
(head_array = (cros_node ** )calloc (max + 1,sizeof (cros_node *));
    max 的定义如下面的函数所示;                  )

(此时已为十字链表数据结构申请了内存用完后要释放内存 (可通过调用函数 void destroy_cros_array (cros_node *head );)
 
 下面这个函数为head_array所指向的节点赋值:
 假设下面的函数返回值放在      cros_node      *node;   里面
 有:node -> tag.link   = head_array[1];
     node -> tag.link -> tag.link 
   = head_array[2];
以此类推;

 注意这里的sour必须指向一个最简矩阵   */


---------------------------------------------------------------------------------------------------------------------
void destroy_cros_array (cros_node *head )函数定义如下:

 对于一个m*n的系数矩阵,每个非零元素用一个节点表示,节点结构可以设计成如下图所示。

原创粉丝点击