1 /**2 * 十字链表3 *4 * 当矩阵的非零个数和位置在操作过程中变化大时,就不宜采用顺序存储结构来表示三元组的线性表。例如,在作“将矩阵B加到矩阵A上”的操作时,由于非零元的插入或删除将会引起A.data中元素的移动。为此,对这种类型的矩阵,采用链式存储结构表示三元组的线性表更为恰当。5 *6 * 在链表中,每个非陵园可用一个含5个域的结点表示,其中i,j和e这3个域分别表示该非零元所在的行,列和非零元的值,向右域right用以链接同一行中下一个非零元,向下域down用以链接同一列中下一个非零元。同一行的非零元通过right域链接成一个线性表,同一列中的非零元通常down域链接成一个线性链表,每一个非零元既是某个行链表中的一个结点,又是某个列链表中的一个结点,整个矩阵构成了一个十字交叉的链表。7 *8 * 可用两个分别存储行链表的头指针和列链表的头指针的一维数组来表示。9 */
10
11 //稀疏矩阵的十字链表存储表示
12
13 functionOLNode(i, j, e) {14 //该非零元的行和列下标
15 this.i = i || 0;16 this.j = j || 0;17 this.e =e;18 //该非零元所在行表和列表的后继链域
19 this.right = null; //type: OLNode
20 this.down = null; //type: OLNode
21 }22
23 functionCrossList() {24 //行和列链表头指针向量基址由CreateSMatrix分配
25 this.rhead =[];26 this.chead =[];27 //稀疏矩阵的行数,列数
28 this.mu = 0;29 this.nu = 0;30 this.tu = 0;31 }32 /**33 * 矩阵初始化34 * @param m35 * @param n36 * @param t37 * @param {Array} list 二维数组,每行的元素分别是[i, j, e]38 */
39 CrossList.prototype.createSMatrix = function(m, n, t, list) {40 this.mu =m;41 this.nu =n;42 this.tu =t;43
44 for (var row = 0; row < list.length; row++) {45 var p ={};46 OLNode.apply(p, list[row]);47 var i = list[row][0];48 var j = list[row][1];49 varq;50
51 if (this.rhead[i] == null || this.rhead[i].j >j) {52 p.right = this.rhead[i];53 this.rhead[i] =p;54 } else{55 //查询在行表中的插入位置
56 for (q = this.rhead[i]; q.right && q.right.j < j; q =q.right);57 p.right =q.right;58 q.right =p;59 }60
61 if (this.chead[j] == null || this.chead[j].i >i) {62 p.down = this.chead[j];63 this.chead[j] =p;64 } else{65 for (q = this.chead[j]; q.down && q.down.i < i; q =q.down);66 p.down =q.down;67 q.down =p;68 }69 }70 };71
72 //矩阵相加
73 CrossList.prototype.addMatrix = function(crossList) {74 var hl =[];75 //hl初始化
76 for (var j = 0; j <= this.nu; j++)77 hl[j] = this.chead[j];78
79 for (var i = 0; i <= this.mu; i++) {80 //pa和pb指向每一行的第一个非0元结点,直至最后一行
81 var pa = this.rhead[i];82 var pb =crossList.rhead[i];83 var pre = null;84
85 //处理B的一行,直至本行中无非0元素的结点
86 while(pb) {87 varp, q;88 //新插入一个结点到pa的左侧
89 if (!pa || pa.j >pb.j) {90 p = newOLNode(pb.i, pb.j, pb.e);91
92 //行表的指针变化
93 if (!pre) this.rhead[p.i] =p;94 else pre.right =p;95
96 p.right =pa;97 pre =p;98
99 //列表的指针变化
100 if(hl[p.j]) {101 //从hl[p.j]开始找到新结点在同一列中的前驱结点,并让hl[p.j]指向它
102 for (q = hl[p.j]; q && q.i < p.i;q =q.down)103 hl[p.j] =q;104 }105
106 //在列表中插入新结点,根据行数判断插入前面还是后面
107 if (!this.chead[p.j] || this.chead[p.j].i >p.i) {108 p.down = this.chead[p.j];109 this.chead[p.j] =p;110 } else{111 p.down =hl[p.j].down;112 hl[p.j].down =p;113 }114
115 hl[p.j] =p;116 pb =pb.right;117 } else if (pa.j
122 pa.e +=pb.e;123
124 //当pa.e === 0时,删除该结点
125 if (pa.e === 0) {126 //若无前驱结点,将第一个非0元结点置为当前结点的后继结点,
127 //否则前驱结点的后继结点为当前结点的后继结点
128 if (!pre) this.rhead[pa.i] =pa.right;129 else pre.right =pa.right;130
131 p =pa;132 pa =pa.right;133
134 //列表的指针变化
135 if(hl[p.j]) {136 //从hl[p.j]开始找到新结点在同一列中的前驱结点,并让hl[p.j]指向它
137 for (q = hl[p.j]; q && q.i < p.i; q =q.down)138 hl[p.j] =q;139 }140
141 if (this.chead[p.j] ==p)142 this.chead[p.j] = hl[p.j] =p.down;143 else
144 hl[p.j].down =p.down;145 }146
147 pb =pb.right;148 }149 }150 }151 };152
153 var lists =[154 [1, 4, 5],155 [2, 2, -1],156 [1, 1, 3],157 [3, 1, 2]158 ];159 var a = newCrossList();160 a.createSMatrix(4, 4, 4, lists);161 console.log(a);162
163 var lists2 =[164 [1, 4, -5],165 [2, 3, 1],166 [1, 1, 3],167 [3, 2, 2]168 ];169 var b = newCrossList();170 b.createSMatrix(4, 4, 4, lists2);171 console.log(b);172
173 a.addMatrix(b);174 console.log(a);