MATLAB第七章.docx
- 文档编号:12314085
- 上传时间:2023-06-05
- 格式:DOCX
- 页数:39
- 大小:118.77KB
MATLAB第七章.docx
《MATLAB第七章.docx》由会员分享,可在线阅读,更多相关《MATLAB第七章.docx(39页珍藏版)》请在冰点文库上搜索。
MATLAB第七章
第七章稀疏矩阵单元阵列结构3
7.1稀疏矩阵3
7.1.1sparse数据类型4
例7.16
7.2单元阵列(cellarray)8
7.2.1创建单元阵列9
7.2.2单元创建者——大括号({})的应用10
7.2.3查看单元阵列的内容10
7.2.4对单元阵列进行扩展11
7.2.5删除阵列中的元素12
7.2.6单元阵列数据的应用12
7.2.7字符串单元阵列12
7.2.8单元阵列的重要性13
7.2.9单元阵列函数总结16
7.3结构数组16
7.3.2增加域到结构17
7.3.3删除结构中的域18
7.3.4结构数组中数组的应用18
7.3.5函数getfield和函数setfield20
7.3.6对结构数组应用size函数20
7.3.8struct函数总结21
测试7.121
7.4总结22
7.4.1好的编程习惯总结22
7.4.2MATLAB函数命令总结22
7.5练习23
7.123
7.223
7.323
7.423
7.524
7.624
第七章稀疏矩阵单元阵列结构
在本章中我们要学习三种数据类型:
稀疏矩阵,单元阵列和结构。
稀疏矩阵是矩阵的一种特殊形式,在这个矩阵中只对非零元素分配内存。
单元阵列也是一种矩阵,它的每一个元素可以是MATLAB任何一种数据类型。
它们广泛应用于MATLAB用户图象界面(GUI)函数。
最后,结构提供了一种在单个变量中存储了不同类型的数据的方法,在这个变量中的每一个数据项目都有一个独立的名字。
7.1稀疏矩阵
我们在第二章中已经学过了普通的MATLAB数组。
当一个普通的数组被声明后,MATLAB将会为每一个数组元素分配内存。
例如函数a=eye(10)要创建了100个元素,按10×10的结构分配,对角线上的元素均为1,其余的元素为0。
注意这些数组其中的90个元素为0。
这个包含有一百个元素的矩阵,只有10个元素包含非零值。
这是稀疏矩阵或稀疏数组的一个例子。
稀疏矩阵是指一个很大的矩阵,且大多数的元素为0。
>>a=2*eye(10)
a=
2000000000
0200000000
0020000000
0002000000
0000200000
0000020000
0000002000
0000000200
0000000020
0000000002
现在假如我们要创建一个10×10的矩阵,定义如下
b=
1000000000
0200000000
0020000000
0001000000
0000500000
0000010000
0000001000
0000000100
0000000010
0000000001
若a,b两矩阵相乘得到的结果为
>>c=a*b
c=
2000000000
0400000000
0040000000
0002000000
00001000000
0000020000
0000002000
0000000200
0000000020
0000000002
这两个稀疏矩阵相乘需要1900次相加和相乘,但是在大多数时侯相加和相乘的结果为0,所以我们做了许多的无用功。
这个问题会随着矩阵大小的增大而变得非常的严重。
例如,假设我们要产生两个200×200的稀疏矩阵,如下所示
a=5*eye(200);
b=3*eye(200);
每一个矩阵有20000个元素,其中19800个元素是0。
进一步说,对这两个矩阵相乘需要7980000次加法和乘法。
我们可以看出对大规模稀疏矩阵进行存储和运算(其中大部分为0)是对内存空间和cpu资源的极大浪费。
不巧的是,在现实中的许多问题都需要稀疏矩阵,我们需要一些有效的方示来解决这个问题。
大规模供电系统是现实世界中涉及到稀疏矩阵一个极好的例子。
大规模供电系统可以包括上千条或更多的母线,用来产生,传输,分配电能到子电站。
如果我们想知道这个系统的电压,电流和功率,我们必须首先知道每一条母线的电压。
如果这个系统含有一千个母线,这就要用到含有1000个未知数的联立方程组,包括一个方程,也就是说我们要创建含有1000000个元素的矩阵。
解出这个矩阵,需要上百万次的浮点运算。
但是,在这个系统中,一条母线平均只它的三条母线相连,而在这个矩阵中每一行其他的996个元素将为0,所以在这个矩阵的加法和乘法运算中将会产生0。
如果在求解的过程中这些0可以忽略,那么这个电力系统的电压和电流计算将变得简单而高效。
7.1.1sparse数据类型
在MATLAB中有一个专门的数据类型,用来对稀疏进行运算。
sparse数据类型不同于doulbe数据,它在内存中只存储非零元素。
实际上,sparse数据类型只存储每一个非零元素的三个值:
元素值,元素的行号和列号。
尽管非零元素这三个值必须存储在这内存,但相对于存储稀疏矩阵的所有元素来说要简单高效得多。
我们用10×10的方阵来说明稀疏矩阵的应用。
>>a=eye(10)
a=
1000000000
0100000000
0010000000
0001000000
0000100000
0000010000
0000001000
0000000100
0000000010
0000000001
如果这个矩阵被转化为稀疏矩阵,它的结果是
>>as=sparse(a)
as=
(1,1)1
(2,2)1
(3,3)1
(4,4)1
(5,5)1
(6,6)1
(7,7)1
(8,8)1
(9,9)1
(10,10)1
注意在稀疏矩阵存储的是行列地址和这一点所对应的非零数据值。
只要一个矩阵的大部分数都是0,这种方法用来存储数据就是高效的,但是如果非零元素很多的话,那么用占用更多的空间,因为稀疏矩阵需要存储蓄地址。
函数issparse通常用作检测一个矩阵是否为稀疏矩阵。
如果这个矩阵是稀疏的,那么这个函数将会返回1。
稀疏矩阵的优点可以通过下面的描述体现出来,考虑一个1000×1000的矩阵平均每一行只有4个非零元素。
如果这个矩阵以全矩阵的形式储存,那么它要战胜8000000个字节。
从另一方面说,如果它转化为一个稀疏矩阵,那么内存的使用将会迅速下降。
7.1.1.1产生稀疏矩阵
MATLAB可以通过sparse函数把一个全矩阵转化为一个稀疏矩阵,也可以用MATLAB函数speye,sprand和sprandn直接产生稀疏矩阵,它们对应的全矩阵为eye,rand,和randn。
例如,表达式a=speye(4)将产生一个4×4的稀疏矩阵。
>>a=speye(4)
a=
(1,1)1
(2,2)1
(3,3)1
(4,4)1
表达式b=full(a)把稀疏矩阵转化相应的全矩阵。
>>b=full(a)
b=
1000
0100
0010
0001
7.1.1.2稀疏矩阵的运算
如果一个矩阵是稀疏的,那么单个元素可以通过简单的赋值语句添加或删除,例如下面的语句产生一个4×4的稀疏矩阵,然后把其他的非零元素加入其中。
>>a=speye(4)
a=
(1,1)1
(2,2)1
(3,3)1
(4,4)1
>>a(2,1)=-2
a=
(1,1)1
(2,1)-2
(2,2)1
(3,3)1
(4,4)1
MATLAB允许全矩阵与稀疏的混合运算。
它们产生的结果可以是全矩阵也可以是稀疏矩阵,这取决于那种结果更高效。
更重要的是,任何的适用全矩阵算法同样地也适合稀疏矩阵。
表7.1列出的是一些普通的稀疏矩阵。
表7.1普通的MATLAB稀疏矩阵函数
类别
函数
描述
创建一个稀疏矩阵
speye
创建一个单位稀疏矩阵
sprand
创建一个稀疏矩阵,元素是符合平均分布的随机数
sprandn
创建一个稀疏矩阵,元素是普通的随机数
全矩阵和稀疏矩阵的转换函数
sparse
把一个全矩阵转化为一个稀疏矩阵
full
把一个稀疏矩阵转化为全矩阵
find
找出矩阵中非零元素和它对应的上下标
对稀疏矩阵进行操作的函数
nnz
非零元素的个数
nonzeros
返回一个向量,其中的元素为矩阵中非零元素
spones
用1代替矩阵中的非零元素
spalloc
一个稀疏矩阵所占的内存空间
issparse
如果是稀疏矩阵就返回1
spfun
给矩阵中的非零元素提供函数
spy
用图象显示稀疏矩阵
例7.1
用稀疏矩阵解决联立方程组
为了解说明稀疏矩阵在MATLAB中应用,我们将用全矩阵和稀疏矩阵来解决下面的联立方程组。
1.0x1+0.0x2+1.0x3+0.0x4+0.0x5+2.0x6+0.0x7-1.0x8=3.0
0.0x1+1.0x2+0.0x3+0.4x4+0.0x5+0.0x6+0.0x7+0.0x8=2.0
0.5x1+0.0x2+2.0x3+0.0x4+0.0x5+0.0x6-1.0x7+0.0x8=-1.5
0.0x1+0.0x2+0.0x3+2.0x4+0.0x5+1.0x6+0.0x7+0.0x8=1.0
0.0x1+0.0x2+1.0x3+1.0x4+1.0x5+0.0x6+0.0x7+0.0x8=-2.0
0.0x1+0.0x2+0.0x3+1.0x4+0.0x5+1.0x6+0.0x7+0.0x8=1.0
0.5x1+0.0x2+0.0x3+0.0x4+0.0x5+0.0x6+1.0x7+0.0x8=1.0
0.0x1+1.0x2+0.0x3+0.0x4+0.0x5+0.0x6+0.0x7+1.0x8=1.0
答案
为了解决这一问题,我们将创建一个方程系数的全矩阵,并用sparse函数把他转化为稀疏矩阵。
我们用两种方法解这个方程组,比较它们的结果和所需的内存。
代码如下:
%Scriptfile:
simul.m
%
%Purpose:
%Thisprogramsolvesasystemof8linearequationsin8
%unknowns(a*x=b),usingbothfullandsparsematrices.
%
%Recordofrevisions:
%DateProgrammerDescriptionofchange
%===========================
%10/14/98S.J.ChapmanOriginalcode
%
%Definevariables:
%a--Coefficientsofx(fullmatrix)
%as--Coefficientsofx(sparsematrix)
%b--Constantcoefficients(fullmatrix)
%bs--Constantcoefficients(sparsematrix)
%x--Solution(fullmatrix)
%xs--Solution(sparsematrix)
%Definecoefficientsoftheequationa*x=bfor
%thefullmatrixsolution.
a=[
1.00.01.00.00.02.00.0-1.0;...
0.01.00.00.40.00.00.00.0;...
0.50.02.00.00.00.0-1.00.0;...
0.00.00.02.00.01.00.00.0;...
0.00.01.01.01.00.00.00.0;...
0.00.00.01.00.01.00.00.0;...
0.50.00.00.00.00.01.00.0;...
0.01.00.00.00.00.00.01.0
];
b=[3.02.0-1.51.0-2.01.01.01.0]';
%Definecoefficientsoftheequationa*x=bfor
%thesparsematrixsolution.
as=sparse(a);
bs=sparse(b);
%Solvethesystembothways
disp('Fullmatrixsolution:
');
x=a\b
disp('Sparsematrixsolution:
');
xs=as\bs
%Showworkspace
disp('Workspacecontentsafterthesolutions:
')
whos
运行这个程序,结果如下
>>simul
Fullmatrixsolution:
x=
0.5000
2.0000
-0.5000
-0.0000
-1.5000
1.0000
0.7500
-1.0000
Sparsematrixsolution:
xs=
(1,1)0.5000
(2,1)2.0000
(3,1)-0.5000
(5,1)-1.5000
(6,1)1.0000
(7,1)0.7500
(8,1)-1.0000
Workspacecontentsafterthesolutions:
NameSizeBytesClass
a8x8512doublearray
as8x8276doublearray(sparse)
b8x164doublearray
bs8x1104doublearray(sparse)
x8x164doublearray
xs8x192doublearray(sparse)
Grandtotalis115elementsusing1112bytes
两种算法得到了相同的答案。
注意用稀疏矩阵产生的结果不包含x4,因为它的值为0。
注意b的稀疏形式占的内存空间比全矩阵形式还要大。
这种情况是因为稀疏矩阵除了元素值之外必须存储它的行号和列号,所以当一个矩阵的大部分元素都是非零元素,用稀疏矩阵将降低运算效率。
7.2单元阵列(cellarray)
单元阵列是MATLAB中特殊一种数组,它的元素被称为单元(cells),它可以存储其它类型的MATLAB数组。
例如,一个单元阵列的一个单元可能包含一个实数数组或字符型数组,还可能是复数组(图7.1所示)。
在一个编程项目中,一个单元阵列的每一个元素都是一个指针,指向其他的数据结构,而这些数据结构可以是不同的数据类型。
单元阵列为选择问题信息提供极好的方示,因为所有信息都聚集在一起,并可以通边一单个名字访问。
单元阵列用大括号{}替代小括号来选择和显示单元的内容。
这个不同是由于单元的内容用数据结构代替了内容。
假设一单元阵列如图7.2所示。
元素a(1,1)是数据结构3×3的数字数组。
a(1,1)的含义为显示这个单元的内容,它是一个数据结构。
图7.1一个单元阵列的一个单元可能包含一个实数数组或字符型数组,还可能是复数组
图7.2单元阵列中的每一个元素都是指向其他数据结构的指针,指向的数据结构可能都不相同
>>a(1,1)
ans=
[3x3double]
相对地,a{1,1}的含义为显示这个数据结构的内容。
>>a{1,1}
ans=
13-7
206
051
总起来说,标识a{1,1}反映的是数据结构a(1,1)内容,而标识a(1,1)是一个数据结构。
好的编程习惯
当你访问一单元阵列时,不要把()与{}混淆。
它们完全不同的运算。
7.2.1创建单元阵列
创建单元阵列有两种方法
●用赋值语句
●用函数cell创建
最简单的创建单元阵列的方法是直接把数据结构赋值于独立的单元,一次赋一个单元。
但用cell函数创建将会更加地高效,所以我们用cell创建大的单元数组。
7.2.1.1用赋值语句创建单元阵列
你可以用赋值语句把值赋于单元阵列的一个单元,一次赋一个单元。
这里有两种赋值的方法,即内容索引(contentindexing)和单元索引(cellindexing)。
内容索引要用到大括号{},还有它们的下标,以及单元的内容。
例如下面的语句创建了一个2×2的单元阵列,如图7.2所示。
a{1,1}=[13-7;206;051];
a{1,2}='Thisisatextstring.';
a{2,1}=[3+4*i-5;-10*i3-4*i];
a{2,2}=[];
索引的这种类型定义了包含在一个单元中的数据结构的内容。
单元索引把存储于单元中的数据用大括号括起来,单元的下标用普通下标标记法。
例如下面的语句将创建一个2×2的单元阵列,如图7.2所示。
a(1,1)={[13-7;206;051]};
a(1,2)={'Thisisatextstring.'};
a(2,1)={[3+4*i-5;-10*i3-4*i]};
a(2,2)={[]};
索引的这种类型创建了包含有指定值的一个数据结构,并把这个数据结构赋于一个单元。
这两种形式是完全等价的,你可以在你的程序任选其一。
常见编程错误
不要创建一个与已存在的数字数组重名的元阵列。
如果得名了,MATLAB会认为你把单元阵列的内容赋值给一个普通的数组,这将会产生一个错误信息。
在创建单元阵列之前,确保同名的数字数字数组已经被删除。
7.2.1.2用cell函数创建单元阵列
函数cell允许用户创建空单元阵列,并指定阵列的大小。
例如,下面的语句创建一个2×2的空单元阵列。
a=cell(2,2)
一旦单元阵列被创立,你就可以用赋值语句对单元阵列进行赋值。
7.2.2单元创建者——大括号({})的应用
如果在单个大括号中列出所有单元的内容,那么就定义了许多的单元,在一行中的独立单元用逗号分开,行与行之间用分号隔开。
例如下面的语句创建一个2×3单元阵列。
b={[12],17,[2;4];3-4*i,'Hello',eye(3)}
7.2.3查看单元阵列的内容
MATLAB可以把单元阵列每一个元素的数据结构缩合在一行中显示出来。
如果全部的数据结构没有被显示出来,那么显示就是一个总结。
例如,单元阵列a和b显示如下
>>a
a=
[3x3double][1x22char]
[2x2double][]
>>b
b=
[1x2double][17][2x1double]
[3.0000-4.0000i]'Hello'[3x3double]
注意MATLAB显示的只是数据结构,包括中括号和省略号,而不包含数据结构的内容。
如果你想要知道看到单元阵列的所有内容,要用到celldisp函数。
这个函数显示的是每一个单元中的数据结构的内容。
>>celldisp(a)
a{1,1}=
13-7
206
051
a{2,1}=
3.0000+4.0000i-5.0000
0-10.0000i3.0000-4.0000i
a{1,2}=
Thisisatextstring.
a{2,2}=
[]
如果要用高质量的图象显示数据结构的内容,要用到函数cellplot。
例如,函数cellplot(b)产生了一个图象,如图7.3所示。
图7.3用函数cellplot显示单元阵列b数据结构的内容
7.2.4对单元阵列进行扩展
一个值赋值于一个单元阵列中的元素,如果这个元素现在不存在,那么这个元素就会被自动的建立,其他所需的元素也会被自动建立。
例如,假设定义了一个2×2单元阵列,如图7.1所示。
如果我们执行下面的语句
a{3,3}=5
单元阵列将会自动扩展为3×3单元阵列,如图7.4所示。
图7.4把一个值赋值于a(3,3)产生的结果。
注意其他的空元素也是自动创建的。
7.2.5删除阵列中的元素
如果要删除阵列中的所有元素,我们要用clear命令。
如果要删除单元阵列中的部分元素,我们把空值赋值于这一部分元素。
例如,假设a的定义如下
>>a
a=
[3x3double][1x22char][]
[2x2double][][]
[][][5]
我们可以用下面的语句删除第三行
>>a(3,:
)=[]
a=
[3x3double][1x22char][]
[2x2double][][]
7.2.6单元阵列数据的应用
在一个单元阵列中,数据结构中数据可以随时用内容索引或单元索引调用。
例如假设单元阵列c的定义如下
c={[12;34],'dogs';'cats',i}
存储于c(1,1)的内容可由下面的语句调用
>>c{1,1}
ans=
12
34
同样c(2,1)中的元素可由下面的元素调用
>>c{2,1}
ans=
cats
一个单元内容的子集可由两套下标得到。
例如,假设我们要得到单元c(1,1)中的元素(1,2)。
为了达到此目的,我们可以用表达式c{1,1}(1,2),它代表单元c(1,1)中的元素(1,2)。
>>c{1,1}(1,2)
ans=
2
7.2.7字符串单元阵列
在一个单元阵列中存储一批字符串与在标准的字符数组中
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- MATLAB 第七