数据结构 2014年3月.

Slides:



Advertisements
Similar presentations
第五章 二次型. 第五章 二次型 知识点1---二次型及其矩阵表示 二次型的基本概念 1. 线性变换与合同矩阵 2.
Advertisements

第3节 二次型与二次型的化简 一、二次型的定义 二、二次型的化简(矩阵的合同) 下页.
§1 二阶与三阶行列式 ★二元线性方程组与二阶行列式 ★三阶行列式
一、二阶行列式的引入 用消元法解二元线性方程组. 一、二阶行列式的引入 用消元法解二元线性方程组.
第五章 数组和广义表.
第一章 行列式 第五节 Cramer定理 设含有n 个未知量的n个方程构成的线性方程组为 (Ⅰ) 由未知数的系数组成的n阶行列式
第二章 矩阵(matrix) 第8次课.
第五章 数组和广义表 £5.1 数组 £5.2 矩阵的压缩存储 £5.3 广义表 £5.1.1 数组的定义 £5.2.1 特殊矩阵
第五章 数组和 广义表 数组 稀疏矩阵 广义表.
第五章 数组和广义表.
第 4章 串和数组(二) 本讲主要内容: 数组的定义及其顺序表示和实现。 矩阵的压缩存储。 广义表的定义。
辅导课程六.
串和数组.
数据结构 第5章 数组与广义表.
元素替换法 ——行列式按行(列)展开(推论)
Zhao4zhong1 (赵中) C语言指针与汇编语言地址.
Zhao4zhong1 (赵中) C语言指针与汇编语言地址.
第2章 线性表 2.1 线性表的类型定义 2.2 线性表的顺序表示和实现 2.3 线性表的链式表示和实现 2.4 一元多项式的表示.
§2 求导法则 2.1 求导数的四则运算法则 下面分三部分加以证明, 并同时给出相应的推论和例题 .
第4章 串、数组和广义表 4.1 串 4.2 数组 4.3 广义表.
第一章 函数 函数 — 研究对象—第一章 分析基础 极限 — 研究方法—第二章 连续 — 研究桥梁—第二章.
第4章 串和数组 本章主要介绍下列内容: 串的定义、存储结构和基本运算 数组的定义、基本运算和存储结构 特殊矩阵的压缩存储.
顺序表的插入.
第五章 数组 5.1 数组的定义 5.2 数组的表示和实现* 5.3 数组的压缩.
第一章 函数与极限.
第五章 串和数组 5.1 串的定义和操作 5.2 串的表示和实现 5.3 字符串应用 5.4 字符串匹配算法 5.5 数组
严蔚敏、吴伟民编著 清华大学出版社 学习网站:中国网页设计
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
第五章 数组和广义表.
第6章 数组与广义表 6.1 数组的定义及其基本操作 6.2 数组的顺序存储结构 6.3 矩阵的压缩存储 6.4 广义表的概念
Chapter 05 Sparse Matrix & Lists 第五章 稀疏数组和广义表
实数与向量的积.
顺序表的删除.
线性代数 第二章 矩阵 §1 矩阵的定义 定义:m×n个数排成的数表 3) 零矩阵: 4) n阶方阵:An=[aij]n×n
线 性 代 数 厦门大学线性代数教学组 2019年4月24日6时8分 / 45.
第五章 串和数组 5.1 串的定义和操作 5.2 串的表示和实现 5.3 字符串应用 5.4 字符串匹配算法 5.5 数组
第5章 数组和广义表 本章主题:多维数组、特殊矩阵和广义表 教学目的:掌握数组和广义表的定义、运算及存储结构 教学难点:矩阵的压缩存储
第四章 串和数组 4.1 串的定义* 4.2 串的表示和实现* 4.3 数组 4.4 数组的压缩.
复习.
单链表的基本概念.
顺序查找.
第 四 讲 线性表(二).
正切函数的图象和性质 周期函数定义: 一般地,对于函数 (x),如果存在一个非零常数T,使得当x取定义域内的每一个值时,都有
第16讲 相似矩阵与方阵的对角化 主要内容: 1.相似矩阵 2. 方阵的对角化.
§3 向量组的秩.
§8.3 不变因子 一、行列式因子 二、不变因子.
§6.7 子空间的直和 一、直和的定义 二、直和的判定 三、多个子空间的直和.
1.2 子集、补集、全集习题课.
等差与等比综合(3).
本 章 说 明 5.1 数组的定义 5.2 数组的顺序表示和实现 5.3 矩阵的压缩存储 5.4 广义表的定义 5.5 广义表的存贮结构
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
线性代数 第十一讲 分块矩阵.
2.2矩阵的代数运算.
第15讲 特征值与特征向量的性质 主要内容:特征值与特征向量的性质.
线 性 代 数 厦门大学线性代数教学组 2019年5月12日4时19分 / 45.
第五章 串和数组 5.1 串的定义和操作 5.2 串的表示和实现 5.3 正文匹配模式 5.4 正文编辑 5.5 数组 5.6 数组的压缩.
Ch.5 数组和广义表 黄刘生 中国科学技术大学计算机系 国家高性能计算中心(合肥)
《离散结构》 二元运算性质的判断 西安工程大学计算机科学学院 王爱丽.
§2 方阵的特征值与特征向量.
实验目的:掌握数据的顺序存储结构及它们在计算机中的操作。 实验内容:
基于列存储的RDF数据管理 朱敏
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
数据结构概论 第5章 数组和广义表 董黎刚 浙江工商大学信电学院.
定义5 把矩阵 A 的行换成同序数的列得到的矩阵,
第四节 向量的乘积 一、两向量的数量积 二、两向量的向量积.
4.2 图的存储结构(cont.) v1 v2 v3 v4 v5 vertex= v1 v2 v3 v4 v5 v
第三节 数量积 向量积 混合积 一、向量的数量积 二、向量的向量积 三、向量的混合积 四、小结 思考题.
§4.5 最大公因式的矩阵求法( Ⅱ ).
第5章 其他线性数据结构.
第二章 线性表 东南大学计算机学院 方效林 本课件借鉴了清华大学殷人昆老师 和哈尔滨工业大学张岩老师的课件.
Presentation transcript:

