数据结构--数组

来源:互联网 发布:中国大学生失业率数据 编辑:程序博客网 时间:2024/05/16 17:56

数组的定义:
数组是由一组 类型相同 的数据元素构成的有序集合,每个数据元素称为一个数组元素(简称为元素),每个元素受n(n ≥1)个线性关系的约束, 每个元素在n个线性关系中的序号i1 、i2、… 、in 称为该元素的下标,并称该数组为n维数组。

有点难理解,没关系,我们看下面这个二维数组:
这里写图片描述
例如,这是个二维数组,因此元素a22受两个线性关系的约束,在行上有一个行前驱a21和一个行后继a23,在列上有一个列前驱a12和一个列后继a32。
或者可以理解为,一个数组中的元素的下标需要几个数字来表示时,它就是几维的。

数组的特点:
1.元素本身可以具有某种结构,属于同一数据类型;例如,数组元素可以为线性表。
2.数组是一个具有固定格式和数量的数据集合。
3.下标有界。

数组可以看成是线性表的推广:
这里写图片描述
那么这个二维数组是数据元素为线性表的线性表。

数组没有插入和删除操作,所以,不用预留空间,适合采用顺序存储。
数组的存取和修改操作本质上只对应一种操作–寻址。

二维数组Amn可视为由m个行向量组成的向量,或由n个列向量组成的向量:
这里写图片描述

数组通常有两种顺序存储方式:
行优先顺序和列优先顺序。

1.行优先顺序:
将数组元素按行排列,第 i+1个行向量紧接在第 i 个行向量后面。
以二维数组为例,按行优先顺序存储的线性序列为: a 11 , a 12 , …, a 1n , a 21 , a 22 , …, a 2n , …, a m1 , a m2 , …, a mn

2.列优先顺序:
将数组元素按列向量排列,第 j+ 1个列向量紧接在第 j 个列向量之后,A的 m × n 个元素按列优先顺序存储的线性序列为:
a 11 , a 21 , …, a m1 , a 12 , a 22 , …, a m2 , …, a n1 , a n2 , …, a nm

按上述两种方式顺序存储的序组,只要知道开始结点的存放地址(即基地址),维数和每维的上、下界,以及每个数组元素所占用的单元数,就可以将数组元素的存放地址表示为其下标的线性函数。

设有二维数组A=(a ij ) m×n ,若每个元素占用的存储单元数为l(个),LOC[a 11 ]表示元素a 11 的首地址,即数组的首地址。

以“行优先顺序”存储:
二维数组中任一元素a ij 的(首)地址是:
LOC[a ij ] = LOC[a 11 ] + [(i - 1) * n + (j - 1)] * l
//i=1,2,…,m
//j=1,2,…,n

以“ 列优先顺序 ”存储:
二维数组中任一元素a ij 的(首)地址是:
LOC[a ij ] = LOC[a 11 ] + [(i - 1) * m + (j - 1)] * l
//i = 1, 2,…, n
//j = 1, 2,…, m

矩阵的压缩存储:
对于高阶矩阵,若其中非零元素呈某种规律分布或者矩阵中有大量的零元素,若仍然用常规方法存储,可能存储重复的非零元素或零元素,将造成存储空间的大量浪费。对这类矩阵进行压缩存储:
◆ 多个相同的非零元素只分配一个存储空间;
◆ 零元素不分配空间。

常见的这类特殊矩阵有:对称矩阵、下(上)三角矩阵、对角线矩阵等等。

1.对称矩阵:
对称矩阵中的元素关于主对角线对称,因此,让每一对对称元素a ij 和a ji (i≠j)分配一个存储空间,则n^2个元素压缩存储到n(n+1)/2个存储空间,能节约近一半的存储空间。

假设按“行优先顺序”存储下三角形(包括对角线)中的元素,那么:
这里写图片描述

2.三角矩阵:
以主对角线划分,三角矩阵有上三角和下三角两种。
三角矩阵中的重复元素c可共享一个存储空间,其余的元素正好有n(n+1)/2个,因此,三角矩阵可压缩存储到向量sa[0…n(n+1)/2]中。
这里写图片描述

3.对角矩阵:
对角矩阵即除了主对角线和主对角线上或下方若干条对角线上的元素之外,其余元素皆为零。
这里写图片描述

由此可知,一个k对角矩阵(k为奇数)A是满足下述条件: 当| i-j |>(k-1)/2时, a ij = 0。

对这种矩阵,当以按“行优先顺序”存储时, 第1行和第n行是2个非零元素,其余每行的非零元素都要是3个,则需存储的元素个数为3n-2。

4.稀疏矩阵:
对于稀疏矩阵,目前还没有一个确切的定义。
三元组表示法
矩阵中的每个元素都是由行序号和列序号唯一确定的。因此,我们需要用三项内容表示稀疏矩阵中的每个非零元素,即形式为: ( i,j,value) 。其中,i 表示行序号, j 表示列序号, value 表示非零元素的值。

若以行序为主序,稀疏矩阵中所有非0元素的三元组,就可以得构成该
稀疏矩阵的一个三元组顺序表。相应的数据结构定义如下:

#define MAX_SIZE 101typedef int elemtype ;//三元组结点定义typedef struct{    int row ; /* 行下标 */    int col ; /* 列下标 */    elemtype value; /* 元素值 */}Triple ;//三元组顺序表定义typedef struct{    int rn ; /* 行数 */    int cn ; /* 列数 */    int tn ; /* 非0元素个数 */    Triple data[MAX_SIZE] ;}TMatrix ;

稀疏矩阵的转置运算:
设稀疏矩阵A是按行优先顺序压缩存储在三元组表a.data中,若仅仅是简单地交换a.data中i和j的内容,得到三元组表b.data,b.data将是一个按列优先顺序存储的稀疏矩阵B,要得到按行优先顺序存储的b.data,就必须重新排列三元组表b.data中元素的顺序。

求转置矩阵的基本算法思想是:
1.将矩阵的行、列下标值交换。即将三元组表中的行、列位置值i 、j相互交换;
2.重排三元组表中元素的顺序。即交换后仍然是按行优先顺序排序的。

算法思想:按稀疏矩阵A的三元组表a.data中的列次序依次找到相应的三元组存入b.data中。每找转置后矩阵的一个三元组,需从头至尾扫描整个三元组表a.data 。找到之后自然就成为按行优先的转置矩阵的压缩存储表示。

对于稀疏矩阵,当非0元素的个数和位置在操作过程中变化较大时,采用链式存储结构表示比三元组的线性表更方便。
矩阵中非0元素的结点所含的域有:行、列、值、行指针 (指向同一行的下一个非0元)、列指针(指向同一列的下一个非0元)。其次,十字交叉链表还有一个头结点:
这里写图片描述

结构体实现如下:

typedef struct Clnode{     int row , col ; /* 行号和列号 */    elemtype value ; /* 元素值 */    struct Clnode *down , *right ;}OLNode ; /* 非0元素结点 */typedef struct{     int rn; /* 矩阵的行数 */    int cn; /* 矩阵的列数 */    int tn; /* 非0元素总数 */    OLNode *rchead ;    OLNode *chead ;}CrossList ;

十字链表存储示意图如下:
这里写图片描述

0 0
原创粉丝点击