① 数据结构-特殊矩阵的压缩存储
本文介绍对称矩阵、三角矩阵、对角矩阵和稀疏矩阵的压缩存储方法。
在一个n阶矩阵A中,若元素满足aij=aji,0<=i,j<=n-1,则称矩阵A为对称矩阵。
按行优先顺序将这些元素存放在一个一维数组s[n(n+1)/2]中,元素aij在s中对应的下标为k:
以主对角线划分,三角矩阵分为上三角和下三角两种,上三角矩阵的下三角所有元素均为常数c,下三角矩阵正好相反。
按行优先顺序将三角矩阵存放在一维数组s[n(n+1)/2+1],其中常数c存放在数组的最后一个分量中。
上三角矩阵元素aij在s中对应的下标为k:
下三角矩阵元素aij在s中对应的下标为k:
对角矩阵是指矩阵中所有的非零元素集中在以主对角线为中心的带状区域中。一个k对角矩阵(k为奇数)A满足若|i-j|>(k-1)/2则元素aij=0。
将三对角矩阵A中的非零元素按行优先顺序存放到数组s[3n-2]中,在三对角矩阵A中,除第一行和最后一行只有两个非零元素外,其他每行中均有三个非零元素。三对角矩阵中的元素aij在s中对应的下标为 k=3×i-1+j-(i-1)=2×i+j .
设矩阵Amn中有s个非零元素,若s远远小于矩阵元素的总数,即s<<mxn,则称A为稀疏矩阵。
对于稀疏矩阵的压缩存储方法通常有两种,分别是三元组顺序表和十字链表。
1. 三元组顺序表
每个元素是一个结构体,包括该元素在矩阵中的行数、列数和数值,所有元素存在一个向量vector中,并同时记录矩阵的行数、列数及非零元素个数等信息。
2. 十字链表
为了克服顺序表中对非零元素插入和删除操作带来的不便,采用链接存储结构存储稀疏矩阵。
十字链表将每个元素存储为一个结构体,除了包括元素的行号、列号、数值外,还包括一个向右指针域用于指向同一行中的下一个非零元素和一个向下指针域用于指向同一列中的下一个非零元素。所有结构体通过两个一维指针数组分别存储各个行链表的头指针和各个列链表的头指针组织成一个整体。
目标是将每个元素的行号列号交换,并按照新的行列号按序存放。关键在于如何高效地进行按序存放。
方法一:朴素转置算法
按照原列号分别从头至尾扫描,依次放入新的矩阵中。对于一个m行n列且非零元素个数为t的稀疏矩阵而言,该算法的时间复杂度为O(t×n)。
方法二:快速转置算法
采用一个数组cnum[cols]记录每一列中的元素个数,一个数组cpot[cols]记录每一列的第一个非零元素在转置矩阵顺序表中的下标。cnum和cpot各采用一次遍历得到,其中cpot[0]=0,cpot[col]=cpot[col-1]+cnum[col-1]。
② 在MATLAB中,“矩阵元素的序号和下标可以相互转换”,这句话怎么理解谢谢
例如矩阵a
>> a=[1 2 3; 4 5 6 ]
a =
1 2 3
4 5 6
则a(1,1)=1, a(2,3)=6,其中,a(1,1)表示a的第一行第一列的元素,a(2,3)表示a的第二行第三列的元素。(1,1)和 (2,3)就是下标(Subscript )。矩阵元素的序号就是矩阵元素的存储顺序,在这个例子中这个矩阵中的元素的存储顺序是1 4 2 5 3 6, 第4个元素即a(4)=5 。
“矩阵元素的序号和下标可以相互转换”,这句话就是说a(4)和a(2,2)一样,a(2)和a(2,2)一样,a(5)和a(1,3)一样。参见help sun2ind 。
可以通过下标(行列索引)引用矩阵的元素,如 Matrix(m,n)。也能用元素的序号来引用矩阵元素。矩阵元素的序号就是相应元素在内存中的摆列顺序。在MATLAB中,矩阵元素按列储存,先储存头列,再第二列,依次类推。序号(Index)与下标(Subscript )是一一对应的,以m*n矩阵A为例,矩阵元素A(i,j)的序号为(j-1)*m+i。其彼此转换关系也可利用sub2ind和ind2sub函数求得。
③ 矩阵M23是什么
矩阵M23是:
在实现中通常将其存储为一个一维的线性数组如float matrix【16】或者float* matrix。
在opengl中这个matrix中数据的顺序是先遍历列的,线性存储为{m11,m21,m31,m41,m12,m22,m32......},这被称为矩阵的列序(column-major)存储,我们使用GlGetfloatv(GL_MODELVIEW_MATRIX,...)等得到的存储矩阵的数组都是按照这样的顺序存储矩阵的。
但是在cg中这个matrix的存储顺序确实先遍历行的,也就是存储为{m11,m12,m13,m14,m21,m22,m23,m24,m31,......},称为行序(row-major)存储,可能多数人认为这种存储顺序更“自然”,(其实我也这么觉得),这种存储方式也被称为是c-style的,好像是大多数系统里是按照行序存储矩阵的。
不同的系统对矩阵的存储方式不一样,如果在程序中综合使用了不同的框架,就要注意进行统一了,比如你在opengl 中使用了CG脚本的时候,例如一个cg程序void programm(uniform float4x4 modelviewMatrix,... ...)要求你从程序中传入一个modelview矩阵,我们在程序中使用opengl的GlGetfloatv()函数得到了float* glmatrix 为这个modelview矩阵,但是这个glmatrix确不能直接赋给modelviewMatrix供cg使用,因为cg在解析这个glmatrix 会把它解析为行序的,我们可以在让modelviewMatrix得到glmatrix 后,调用transfor()将modelviewMatrix做一个转置,modelviewMatrix就变成cg所能正确解析的行序的了。
行序和列序的转换其实就是一个矩阵的转置关系,虽然这个变换很简单,但是在使用不同的框架时,要记得先注意一下这个系统式采用哪种方式存储矩阵的,才不会犯错。
④ 上三角矩阵按行优先存储公式
题目出错了,上三角肯定是 i<=j
公式也不对,怎么可能跟n无关呢,第i行的元素个数是n-i+1,
a(i,j)前面有i-1行,这i-1行共有(n-1+1)+...+(n-(i-1)+1)个元素,第i行有j-i+1,加在一起再减1就是k(因为数组下标为0)
⑤ 利用稀疏矩阵的顺序存储实现稀疏矩阵的加、减、乘、转置等简单运算。 这是课题要求,求大佬用c语言。
内容
假设两个稀疏矩阵A和B,他们均为m行n列,要求表写求矩阵的加法即:C=A+B的算法(C矩阵存储A与B相加的结果)
分析
利用一维数组来存储,一维数组顺序存放非零元素的行号、列号和数值,行号-1表示结束,然后进行矩阵加法运算时依次扫描矩阵A和B的行列值,并以行优先。当行列相同的时候,将第三个元素的值相加和以及行列号三个元素存入结果数组C中;不相同时,将A或B的三个元素直接存入结果数组中。
代码
// fanchen.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include<iostream> using namespace std; #define LINE 10 struct Node{ //行号 int row; //列号 int line; //数据 int data; }; //初始化数组 int init(Node array[]) { int row,line,data; int index = 0; while(cin>>row){ if(row == -1){ break; } cin>>line>>data; array[index].data=data; array[index].line = line; array[index].row = row; index++; } return index; } //打印数组 void printArray(Node array[],int len) { for(int i = 0;i < len;i++){ cout<<array[i].row<<" "<<array[i].line<<" "<<array[i].data<<endl; } } int calc(Node a
⑥ 稀疏矩阵是怎样存储的
/*
稀疏矩阵的三元组顺序表存储表示
*/
# define MAX_SIZE 100//非零元个数的最大值
struct Triple
{
int i,j;//行下标,列下标
ElemType e;//非零元素值
};
struct TSMatrix
{
Triple data[MAX_SIZE+1];//非零元三元组表,data[0]未用
int mu,nu,tu;//矩阵的行数、列数和非零元个数
};
⑦ 固态硬盘每个矩阵储存多少
对于一般线性结构的矩阵,我们采用顺序存储结构,以二维数组来存储。
以二维数组存储分为两种主要形式:以行为序存储以列为序存储。
这样对于一个矩阵,一旦确定了行数和列数,便可以为其分配存储空间,反之,如果给定了矩阵中的第一个元素的存放地址(basic address),我们就可以将矩阵中元素的存储地址表示为其下标的线性函数,这样就可以随机读取或查找矩阵中的任意一个元素。比如:Loc(a ij) = Loc(a 11) + [(i-1)*n+(j-1)]*d 我们假设每个元素占用d个单元,aij就是前面所有元素占用的单元数加上基地址。
⑧ 设有一个 10 × 10的对称矩阵 A采用压缩方式进行存储,存储时以按行优先的顺序
对称矩阵且存储的是下三角,那你首先得看a65是在下三角还是上三角,因为上三角的值是由下三角对称的值来存储的。6>5,a65在下三角。按行存储下三角,从第一行开始分别存储1,2,3,...个元素,a65表示第7行的第6个元素,那他前面的数据占的字节就是(1+2+3+4+5+6+5)*2=52,所以a65的地址是下一个53
⑨ 多维数组-矩阵的压缩存储- 特殊矩阵(二)
三角矩阵
( )三角矩阵的划分
以主对角线划分 三角矩阵有上三角矩阵和下三角矩阵两种
①上三角矩阵
如下图(a)所示 它的下三角(不包括主角线)中的元素均为常数c
②下三角矩阵
与上三角矩阵相反 它的主对角线上方均为常数c 如下图(b)所示
注意
在多数情况下 三角矩阵的常数c为零
( )三角矩阵的压缩存储
三角矩阵中的重复元素c可共享一个存储空间 其余的元素正好有n×(n+ )/ 个 因此 三角矩阵可压缩存储到向量sa[
n(n+ )/ ]中 其中c存放在向量的最后一个分量中
① 上三角矩阵中a ij 和sa[k]之间的对应关系
上三角矩阵中 主对角线之上的第p行( ≤p <n)恰有n-p个元素,按行优先顺序存放上三角矩阵中的元素a 时:
a ij 元素前有i行(从第0行到第i-1行),一共有:
(n-0)+(n-1)+(n-2)+…+(n-i)=i×(2n-i+1)/2个元素;
在第i行上,a ij 之前恰有j-i个元素(即a ij ,a i,j+l ,…,a i,j-1 ),因此有:
sa[i×(2n-i+1)/2+j-i]= a ij
所以:
┌i×(2n-i+1)/2+j-i 当i≤j
k=│
└n×(n+1)/2 当i>j
②下三角矩阵中a ij 和sa[k]之间的对应关系
┌i×(i+1)/2+j 当i≥j
k=│
└n×(n+1)/2 当i <j p=""> </j>
注意:
三角矩阵的压缩存储结构是随机存取结构。wIngWIt.Com
3.对角矩阵
所有的非零元素集中在以主对角线为中心的带状区域中,即除了主对角线和主对角线相邻两侧的若干条对角线上的元素之外,其余元
素皆为零的矩阵为对角矩阵。
【例】下图给出了一个三对角矩阵。
其中:
非零元素仅出现在主对角上(a ii ,0≤i≤n-1),紧邻主对角线上面的那条对角线上(a i , i+1 ,0≤i≤n-2)和紧邻主对角线下
面的那条对角线上(a i+1 , i ,0≤i≤n-2)。当|i-j|>1时,元素a ij =0。
由此可知,一个k对角线矩阵(k为奇数)A是满足下述条件的矩阵:
若|i-j|>(k-1)/2,则元素a ij =0。
对角矩阵可按行优先顺序或对角线的顺序,将其压缩存储到一个向量中,并且也能找到每个非零元素和向量下标的对应关系。具
体【参见练习】
lishixin/Article/program/sjjg/201311/23898
⑩ 有一矩阵,用C描述:int a[100][100];该矩阵按先行后列次序存储。
这个好像是操作系统里的东西,很长时间没看了,早忘了,但是基本原理应该是这样的仅供参考:
A:for (i=0;i<100;i++) for (j=0;j<100;j++) a[i][j]=0;
参数会从i=0;j从0————100,数组行不变时按顺序存储,的第一行开始存储前面100个会报缺页,后面数字都是零,就不会报缺页,当一个页面存储达到200个数字后会换页到下一页存储。
B:for (j=0;j<100;j++) for (i=0;i<100;i++) a[i][j]=0;
因为是啊a[i][j]前面是j也就是数组的列在改变,而后面的i也就是行在改变,
与A不同的是当j=0;是i从0————100;也就是说数组的行在不停的改变,行改变了,存储顺序不断发生改变,每次改变行的时候就会切换不同的页面,所一第二种程序的缺页次数更多。