数据结构 2014年3月

第五章 数组与广义表 基本内容: 多维数组和广义表是对线性表的扩展:线性表中的数据元素本身又是一个多层次的线性表。 5.1 数组的定义 第五章 数组与广义表    多维数组和广义表是对线性表的扩展:线性表中的数据元素本身又是一个多层次的线性表。 基本内容: 5.1 数组的定义 5.2 数组的顺序表示和实现 5.3 矩阵的压缩存储 5.4 广义表的定义 5.5 广义表的存储结构

5.1 数组的定义 ADT Array{ 数据对象:ji=0,…,bi-1,i=1,2,…,n, 5.1 数组的定义 ADT Array{ 数据对象:ji=0,…,bi-1,i=1,2,…,n, D={aj1j2…jn| n(>0)称为数组的维数,bi是数组第i维的长度,ji是数组元素的第i维下标,aj1j2…jn∈ElemSet} 数据关系:R={R1,R2,…,Rn} Ri={<aj1…ji…jn,aj1…ji+1…jn>| 0≤jk≤bk-1, 1≤k≤n 且k≠i,0≤ji≤bi-2, aj1…ji…jn,aj1…ji+1…jn∈D,i=2,…n}

一、二维数组的线性表理解: Amn= typedef elemtype array2[m][n]; 等价于: 可以看成是由个行向量组成的向量,也可以看成是个列向量组成的向量。在C语言中,一个二维数组类型可以定义为其分量类型为一维数组类型的一维数组类型,也就是说, typedef elemtype array2[m][n]; 等价于: typedef elemtype array1[n]; typedef array1 array2[m]; a0,0 a1,2 … a1,n a2,1 a2,2 … a2,n … … … … am,1 am,2 … am,n Amn=

二、二维数组的基本操作: 对数组一般不做插入和删除操作,也就是说,数组一旦建立,结构中的元素个数和元素间的关系就不再发生变化。因此,一般都是采用顺序存储的方法来表示数组。

5.2 数组的顺序表示和实现 (1)多维数组用一维的存储单元存放需约定次序。PASCAL和C语言是以行序为主序,FORTRAN以列序为主序。 5.2 数组的顺序表示和实现 (1)多维数组用一维的存储单元存放需约定次序。PASCAL和C语言是以行序为主序,FORTRAN以列序为主序。 (2)给定维数和各维长度,数组的存储空间确定。 (3)二维数组中任一元素aij的存储地址: Loc(i,j)=Loc(0,0)+(b2*i+j)*L (4)n维数组:教材p93 Loc(j1,j2,…,jn)=Loc(0,0,…,0)+ ∑ciji 其中 cn=L, ci-1=bi*ci, 1<i≤n

5.3 矩阵的压缩存储 矩阵一般可用二维数组实现,特殊矩阵采用压缩存储。 压缩存储:为多个值相同的元只分配一个存储空间, 对零元不分配空间。 5.3 矩阵的压缩存储 矩阵一般可用二维数组实现,特殊矩阵采用压缩存储。 压缩存储:为多个值相同的元只分配一个存储空间, 对零元不分配空间。 特殊矩阵:值相同的元素或者零元素在矩阵中的分布有 一定规律 稀疏矩阵:非零元较零元少,且分布没有一定规律的矩 阵

一、特殊矩阵的存储 1、对称矩阵: 在一个n阶方阵A中,若元素满足下述性质: aij=aji0≦i,j≦n-1则称A为对称矩阵。如图5.1便是一个5阶对称矩阵。 5 1 3 7 a00 5 0 8 0 0 a10 a 11 1 8 9 2 6 a20 a21 a23 3 0 2 5 1 ……………….. 7 0 6 1 3 an-1 0 a n-1 1 a n-1 2 …a n-1 n-1 压缩存储方法:对称矩阵中的元素关于主对角线对称,故只要存储矩阵中上三角或下三角中的元素,让每两个对称的元素共享一个存储空间。

下三角矩阵中,第i行恰有i+1个元素,元素总数为:(i+1)=n(n+1)/2,将这些元素存放在一个向量sa[0 下三角矩阵中,第i行恰有i+1个元素,元素总数为:(i+1)=n(n+1)/2,将这些元素存放在一个向量sa[0..n(n+1)/2-1]中。必须在aij和sa[k]之间找一个对应关系。 若i≧j,则ai j在下三角形中。 ai j之前的i行(从第0行到第i-1行)一共有1+2+…+i=i(i+1)/2个元素,在第i行上, ai j之前恰有j个元素(即ai0,ai1,ai2,…,aij-1),因此有: k=i*(i+1)/2+j 0≦k<n(n+1)/2 若i<j,则aij是在上三角矩阵中。因为aij=aji,所以只要交换上述对应关系式中的i和j即可得到: k=j*(j+1)/2+i 0≦ k<n(n+1)/2

a00 a10 a11 a20 …… an-1 0 an-1,n-1 k=0 1 2 3 n(n-1)/2 n(n-1)/2-1 例如a21和a12均存储在 sa[4]中,这是因为 k=I*(I+1)/2+J=2*(2+1)/2+1=4 2、三角矩阵 以主对角线划分,三角矩阵有上三角和下三角两种。上三角矩阵如图所示,它的下三角(不包括主对角线)中的元素均为常数。下三角矩阵正好相反,它的主对角线上方均为常数,如图所示。在大多数情况下,三角矩阵常数为零。

a00 a01 … a 0 n-1 a00 c … c c a11 … a 1 n-1 a10 a11 … c ………………….. …………….. c c … a n-1 n-1 an-1 0 an-1 1 … an-1 n-1 (a)上三角矩阵 (b)下三角矩阵 以主对角线划分,三角矩阵有上三角和下三角两种。上三角矩阵如图所示,它的下三角(不包括主对角线)中的元素均为常数。下三角矩阵正好相反,它的主对角线上方均为常数,如图所示。在大多数情况下,三角矩阵常数为零。

三角矩阵中的重复元素c可共享一个存储空间,其余的元素正好有n(n+1)/2个,因此,三角矩阵可压缩存储到向量sa[0 三角矩阵中的重复元素c可共享一个存储空间,其余的元素正好有n(n+1)/2个,因此,三角矩阵可压缩存储到向量sa[0..n(n+1)/2]中,其中c存放在向量的最后一个分量中。 上三角矩阵中,主对角线之上的第p行(0≦p<n)恰有n-p个元素,按行优先顺序存放上三角矩阵中的元素aij时,aij之前的i行一共有(n-p)=i(2n-i+1)/2 个元素,在第i行上,aij前恰好有j-i个元素:aij,aij+1,…aij-1。因此,sa[k]和aij的对应关系是: i(2n-i+1)/2+j-i 当i≦j n(n+1)/2 当i>j 下三角矩阵的存储和对称矩阵类似,sa[k]和aij对应关系是: i(i+1)/2+j i≧j n(n+1)/2 i>j

3、对角矩阵 对角矩阵中,所有的非零元素集中在以主对角线为了中心的带状区域中,即除了主对角线和主对角线相邻两侧的若干条对角线上的元素之外,其余元素皆为零。下图给出了一个三对角矩阵, a00 a01 a10 a11 a12 a21 a22 a23 …. ….. …. an-2 n-3 an-2 n-2 an-2 n-1 an-1 n-2 an-1 n-1

上例中,a34对应着sa[10]。k=2*i+j=2*3+4=10 a21对应着sa[5] k=2*2+1=5 在一个nn的三对角矩阵中,只有n+n-1+n-1个非零元素,故只需3n-2个存储单元即可,零元已不占用存储单元。故可将nn三对角矩阵A压缩存放到只有3n-2个存储单元的s向量中,假设仍按行优先顺序存放。 a00 a01 a10 a11 a12 a21 … a n-1 n-2 a n-1 n-1 K=0 1 2 3 4 5 … … 3n-2 3n-1 数组sa中的元素sa[k]与三对角带状矩阵中的元素aij存在一一对应关系,在aij之前有i行,共有3*i-1个非零元素,在第i行,有j-i+1个非零元素,这样,非零元素aij的地址为:LOC(i,j)=LOC(0,0)+[3*i-1+(j-i+1)]*d =LOC(0,0)+(2i+j)*d 上例中,a34对应着sa[10]。k=2*i+j=2*3+4=10 a21对应着sa[5] k=2*2+1=5 由此,我们称sa[0..3*n-2]是阶三对角带状矩阵A的压缩存储表示。

二、稀疏矩阵的存储 1.三元组表 在压缩存放稀疏矩阵的非零元同时,若还存放此非零元所在的行号和列号,则称为三元组表法,即称稀疏矩阵可用三元组表进行压缩存储,但它是一种顺序存储(按行优先顺序存放)。一个非零元有行号、列号、值,为一个三元组,整个稀疏矩阵中非零元的三元组合起来称为三元组表。

此时,数据类型可描述如下: #define MAXSIZE 12500 /*定义非零元的最大数目*/ Typedef struct { /*定义三元组*/ int i , j; /*非零元行、列号*/ Elemtype e; /*非零元值*/ }Triple; Typedef struct { /*定义稀疏矩阵*/ int mu,nu,tu; /*稀疏矩阵行、列数、非零元个数*/ Triple data[MAXSIZE+1]; /*三元组表*/ }TSMatrix;

M= T= TSMatrix M; M.mu=7 m.nu=6 m.tu=8 m.data[]= 3 1 -3 6 1 15 2 1 12 0 12 9 0 0 0 0 0 0 -3 0 0 15 0 0 0 0 0 0 0 12 0 0 0 18 0 -3 0 0 0 0 14 0 9 0 0 24 0 0 0 0 24 0 0 0 0 0 0 0 0 0 –7 0 18 0 0 0 0 0 0 0 14 0 0 0 15 0 0 –7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 M= T= 图5.4 稀疏矩阵M和转置矩阵T TSMatrix M; M.mu=7 m.nu=6 m.tu=8 m.data[]= i j v 3 1 -3 6 1 15 2 1 12 2 5 18 3 1 9 3 4 24 4 6 -7 6 3 14 1 2 3 4 5 6 7 TSMatrix M; M.mu=6 m.nu=7 m.tu=8 m.data[]= i j v 1 2 12 1 3 9 3 1 -3 3 6 14 4 3 24 5 2 18 6 1 15 6 4 -7 1 2 3 4 5 6 7 转置

2、举例:如何求矩阵的转置矩阵? (1)普通转置:基本思想是:对A中的每一列col(0≦col≦n-1),通过从头至尾扫描三元表a.data,找出所有列号等于col的那些三元组,将它们的行号和列号互换后依次放入b.data中,即可得到B的按行优先的压缩存储表示。 Status TransposeSMatrix(TSMatrix M, TSMatrix &T) { // 采用三元组顺序表存储表示,求稀疏矩阵M的转置矩阵T int p, q, col; T.mu = M.nu; T.nu = M.mu; T.tu = M.tu; if (T.tu) { q = 1; for (col=1; col<=M.nu; ++col) for (p=1; p<=M.tu; ++p) if (M.data[p].j == col) { T.data[q].i=M.data[p].j;T.data[q].j =M.data[p].i; T.data[q].e =M.data[p].e; ++q; } } return OK;

(2)快速转置 基本思想: 先求得矩阵M中的每一列中非零元素的个数,预先确定出矩阵M中的每一列的第一个非零元素在数组B中应在的位置,(其中第1列第1个非零元在数组B中也是第1个位置,矩阵M中每一列的第一个非零元素在数组B中的位置等于前一列第一个非零元素的位置加上前列非零元素的个数。),这样,顺序扫描一遍数组A就可以把所有元素放到数组B中恰当的位置。为此,需要设置两个一维数组num[0..n]和cpot[0..n],num[0..n]:统计M中每列非零元素的个数,num[col]的值可以由A的第二列求得。cpot[0..n]:由递推关系得出M中的每列第一个非零元素在B中的位置。

算法通过cpot数组建立位置对应关系: cpot[1]=1 cpot[col]=cpot[col-1]+num[col-1] 2<=cpl<=a.n 例如:图中的矩阵M和相应的三元组A可以求得num[col]和 cpot[col]的值如下: col 1 2 3 4 5 6 7 num[col] 2 2 2 1 0 1 0 cpot[col] 1 3 5 7 8 8 9

Status FastTransposeSMatrix(TSMatrix M, TSMatrix &T) {// 采用三元组顺序表存储表示,求稀疏矩阵M的转置矩阵T int col, t, p, q; int num[20], cpot[20]; T.mu = M.nu; T.nu = M.mu; T.tu = M.tu; if (T.tu) { for (col=1; col<=M.nu; ++col) num[col] = 0; for (t=1; t<=M.tu; ++t) // 求 M 中每一列所含非零元的个数 ++num[M.data[t].j]; cpot[1] = 1; // 求 M 中每一列的第一个非零元在 b.data 中的序号 for (col=2; col<=M.nu; ++col) cpot[col] = cpot[col-1]+num[col-1]; for (p=1; p<=M.tu; ++p) { col = M.data[p].j; q = cpot[col]; T.data[q].i =M.data[p].j; T.data[q].j =M.data[p].i; T.data[q].e =M.data[p].e; ++cpot[col]; } // for } // if return OK; } // FastTransposeSMatrix

3、十字链表---数组的链式存储 (1)当矩阵中非零元素的个数和位置经过运算后变化较大时,就不宜采用顺序存储结构,而应采用链式存储结构来表示三元组。 (2)稀疏矩阵的链接表示采用十字链表:行链表与列链表十字交叉。 (3)行链表与列链表都是带表头结点的循环链表。用表头结点表征是第几行,第几列。

right——指向同一行中下一个非零元素的指针(向右域) 元素结点 right——指向同一行中下一个非零元素的指针(向右域) down——指向同一列中下一个非零元素的指针(向下域) 表头结点 行表头结点 列表头结点 next用于表示头结点的链接 i j val down right

1 3 4 5 2 -1 ^ 3 0 0 5 0 -1 0 0 2 0 0 0

5.4 广义表的定义 一、定义 1、广义表是n(n>=0)个元素a1,a2,a3,…,an的有限序列,其中ai或者是原子项,或者是一个广义表。通常记作LS=(a1,a2,a3,…,an)。LS是广义表的名字,n为它的长度。若ai是广义表,则称它为LS的子表。 例如: A = ( ) F = (d, (e)) D = ((a,(b,c)), F) C = (A, D, F) B = (a, B) = (a, (a, (a,  , ) ) )

(1)表头 Head(LS) =1 第1个元素本身 二、广义表的运算 (1)表头 Head(LS) =1 第1个元素本身 (2)表尾 Tail(LS) = ( 2, …, n) 除第1个元素外其余元素所构成的广义表。 例如: D = ( E, F ) = ((a, (b, c)),F ) Head( D ) = E Tail( D ) = ( F ) Head( E ) = a Tail( E ) = ( ( b, c) ) Head( (( b, c)) ) = ( b, c) Tail( (( b, c)) ) = ( ) Head( ( b, c) ) = b Tail( ( b, c) ) = ( c ) Head( ( c ) ) = c Tail( ( c ) ) = ( )

三、广义表的存储结构 表结点: tag=1 hp tp 原子结点: tag=0 data 表头、表尾分析法:空表 ls = NIL 指向表头的指针 指向表尾的指针 非空表 ls

L=(a,(x,y),((x))) L 1 1 1  1   1  0 a 1  0 x

作业: 5-1 按行优先存储方式,写出二维数组A[10][8]在内存中的地址计算公式(假设每个数组元素占用L个字节的内存单元,a[0][0]的内存地址为Loc(a[0][0]))。 5-2 按列优先存储方式,写出二维数组A[10][8]在内存中的地址计算公式(假设每个数组元素占用L个字节的内存单元,a[0][0]的内存地址为Loc(a[0][0]))。 5-3 设有上三角矩阵Ann,它的下三角部分全为0,将其上三角元素按行优先存储方式存入数组B[m]中(m足够大),使得B[k]=a[i][j],且有k=f1(i)+f2(j)+c。试推出函数f1、f2及常数c(要求f1和f2中不含常数项)。