关于稀疏矩阵,就是值为0的元素数量很多的矩阵。如果把0元素位置看成空白,非零看成黑点,稀疏矩阵就像是一张照片,广阔的天空中只有远方的几只鸟。我也不知道这么理解对不对,瞎猜的。
至于矩阵的应用,书上说计算机图形学,工程技术中会用到,但现在我没整过具体的东西,所以就关于稀疏矩阵有啥用,以后碰到了再补上。
那么现在如何存储稀疏矩阵呢?怎样才能做到存的空间小,修改起来方便,使用的时候能快速呢。目前我只知道两种书上提到的方法:
1.三元组线性表
2.十字链表OrthogonalList
现在,就十字链表,使用C++实现。先说下十字链表的数据结构,然后说下具体实现。
十字链表的数据结构
链表嘛,就是一串羊肉串,一小块羊肉就是一个结点,结点里有骨头也有肉。十字链表就是一维链表+另一维链表。
(1)这是结点:
row是行,col是列,value/next是联合(要么是一个T类型的值,要么是一个OrthogonalNode *类型的地址
(2)这是十字链表的例子:
这里是引用教科书上的例子
很容易看出十字链表的存储原理,本质上就是个二维的链表
十字链表的实现
// DS_OrthogonalList.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
template<class T>
struct OrthogonalNode
{
int m, n;
OrthogonalNode<T> *down, *right;
union
{
T value;
OrthogonalNode<T> *next;
};
};
template<class T>
class OrthogonalList
{
public:
OrthogonalList<T>(T *matrix, int row, int col);
void insertE(OrthogonalNode<T> *p);
void deleteE(OrthogonalNode<T> *p);
OrthogonalNode<T> *Gethead(int i);
OrthogonalNode<T> *head;
private:
int rows, cols, numbers;
vector<OrthogonalNode<T> *> orthogonalArray;
};
int main()
{
int matrix[] = { 3, 0, 0, 1, 0, -4, 8, 0, 2, 0, 0, 6 };
OrthogonalList<int> oList(matrix, 3, 4);
//test:遍历所有结点,如果成功遍历,说明十字链表的构造成功
OrthogonalNode<int> *me = oList.head->right, *subMe = me->down;
while (oList.head != me)
{
while (me != subMe)
{
cout << "(" << subMe->m << "," << subMe->n << "," << subMe->value << ") ";
subMe = subMe->down;
}
cout << endl;
me = me->next;
subMe = me->down;
}
system("pause");
return 0;
}
template<class T>
OrthogonalList<T>::OrthogonalList(T * matrix, int row, int col)
{
//初始化总链头,头结点包含非(row行,col列,非零元素个数)
if (!orthogonalArray.empty())//如果向量不空,那么就将向量重置为临时对象
vector<OrthogonalNode<T> *>().swap(orthogonalArray);
rows = row;
cols = col;
head = new OrthogonalNode<T>;
//head->value = ?,后面处理
head->down = NULL;
head->right = head;
head->m = row;
head->n = col;
//初始化子链头,头结点对应为base行base列
int maX = max(row, col);
OrthogonalNode<T> *me = head;
for (int base = 0; base <= maX - 1; ++base)
{
OrthogonalNode<T> *subHead = new OrthogonalNode<T>;
subHead->next = head;
subHead->down = NULL;
subHead->right = NULL;
subHead->m = 0;
subHead->n = 0;
if (head == me)
me->right = subHead;
else
me->next = subHead;
me = subHead;
orthogonalArray.push_back(subHead);
}
//遍历,当base行i列为非零元素,则插入到链表中,非零元素总数numbers加一
for (int base = 0; base <= row - 1; ++base)
for (int i = 0; i <= col - 1; ++i)
if (0 != matrix[base*col + i])
{
OrthogonalNode<T> *temp = new OrthogonalNode<T>;
temp->m = base;
temp->n = i;
temp->value = matrix[base*col + i];
insertE(temp);
++orthogonalArray[base]->m;
++orthogonalArray[i]->n;
++numbers;
}
head->value = numbers;//终于,知道了元素的总个数
}
template<class T>
void OrthogonalList<T>::insertE(OrthogonalNode<T>* p)
{
//将结点插入到对应p->m行的链表中
OrthogonalNode<T> *rowHead = orthogonalArray[p->m], *colHead = orthogonalArray[p->n],
*before = rowHead, *after = before->right;
while (rowHead != after && NULL != after)
{
if (after->n > p->n)
break;
before = before->right;
after = after->right;
}
before->right = p;
p->right = after;
if (NULL == after)
p->right = rowHead;
//将结点插入到对应p->n列的链表中
before = colHead; after = before->down;
while (colHead != after && NULL != after)
{
if (after->m > p->m)
break;
before = before->down;
after = after->down;
}
before->down = p;
p->down = after;
if (NULL == after)
p->down = colHead;
}
template<class T>
void OrthogonalList<T>::deleteE(OrthogonalNode<T>* p)
{
//和insert同理,省略
}
template<class T>
OrthogonalNode<T>* OrthogonalList<T>::Gethead(int i)
{
return nullptr;
}