cisco
Uploaded by
42 SLIDES
635 VUES
420LIKES

第 5 章 数组和广义表

DESCRIPTION

第 5 章 数组和广义表. wangzs@vip.sina.com. 学习要点. 数组的类型定义 数组的存储表示方法 特殊矩阵的压缩存储表示方法 稀疏矩阵的压缩存储表示方法 广义表的定义 广义表的存储结构. 数组的回顾. 在程序设计语言中,数组被定义为 连续的 、 有限的 , 有序的同种元素 的集合。. 一组 “ 连续的存储区域 ” ,指根据此区域的起点,通过名称及偏移的方式,可以很容易地取到该区域的数据. 数组的回顾. C 语言中一维数组的定义及使用: 类型说明符 数组名 [ 常量表达式 ] ; 例如: int a[10]. 操作举例:读入数据

1 / 42

Télécharger la présentation

第 5 章 数组和广义表

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第5章 数组和广义表 wangzs@vip.sina.com

  2. 学习要点 • 数组的类型定义 • 数组的存储表示方法 • 特殊矩阵的压缩存储表示方法 • 稀疏矩阵的压缩存储表示方法 • 广义表的定义 • 广义表的存储结构

  3. 数组的回顾 在程序设计语言中,数组被定义为连续的、有限的,有序的同种元素的集合。 一组“连续的存储区域”,指根据此区域的起点,通过名称及偏移的方式,可以很容易地取到该区域的数据.

  4. 数组的回顾 C语言中一维数组的定义及使用: 类型说明符数组名[常量表达式]; 例如: int a[10] 操作举例:读入数据 for (i=0;i<=9;i++) scanf(“%d”,&a[i]);

  5. 数组的回顾 C语言中二维数组的定义及使用: 类型说明符数组名[常量表达式][常量表达式]; 例如: int a[3][4] 操作举例:读入数据 for (i=0;i<=2;i++) for (j=0;j<=3;j++) scanf(“%d”,&a[i][j]);

  6. 5.1 数组的定义 数组可以看成是一种特殊的线性表,即线性表中数据元素本身也是一个线性表。 α0a00 a01 …….. a0n-1 α1a10 a11 …….. a1n-1 …………………. αm-1am-10 am-11 …….. am-1n-1 A=(α0α1…αi…αp)(p=m-1,p=n-1) 其中每个数据元素αi是个行向量形式的线性表 αi= (αi0αi1…αii…αin-1 ) 或是一个列向量形式的线性表 αi= (α0iα1i…αji…αm-1i)

  7. 数组的逻辑定义 • 数组特点 • 数组结构固定(维数、上下界、元素关系) • 数据元素同构 • 数组的基本操作 • 数组初始化 • 数组结构销毁 • 存数组元素 • 取数组元素

  8. 5.2 数组的顺序表示和实现 • 数组只需要顺序存储结构 • 数组不需要插入和删除(移动元素)操作 • 顺序存储结构可实现随机存取 • 数组是多维结构,存储器是一维结构,所以存在两种从多维到一维的映象方法。 • 以行序为主序(低下标优先) • 以列序为主序(高下标优先) • 以第一行第一列元素的地址作为基地址,其他元素根据基地址和下标计算出存储地址。

  9. 数组的顺序表示和实现 a00 a01 ……. a0n-1 a10 a11 …….. a1n-1 ………. am-10 am-11 …….. am-1n-1 0 按行序为主序存放 1 n-1 a00 a01 …….. a0n-1 n a10 a11 …….. a1n-1 …………………. am-10 am-11 …….. am-1n-1 Loc( aij)=Loc(a00)+[n*i+j]*l (m-1)*(n-1)

  10. 数组的顺序表示和实现 a00 a10 ……. am-10 a00 a01……..a0n-1 a01 a10a11 ……..a1n-1 a11 …….. …………………. am-11 am-10am-11…….. am-1n-1 ………. a0n-1 a0n-1 …….. am-1n-1 0 按列序为主序存放 1 m-1 m Loc(aij)=Loc(a00)+[m*j+i]*l (m-1)*(n-1)

  11. 5.3 矩阵的压缩存储 a11 0 0…….. 0 a11 a12 …. … ….. a1n a21 a22 0…….. 0 a21 a22 …….. ……. a2n …………………. 0 …………………. an1 an2 an3…….. ann an1 an2 …….. ann 这个矩阵中有一半的元素重复的,将浪费一半存储空间

  12. 矩阵的压缩存储 • 矩阵的压缩存储:对于多个值相同的元素只分配一个存储空间,对零元不分配存储空间。 • 特殊矩阵:值相同的元素或者零元素在矩阵中的分布有一定的规律。 • 稀疏矩阵:矩阵中存在大量的零元素。

  13. 矩阵的压缩存储 12 …. … ….. 7 2 4…….. ……. 9 …………………. 7 9…….. 10 按行序为主序: …... …... a11 a21 a22 a31 a32 an1 ann k=0 1 2 3 4 n(n-1)/2 n(n+1)/2-1 i(i-1) j(j-1) Loc(aij)=Loc(a11)+[ +(j-1)]*L Loc(aij)=Loc(a11)+[ +(i-1)]*L 2 2 若 n阶矩阵A中的元满足aij= aji 对称矩阵

  14. a11 0 0…….. 0 a21 a22 0…….. 0 …………………. 0 an1 an2 an3…….. ann 按行序为主序: …... …... a11 a21 a22 a31 a32 an1 ann k=0 1 2 3 4 n(n-1)/2 n(n+1)/2-1 i(i-1) Loc(aij)=Loc(a11)+[ +(j-1)]*L 2 矩阵的上(下)三角(不包括对角线)中的元素均 为常数c或为0的n阶矩阵 三角矩阵

  15. 对角矩阵 a11a120 …………… . 0 a21a22a230…………… 0 0a32a33a34 0……… 0 …………………………… 00… an-1,n-2an-1,n-1an-1,n 00… … an,n-1ann. 按行序为主序: …... a11 a12 a21 a22 a23 ann-1 ann …... k=0 1 2 3 4 n(n-1)/2 n(n+1)/2-1 Loc(aij)=Loc(a11)+[2(i-1)+(j-1)]*L

  16. 稀疏矩阵 • 假设在m*n的矩阵中,有t个元素不为0,则有 δ =t/(m*n),认为δ ≤ 0.05时为稀疏矩阵 • 压缩存储原则:只存矩阵的行列维数和每个非零元的行列下标及其值(三元组) 用三元组表示: ((1,2,12),(1,3,9),(3,1,-3),(3,6,14),(4,3,24),(5,2,18),(6,1,15), (6,4,-7))再加上行列值(6,7)就可以唯一确定一个稀疏矩阵

  17. 非零元值 行列下标 i j e 0 1 2 3 4 5 6 7 8 M 稀疏矩阵的压缩存储方法--顺序存储结构 1 2 12 1 3 9 3 1 -3 3 6 14 需存储: 行数=6;列数=7;非零元个数=8 每个非零元信息 4 3 24 5 2 18 6 1 15 6 4 -7

  18. 稀疏矩阵的压缩存储方法--顺序存储结构 三元组顺序表 #define MAXSIZE 12500 typedef struct{ int i,j; ElemType e; }Triple; typedef struct{ Triple data[MAXSIZE+1]; int mu,nu,tu; }TSMatrix

  19. 非零元值 行列下标 i j e 0 1 2 3 4 5 6 7 8 M TSMatrix M; M.mu=6;M.nu=7;M.tu=8 1 2 12 1 3 9 M.data[p].i,M.data[p].j,M.data[p].e分别存放非零元行列数和非零元值 3 1 -3 3 6 14 4 3 24 三元组表所需存储单元个数为3(tu+1) 其中tu为非零元个数 5 2 18 6 1 15 6 4 -7

  20. 三元组存放的稀疏矩阵转置操作 问题描述:已知一个稀疏矩阵的三元组表,求该矩阵转置矩阵的三元组表 一般矩阵转置算法: for(col=0;col<n;col++) for(row=0;row<m;row++) n[col][row]=m[row][col]; 时间复杂度:T(n)=O(mn)

  21. i j e i j e 1 3 -3 1 2 12 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 1 6 15 1 3 9 T 2 1 12 3 1 -3 M 2 5 18 3 6 14 ? 3 1 9 4 3 24 3 4 24 5 2 18 6 1 15 4 6 -7 6 3 14 6 4 -7

  22. 三元组存放的稀疏矩阵转置操作 • 解题思路:只要做到 将矩阵行、列值互换 将每个三元组中的i和j相互调换 重排三元组次序,使T中元素以T的行(M的列)为主序 方法一:按M的列序转置 即按T中三元组次序依次在M中找到相应的三元组进行 转置。为找到M中每一列所有非零元素,需对其三元组表 M从第一行起扫描一遍。由于M中以行序为主序,所以 由此得到的恰是T中应有的顺序

  23. 三元组存放的稀疏矩阵转置操作 i j v i j v 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 p p p p p p p p q q q p q q q p p q p q p p p p 1 2 12 1 3 9 3 1 -3 3 6 14 M T 4 3 24 5 2 18 6 1 15 6 4 -7 1 3 -3 1 6 15 2 1 12 2 5 18 3 1 9 3 4 24 4 6 -7 6 3 14 col=1 col=2

  24. 算法描述: int TransposeSmatrix(TSMatrix M,TSMatrix &T) { T.mu=M.nu; T.nu=M.mu; T.tu=M.tu; if (T.tu){ int q=1; for(int col=1;col<=M.nu;++col) for(int 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 1; } 时间复杂度:O(nu  tu)若tu和mu  nu 同数量级则:时间复杂度为O(mu  nu2)

  25. 方法二:快速转置 即按M中三元组次序转置,转置结果放入T中恰当位置

  26. i j v i j v 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 p p p p p p p p 1 2 12 1 3 9 3 1 -3 3 6 14 M T 4 3 24 5 2 18 6 1 15 6 4 -7 1 3 -3 1 6 15 2 1 12 2 5 18 3 1 9 3 4 24 4 6 -7 6 3 14 此方法关键是要预先确定M中每一列(T的每一行)第一个非零元在T中位置,为确定这些位置,转置前应先求得M的每一列中非零元个数。

  27. 实现:设两个数组 num[col]:表示矩阵M中第col列中非零元个数 cpot[col]:指示M中第col列第一个非零元在T中位置 显然有: cpot[1]=1; cpot[col]=cpot[col-1]+num[col-1]; (2col Ma.nu)

  28. 三元组存放的稀疏矩阵转置操作 col 3 6 7 1 2 4 5 2 num[col] 1 0 2 2 1 0 cpot[col] 1 3 7 8 5 8 9

  29. i j v i j v 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 p p p p p p p p 1 2 12 1 3 9 3 1 -3 col 7 6 1 3 2 5 4 3 6 14 num[col] M M 0 2 2 0 1 2 1 4 3 24 9 cpot[col] 8 3 1 7 8 5 5 2 18 6 1 15 6 4 -7 6 4 9 2 本列下一位置 5 7 3 1 3 -3 1 6 15 2 1 12 2 5 18 3 1 9 3 4 24 4 6 -7 6 3 14

  30. int fastTransposeSMatrix(TSMatrix M,TSMatrix &T){ int col,p,q,t; int num[10],cpot[10]; 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++) ++num[M.data[t].j]; cpot[1]=1; 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]; } } return 1; } 时间复杂度:T(n)=O(nu+tu) 若 t 与mn同数量级,则T(n)=O(mn)

  31. 稀疏矩阵的压缩存储方法--链式存储结构 3 2 1 4 5 8 2 2 4 col val row ^ down right 1 3 1 ^ ^ ^ ^ ^ ^

  32. 稀疏矩阵的压缩存储方法--链式存储结构 十字链表 typedef struct OLNode{ int i,j; ElemType e; struct OLNode*right,*down; }OLNode; *Olink; typedef struct{ Olink*rhead,*chead; int mu,nu,tu; }CrossList;

  33. 从键盘接收信息建立十字链表算法 1、初始化rhead与chead指针 2、接收信息生成结点 3、将新生成的结点插入到十字链表中 修改同一行的前一个元素的right指针,修改同一列元素的down指针

  34. 1 2 3 1 8 5 4 7 4 2 2 2 ^ ^ 1 3 1 ^ ^ ^ ^ ^ ^ ^ ^ m=4,n=3,t=5 1,1,3 2,2,5 2,3,4 4,1,8 2,1,7

  35. 矩阵相加 矩阵A+矩阵B可能出现的情况: 1、aij+bij : aij与bij均为非零元若值非零,修改相应的 aij的值;若为零元,则删除aij结点 2、 aij + bij = aij :表示bij为零,则不作任何操作 3、 aij + bij =bij:表示aij为零,则插入bij元素

  36. 设pa,pb分别指向矩阵A和矩阵B中行值相等的两个结点设pa,pb分别指向矩阵A和矩阵B中行值相等的两个结点 若pa= =Null表示A中无非零元 则: (1)pa= = Null或者pa->j > pb->j则在A中插入结点bij (2)pa->j < pb->j则pa=pa->right (3)pa->j= =pb->j且pa->e+pb->e !=0 则pa->e= pa->e+pb->e 若pa->e+pb->e =0则删除pb结点并修改pa同行、同列  的前一个结点的right与down域 此外:需要设定辅助指针:pre 指示pa同一行的前驱结 点;A的每一列的链表上设一个指针hl[j],初值和列链 表的头指针相同,即hl[j]=chead[j]

  37. 5.4 广义表的定义 广义表也一种线性表,又称为列表。一般记作: LS=(α1,…,αi…,αn) LS:表名; n: 表长;空表:n = 0 αi:元素,若是单个元素,称为广义表LS的原子, 若是广义表则称为广义表LS的子表。 表头:第一个元素;其余元素组成的表为表尾。 广义是线性表的推广。广泛地用于人工智能等领域的表处理语言LISP。

  38. 广义表的定义 例:以下为广义表 A=()F=(b,(c,d,e))E=(b,(c),(d,e)) D=(E,A,F)C=(A,D,F)B=(a,B)=(a,(a,(a,v...))) 基本操作举例: 求长度GListLength(L);由最外层括弧中的"逗号"来定 求深度GListDepth(L);括弧嵌套的最深层次 求表头GetHead(L);表中第一个数据元素(单原子或表) 求表尾GetTail(L); “必定”是个广义表(可能为空)

  39. 广义表的定义 结论:广义表是一种多层次结构,兼有线性结构的特性: 1. 广义表中的数据元素有固定的相对次序; 2. 广义表的长度定义为最外层括弧中包含的数据元素个数; 3. 广义表的深度定义为广义表中括弧的最大重数。 4. 广义表可被其它广义表所共享。 D=(E,A,F) 5. 广义表可以是一个“自递归”的表。B=(a,B) 自递归的广义表的长度是个有限值,而深 度为无限值。

  40. 5.4 广义表的存储结构 tag=0 atom tag=1 hp tp 表结点 原子结点 采用链式存储结构: typedefenum{ATOM,LIST}ElemTag;//ATOM=0;LIST=1 typedef struct GLNode{ ElemTag tag; union{ AtomType atom; struct{ struct GLNode *hp,*tp; }ptr; }; }*GList

  41. 小结 本章学习了线性表的扩展:即数据元素本身也是一个数据结构(线性表)。 要求掌握数组的类型定义、数组的存储表示方法、 特殊矩阵的压缩存储表示方法及其与线性存储结构的对应、稀疏矩阵的压缩存储表示方法及其运算。 另外,要求掌握广义表的定义和广义表的存储结构。

  42. 作业及思考题 • 实现二维数组到一维数组的映射的算法。 • 上机实现三元组存放的稀疏矩阵转置算法。

More Related