图片的存储结构
⑴ PNG、JPEG、BMP等几种图片格式详解(四)—— GIF
以下部分内容来自 网络 ,还会有一部分是自己的见解,我写这篇文章的目的是既让大家可以了解网络上已有的知识,但是不用再去找网络,还有就是可以看到我关于这种图片格式的深层次的了解,看完这篇,包括我在内,会感觉到即使很小很小的一个知识点,深入以后都是非常深的,底层和深层次原理是我的最爱,这也是我写博客的初衷和目的。
GIF(Graphics Interchange Format) 的原义是“ 图像 互换格式”,是 CompuServe 公司在 1987年开发的 图像文件格式 。GIF文件的数据,是一种基于 LZW算法 的连续色调的无损 压缩格式 。其 压缩率 一般在 50% 左右,它不属于任何应用 程序 。GIF格式可以存多幅彩色图像,如果把存于一个文件中的多幅 图像数据 逐幅读出并显示到屏幕上,就可构成一种最简单的动画。
GIF图象是基于颜色列表的(存储的数据是该点的颜色对应于颜色列表的索引值),最多只支持8位(256色)。GIF文件内部分成许多存储块,用来存储多幅图象或者是决定图象表现行为的控制块,用以实现动画和交互式应用。GIF文件还通过LZW压缩算法压缩图象数据来减少图象尺寸。
GIF格式自1987年由 CompuServe 公司引入后,因其体积小、成像相对清晰,特别适合于初期慢速的 互联网 ,而大受欢迎。
在早期, GIF 所用的LZW压缩算法是Compuserv所开发的一种免费算法。然而令很多软件开发商感到意外的是,GIF文件所采用的压缩算法忽然成了 Unisys 公司的专利。
据Unisys公司称,他们已注册了 LZW算法 中的W部分。如果要开发生成(或显示)GIF文件的程序,则需向该公司支付版税。由此,人们开始寻求一种新技术,以减少开发成本。 PNG ( Portable Network Graphics ,便携网络图形)标准就在这个背景下应运而生了。它一方面满足了市场对更少的法规限制的需要,另一方面也带来了更少的技术上的限制,如颜色的数量等。
在2003年6月20日,LZW算法在美国的专利权已到期而失效。在欧洲、日本及加拿大的专利权亦已分别在2004年的6月18日、6月20日和7月7日到期失效。尽管如此,PNG文件格式凭着其技术上的优势,已然跻身于网络上第三广泛应用格式。与GIF相关的专利于2006年8月11日过期。
长久以来,iOS一直被吐槽不能用GIF。造成这一局面的主要原因是:
GIF分为静态GIF和动画GIF两种,扩展名为.gif,是一种压缩 位图 格式,支持透明 背景图像 ,适用于多种操作系统,“体型”很小,网上很多小动画都是GIF格式。其实GIF是将多幅图像保存为一个图像文件,从而形成动画,最常见的就是通过一帧帧的动画串联起来的搞笑gif图,所以归根到底GIF仍然是 图片文件格式 。
但GIF只能显示256色。和 jpg格式 一样,这是一种在网络上非常流行的图形文件格式。
GIF主要分为两个版本,即 GIF 89a 和 GIF 87a
此给出的语法用来说明形成gif 数据流 的块序列,用一些规则列表来表达。下面列出用于gif语法的符号定义。
gif语法的符号定义:<GIF 数据流 > ::= 头部 <;逻辑视屏> <;数据>* 尾记录
gif 数据流 中的 数据块 可以分为三组:控制块、成象块和特殊用途块。
色表- gif格式利用色表来显示基于光栅的图像。色表分为全局色表和局部色表。全局色表对于那些没有设置局部色表的图像起作用。全局色表的作用域是整个 数据流 。局部色表对于紧接在其后的单张图像起作用。这两种色表都是可选的。
全局色表这东西是我们感兴趣的东西,它有点像png格式定义种的调色板,如果要修改gif图片的颜色,哈哈,修改这个全局色表就可以,如果有全局色表块,那么它一定从gif流的14个字节开始(头部6个 + 逻辑视频描述块7个)。
以下是各 数据块 的说明,如果注明为版本89a的话,则说明这个数据块不会在87a版的协议中出现。
Packed Fields 说明:
GIF文件内部是按块划分的,包括 控制块( Control Block ) 和 数据块(DataSub-blocks) 两种。控制块是控制数据块行为的,根据不同的控制块包含一些不同的控制参数;数据块只包含一些8-bit的字符流,由它前面的控制块来决定它的功能,每个数据块大小从0到255个字节,数据块的第一个字节指出这个数据块大小(字节数),计算数据块的大小时不包括这个字节,所以一个空的数据块有一个字节,那就是数据块的大小0x00。 下表是一个数据块的结构:
一个GIF文件的结构可分为文件头(File Header)、GIF数据流(GIF DataStream)和文件终结器(Trailer)三个部分。文件头包含GIF文件署名(Signature)和版本号(Version);GIF数据流由控制标识符、图象块(ImageBlock)和其他的一些扩展块组成;文件终结器只有一个值为0x3B的字符('';'')表示文件结束。下表显示了一个GIF文件的组成结构:
是用来标识GIF署名(Signature)和版本号(Version)的。
GIF署名用来确认一个文件是否是GIF格式的文件,这一部分由三个字符组成:"GIF";文件版本号也是由三个字节组成,可以为"87a"或"89a"。具体如下图所示。
它包含了很多的部分。
(1) 逻辑屏幕标识符 (Logical Screen Descriptor) :这一部分由7个字节组成,定义了GIF图象的大小 (Logical Screen Width &Height) 、颜色深度 (Color Bits) 、背景色 (Blackground ColorIndex) 以及有无全局颜色列表 (Global Color Table) 和颜色列表的索引数 (IndexCount) ,具体描述见下图。
也可以参考下图。
(2)全局颜色列表 (Global Color Table) :
全局颜色列表必须紧跟在逻辑屏幕标识符后面,每个颜色列表索引条目由三个字节组成,按R、G、B的顺序排列。
(3)图象标识符 (Image Descriptor) :一个GIF文件内可以包含多幅图象,一幅图象结束之后紧接着下是一幅图象的标识符,图象标识符以0x2C('','')字符开始,定义紧接着它的图象的性质,包括图象相对于逻辑屏幕边界的偏移量、图象大小以及有无局部颜色列表和颜色列表大小,由10个字节组成,具体如下所示。
也可以参考下图。
(4)局部颜色列表 (Local Color Table) :如果上面的局部颜色列表标志置位的话,则需要在这里(紧跟在图象标识符之后)定义一个局部颜色列表以供紧接着它的图象使用,注意使用前应线保存原来的颜色列表,使用结束之后回复原来保存的全局颜色列表。如果一个GIF文件即没有提供全局颜色列表,也没有提供局部颜色列表,可以自己创建一个颜色列表,或使用系统的颜色列表。局部颜色列表的排列方式和全局颜色列表一样:RGBRGB......
(5) 基于颜色列表的图象数据 (Table-Based Image Data) :由两部分组成: LZW 编码长度 (LZW Minimum Code Size) 和图象数据 (Image Data) 。
下面给出总体的存储结构的原理图。
PC上制作软件主要为 Adobe ImageReady 和 fireworks 两个。
WEB上gif在线制作编辑 gif5.net ,支持 图片 、视频、FLASH转GIF。
我一般使用 LICEcap 制作gif图。
1. 网络
2. GIF图片的文件储存结构和动画原理
3. GIF图片原理和储存结构深入解析
⑵ 视频,图片,音频这些格式的文件在内存中是以什么数据结构存储的呢
仍然是二进制的,只是不同于单纯的二进制数字。
具体来说就很繁琐了,
⑶ 图的三种存储结构
设图G有n (n 1) 个顶点,则邻接矩阵是一个n阶方阵。
当矩阵中的 [i,j] !=0(下标从1开始) ,代表其对应的第i个顶点与第j个顶点是连接的。
为图G中的每一个顶点建立一个单链表,每条链表的结点元素为与该顶点连接的顶点。
可以看成是有向图的邻接表和逆邻接表结合起来的一种链表。
⑷ 关于数据结构中图的储存方式的选择
首先你要明白,邻接链表存图的空间复杂度与图中边的数量有关(O(N+E) E表示图中边的数目),而数组存图空间复杂度与点数有关(O(N^2)N表示点数)
看点的数量,如果点的数量不是很大(比如几百个左右或者更小)那么二者都可以选择。
如果点的数量过大的话,用数组存储稀疏图会造成大量的空间浪费,此时选择使用邻接表更好。
⑸ 视频,图片,音频这些格式的文件在内存中是以什么数据结构存储的呢
有很多的,具体点是:视频是mv
rm
rvb等等了,图片是jpg
很多的,音频是mp3
wmv等等格式了.具体的你得问编这些程序的人了
⑹ 存储图用链式前向星好还是vector数组
一般来讲,图的常用存储结构有邻接矩阵,和邻接表,但我们知道邻接矩阵空间浪费太严重,邻接表不好写,今天来讲一下图的另一只常用的存储结构:前向星和链式前向星,介于上述两种存储结构之间的一种比较均衡的存储结构。
首先我们来说一下图的前向星表示方法:
前向星是一种通过存储边信息的方式来存储图的一种数据结构,他构造简单,读入每条边的信息,将边存放在数组中,把数组中的边按照起点顺序排列,前向星也就构造完成了。方便查询,我们用另外一个数组head(i)来存储起点为vi的第一条边的位置。
存储结构:
int head[MAXN];
struct Node
{
int from;//起点
int to;//终点
int w;//权值
};
Node map[MAXN];
比较函数:
bool cmp(const Node &a,const Node &b)
{
if(a.from==b.from)
{
if(a.to==b.to) return a.w<b.w;
else return a.to<b.to;
}
else return a.from<b.from;
}
读入数据:
cin>>n>>m;
for(i=1;i<=m;i++)
cin>>map[i].from>>map[i].to>>map[i].w;
sort(map+1,map+m+1,cmp);
memset(head,-1,sizeof(head));
for(i=1;i<=m;i++)
if(map[i].from!=map[i-1].from)
head[map[i].from]=i;
遍历函数:
for(i=1;i<=n;i++)
for(j=head[i];map[j],from==i&&j<=m;j++)
cout<<map[i].from<<map[i].to<<map[i].w<<endl;
⑺ 图的存储结构——所存储的信息有哪些
一、邻接矩阵存储方法
邻接矩阵是表示顶点之间相邻关系的矩阵。
设G=(V,E)是具有n(n>0)个顶点的图,顶点的顺序依次为0~n-1,则G的邻接矩阵A是n阶方阵,其定义如下:
(1)如果G是无向图,则:
A[i][j]=1:若(i,j)∈E(G) 0:其他
(2)如果G是有向图,则:
A[i][j]=1:若<i,j>∈E(G) 0:其他
(3)如果G是带权无向图,则:
A[i][j]= wij :若i≠j且(i,j)∈E(G) 0:i=j ∞:其他
(4)如果G是带权有向图,则:
A[i][j]= wij :若i≠j且<i,j>∈E(G) 0:i=j∞:其他
注意:带权图和不带权图表示的元素类型不同。
带权图(不论有向还是无向图)A[i][j]用double表示,不带权图(不论有向还是无向图)A[i][j]用int表示。
用一维数组G[ ]存储有4个顶点的无向图如:G[ ] = { 0, 1, 0, 1, 1, 0, 0, 0, 1, 0 }
则顶点2和顶点0之间是有边的。
如:
邻接矩阵的特点如下:
(1)图的邻接矩阵表示是唯一的。
(2)无向图的邻接矩阵一定是一个对称矩阵。因此,按照压缩存储的思想,在具体存放邻接矩阵时只需存放上(或下)三角形阵的元素即可。
(3)不带权的有向图的邻接矩阵一般来说是一个稀疏矩阵。因此,当图的顶点较多时,可以采用三元组表的方法存储邻接矩阵。
(4)对于无向图,邻接矩阵的第i行(或第i列)非零元素(或非∞元素)的个数正好是第i个顶点的度。
(5)对于有向图,邻接矩阵的第i行(或第i列)非零元素(或非∞元素)的个数正好是第i个顶点的出度(或入度)。
(6)用邻接矩阵方法存储图,很容易确定图中任意两个顶点之间是否有边相连。但是,要确定图中有多少条边,则必须按行、按列对每个元素进行检测,所花费的时间代价很大。这是用邻接矩阵存储图的局限性。
邻接矩阵的数据类型定义如下:
#define MAXV <最大顶点个数>
typedef struct
{ int no; //顶点编号
InfoType info; //顶点其他信息
} VertexType; //顶点类型
typedef struct //图的定义
{ int edges[MAXV][MAXV]; //邻接矩阵
int n,e; //顶点数,弧数
VertexType vexs[MAXV]; //存放顶点信息
} MGraph; //图的邻接矩阵表示类型
二、 邻接表存储方法
图的邻接表存储方法是一种顺序分配与链式分配相结合的存储方法。
在邻接表中,对图中每个顶点建立一个单链表,第i个单链表中的节点表示依附于顶点i的边(对有向图是以顶点i为尾的边)。每个单链表上附设一个表头节点。
其中,表节点由三个域组成,adjvex指示与顶点i邻接的点在图中的位置,nextarc指示下一条边或弧的节点,info存储与边或弧相关的信息,如权值等。
表头节点由两个域组成,data存储顶点i的名称或其他信息,firstarc指向链表中第一个节点。
typedef struct ANode
{ int adjvex; //该边的终点编号
struct ANode *nextarc; //指向下一条边的指针
InfoType info; //该边的相关信息
} ArcNode; //边表节点类型
typedef struct Vnode
{ Vertex data; //顶点信息
ArcNode *firstarc; //指向第一条边
} VNode; //邻接表头节点类型
typedef VNode AdjList[MAXV]; //AdjList是邻接表类型
typedef struct
{ AdjList adjlist; //邻接表
int n,e; //图中顶点数n和边数e
} ALGraph; //完整的图邻接表类型
邻接表的特点如下:
(1)邻接表表示不唯一。这是因为在每个顶点对应的单链表中,各边节点的链接次序可以是任意的,取决于建立邻接表的算法以及边的输入次序。
(2)对于有n个顶点和e条边的无向图,其邻接表有n个顶点节点和2e个边节点。显然,在总的边数小于n(n-1)/2的情况下,邻接表比邻接矩阵要节省空间。
(3)对于无向图,邻接表的顶点i对应的第i个链表的边节点数目正好是顶点i的度。
(4)对于有向图,邻接表的顶点i对应的第i个链表的边节点数目仅仅是顶点i的出度。其入度为邻接表中所有adjvex域值为i的边节点数目。
例, 给定一个具有n个节点的无向图的邻接矩阵和邻接表。
(1)设计一个将邻接矩阵转换为邻接表的算法;
(2)设计一个将邻接表转换为邻接矩阵的算法;
(3)分析上述两个算法的时间复杂度。
解:
(1)在邻接矩阵上查找值不为0的元素,找到这样的元素后创建一个表节点并在邻接表对应的单链表中采用前插法插入该节点。
void MatToList(MGraph g,ALGraph *&G)
//将邻接矩阵g转换成邻接表G
{ int i,j,n=g.n; ArcNode *p; //n为顶点数
G=(ALGraph *)malloc(sizeof(ALGraph));
for (i=0;i<n;i++) //给所有头节点的指针域置初值
G->adjlist[i].firstarc=NULL;
for (i=0;i<n;i++) //检查邻接矩阵中每个元素
for (j=n-1;j>=0;j--)
if (g.edges[i][j]!=0)
{ p=(ArcNode *)malloc(sizeof(ArcNode));
//创建节点*p
p->adjvex=j;
p->nextarc=G->adjlist[i].firstarc;
//将*p链到链表头
G->adjlist[i].firstarc=p;
}
G->n=n;G->e=g.e;
}
(2)在邻接表上查找相邻节点,找到后修改相应邻接矩阵元素的值。
void ListToMat(ALGraph *G,MGraph &g)
{ int i,j,n=G->n;ArcNode *p;
for (i=0;i<n;i++)
{ p=G->adjlist[i].firstarc;
while (p!=NULL)
{ g.edges[i][p->adjvex]=1;
p=p->nextarc;
}
}
g.n=n;g.e=G->e;
}
(3)算法1的时间复杂度均为O(n2)。算法2的时间复杂度为O(n+e),其中e为图的边数。
⑻ 数据结构——图
转自: http://www.cnblogs.com/mcgrady/archive/2013/09/23/3335847.html
阅读目录
一,图的定义
二,图相关的概念和术语
三,图的创建和遍历
四,最小生成树和最短路径
五,算法实现
这一篇我们要总结的是图(Graph),图可能比我们之前学习的线性结构和树形结构都要复杂,不过没有关系,我们一点一点地来总结,那么关于图我想从以下几点进行总结:
1,图的定义?
2,图相关的概念和术语?
3,图的创建和遍历?
4,最小生成树和最短路径?
5,算法实现?
一,图的定义
什么是图呢?
图是一种复杂的非线性结构。
在线性结构中,数据元素之间满足唯一的线性关系,每个数据元素(除第一个和最后一个外)只有一个直接前趋和一个直接后继;
在树形结构中,数据元素之间有着明显的层次关系,并且每个数据元素只与上一层中的一个元素(双亲节点)及下一层的多个元素(孩子节点)相关;
而在图形结构中,节点之间的关系是任意的,图中任意两个数据元素之间都有可能相关。
图G由两个集合V(顶点Vertex)和E(边Edge)组成,定义为G=(V,E)
二,图相关的概念和术语
1,无向图和有向图
对于一个图,若每条边都是没有方向的,则称该图为无向图。图示如下:
因此,(Vi,Vj)和(Vj,Vi)表示的是同一条边。注意,无向图是用小括号,而下面介绍的有向图是用尖括号。
无向图的顶点集和边集分别表示为:
V(G)={V1,V2,V3,V4,V5}
E(G)={(V1,V2),(V1,V4),(V2,V3),(V2,V5),(V3,V4),(V3,V5),(V4,V5)}
对于一个图G,若每条边都是有方向的,则称该图为有向图。图示如下。
因此,和是两条不同的有向边。注意,有向边又称为弧。
有向图的顶点集和边集分别表示为:
V(G)={V1,V2,V3}
E(G)={,,,}
2,无向完全图和有向完全图
我们将具有n(n-1)/2条边的无向图称为无向完全图。同理,将具有n(n-1)条边的有向图称为有向完全图。
3,顶点的度
对于无向图,顶点的度表示以该顶点作为一个端点的边的数目。比如,图(a)无向图中顶点V3的度D(V3)=3
对于有向图,顶点的度分为入度和出度。入度表示以该顶点为终点的入边数目,出度是以该顶点为起点的出边数目,该顶点的度等于其入度和出度之和。比如,顶点V1的入度ID(V1)=1,出度OD(V1)=2,所以D(V1)=ID(V1)+OD(V1)=1+2=3
记住,不管是无向图还是有向图,顶点数n,边数e和顶点的度数有如下关系:
因此,就拿有向图(b)来举例,由公式可以得到图G的边数e=(D(V1)+D(V2)+D(V3))/2=(3+2+3)/2=4
4,子图
故名思义,这个就不解释了。
5,路径,路径长度和回路
路径,比如在无向图G中,存在一个顶点序列Vp,Vi1,Vi2,Vi3…,Vim,Vq,使得(Vp,Vi1),(Vi1,Vi2),…,(Vim,Vq)均属于边集E(G),则称顶点Vp到Vq存在一条路径。
路径长度,是指一条路径上经过的边的数量。
回路,指一条路径的起点和终点为同一个顶点。
6,连通图(无向图)
连通图是指图G中任意两个顶点Vi和Vj都连通,则称为连通图。比如图(b)就是连通图。下面是一个非连通图的例子。
上图中,因为V5和V6是单独的,所以是非连通图。
7,强连通图(有向图)
强连通图是对于有向图而言的,与无向图的连通图类似。
8,网
带”权值”的连通图称为网。如图所示。
三,图的创建和遍历
1,图的两种存储结构
1) 邻接矩阵,原理就是用两个数组,一个数组保存顶点集,一个数组保存边集。下面的算法实现里边我们也是采用这种存储结构。如下图所示:
2) 邻接表,邻接表是图的一种链式存储结构。这种存储结构类似于树的孩子链表。对于图G中每个顶点Vi,把所有邻接于Vi的顶点Vj链成一个单链表,这个单链表称为顶点Vi的邻接表。
2,图的两种遍历方法
1) 深度优先搜索遍历
深度优先搜索DFS遍历类似于树的前序遍历。其基本思路是:
a) 假设初始状态是图中所有顶点都未曾访问过,则可从图G中任意一顶点v为初始出发点,首先访问出发点v,并将其标记为已访问过。
b) 然后依次从v出发搜索v的每个邻接点w,若w未曾访问过,则以w作为新的出发点出发,继续进行深度优先遍历,直到图中所有和v有路径相通的顶点都被访问到。
c) 若此时图中仍有顶点未被访问,则另选一个未曾访问的顶点作为起点,重复上述步骤,直到图中所有顶点都被访问到为止。
图示如下:
注:红色数字代表遍历的先后顺序,所以图(e)无向图的深度优先遍历的顶点访问序列为:V0,V1,V2,V5,V4,V6,V3,V7,V8
如果采用邻接矩阵存储,则时间复杂度为O(n2);当采用邻接表时时间复杂度为O(n+e)。
2) 广度优先搜索遍历
广度优先搜索遍历BFS类似于树的按层次遍历。其基本思路是:
a) 首先访问出发点Vi
b) 接着依次访问Vi的所有未被访问过的邻接点Vi1,Vi2,Vi3,…,Vit并均标记为已访问过。
c) 然后再按照Vi1,Vi2,… ,Vit的次序,访问每一个顶点的所有未曾访问过的顶点并均标记为已访问过,依此类推,直到图中所有和初始出发点Vi有路径相通的顶点都被访问过为止。
图示如下:
因此,图(f)采用广义优先搜索遍历以V0为出发点的顶点序列为:V0,V1,V3,V4,V2,V6,V8,V5,V7
如果采用邻接矩阵存储,则时间复杂度为O(n2),若采用邻接表,则时间复杂度为O(n+e)。
四,最小生成树和最短路径
1,最小生成树
什么是最小生成树呢?在弄清什么是最小生成树之前,我们需要弄清什么是生成树?
用一句语简单概括生成树就是:生成树是将图中所有顶点以最少的边连通的子图。
比如图(g)可以同时得到两个生成树图(h)和图(i)
知道了什么是生成树之后,我们就很容易理解什么是最小生成树了。所谓最小生成树,用一句话总结就是:权值和最小的生成树就是最小生成树。
比如上图中的两个生成树,生成树1和生成树2,生成树1的权值和为:12,生成树2的权值为:14,我们可以证明图(h)生成树1就是图(g)的最小生成树。
那么如何构造最小生成树呢?可以使用普里姆算法。
2,最短路径
求最短路径也就是求最短路径长度。下面是一个带权值的有向图,表格中分别列出了顶点V1其它各顶点的最短路径长度。
表:顶点V1到其它各顶点的最短路径表
从图中可以看出,顶点V1到V4的路径有3条(V1,V2,V4),(V1,V4),(V1,V3,V2,V4),其路径长度分别为15,20和10,因此,V1到V4的最短路径为(V1,V3,V2,V4)。
那么如何求带权有向图的最短路径长度呢?可以使用迪杰斯特拉(Dijkstra)算法。
⑼ 数据结构 - 图
前面我们学习了线性表,栈、队列和树。前面三者都属于线性表范畴,它的的数据元素是被串起来的,仅有线性关系,每个元素仅有一个直接前驱和一个直接后继,是属于一对一关系。在树里面,每个元素之间存在着明显的层次关系,每一层的元素可能和下一层的多个元素相关,但只能和上一层的一个元素相关,属于一对多的关系。而图是一种较线性表和树更为复杂的数据结构,在图的结构中,节点和节点的关系是任意的,图中任意两个数据元素都可能相关。
定义 :图( Graph )是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。
在图中需要注意的是:
(1)线性表中我们把数据元素叫元素,树中将数据元素叫结点,在图中数据元素,我们则称之为顶点(Vertex)。
(2)线性表可以没有元素,称为空表;树中可以没有节点,称为空树;但是,在图中不允许没有顶点(有穷非空性)。
(3)线性表中的各元素是线性关系,树中的各元素是层次关系,而图中各顶点的关系是用边来表示(边集可以为空)。
顶点Vi的度(Degree)是指在图中与Vi相关联的边的条数。对于有向图来说,有入度(In-degree)和出度(Out-degree)之分,有向图顶点的度等于该顶点的入度和出度之和。
①若无向图中的两个顶点V1和V2存在一条边(V1,V2),则称顶点V1和V2邻接(Adjacent);
②若有向图中存在一条边<V3,V2>,则称顶点V3与顶点V2邻接,且是V3邻接到V2或V2邻接直V3;
注意:无向图中的边使用小括号“()”表示,而有向图中的边使用尖括号“<>”表示。
在无向图中,若从顶点Vi出发有一组边可到达顶点Vj,则称顶点Vi到顶点Vj的顶点序列为从顶点Vi到顶点Vj的路径(Path)。
若从Vi到Vj有路径可通,则称顶点Vi和顶点Vj是连通(Connected)的。
图的存储结构除了要存储图中的各个顶点本身的信息之外,还要存储顶点与顶点之间的关系,因此,图的结构也比较复杂。常用的图的存储结构有邻接矩阵和邻接表等。
我们再来看一个有向图样例,如下图所示的左边。顶点数组为vertex[4]={v0,v1,v2,v3},弧数组arc[4][4]为下图右边这样的一个矩阵。主对角线上数值依然为0。但因为是有向图,所以此矩阵并不对称,比如由v1到v0有弧,得到arc[1][0]=1,而v到v没有弧,因此arc[0][1]=0。
注:由于存在n个顶点的图需要n*n个数组元素进行存储,当图为稀疏图时,使用邻接矩阵存储方法将会出现大量0元素,这会造成极大的空间浪费。这时,可以考虑使用邻接表表示法来存储图中的数据。
首先,回忆我们在线性表时谈到, 顺序存储结构 就存在预先分配内存可能造成存储空间浪费的问题,于是引出了 链式存储 的结构。同样的,我们也可以考虑对边或弧使用链式存储的方式来避免空间浪费的问题。
邻接表 由表头节点和表节点两部分组成,图中每个顶点均对应一个存储在数组中的表头节点。如果这个表头节点所对应的顶点存在邻接节点,则把邻接节点依次存放于表头节点所指向的单向链表中。
上面的图G1包含了"A,B,C,D,E,F,G"共7个顶点,而且包含了"(A,C),(A,D),(A,F),(B,C),(C,D),(E,G),(F,G)"共7条边。
上图右边的矩阵是G1在内存中的邻接表示意图。每一个顶点都包含一条链表,该链表记录了"该顶点的邻接点的序号"。例如,第2个顶点(顶点C)包含的链表所包含的节点的数据分别是"0,1,3";而这"0,1,3"分别对应"A,B,D"的序号,"A,B,D"都是C的邻接点。就是通过这种方式记录图的信息的。
邻接表有向图是指通过邻接表表示的有向图。
上面的图G2包含了"A,B,C,D,E,F,G"共7个顶点,而且包含了"<A,B>,<B,C>,<B,E>,<B,F>,<C,E>,<D,C>,<E,B>,<E,D>,<F,G>"共9条边。
上图右边的矩阵是G2在内存中的邻接表示意图。每一个顶点都包含一条链表,该链表记录了"该顶点所对应的出边的另一个顶点的序号"。例如,第1个顶点(顶点B)包含的链表所包含的节点的数据分别是"2,4,5";而这"2,4,5"分别对应"C,E,F"的序号,"C,E,F"都属于B的出边的另一个顶点。
⑽ 数字图像的存储格式
遥感数据以磁带、光盘等为存储介质,由一个或多个文件组成,每个文件又以若干个记录组成。记录是作为一个单位来处理的一组相连的数据,分为物理记录和逻辑记录; 文件是由若干个逻辑记录构成的在目的、形式和内容上彼此相似的信息项的集合。逻辑记录的排列方式决定了文件的结构方式,加之不同的辅助说明信息而构成了不同的遥感数据格式。对于遥感数字图像而言,它必须以一定的格式存储,才能有效地进行分发和利用。
多波段图像具有空间的位置和光谱的信息。多波段图像的数据格式根据在二维空间的像元配置中如何存储各种波段的信息可分为四类。
1. BSQ,BIL,BIP 格式
BSQ ( Band Sequential) 格式,又称为波段序贯格式,在一个遥感数据文件内各像元DN 值相当于以 “波段” 为主要关键字、以 “行” 为次要关键字、以 “列” ( 像元号) 为第三关键字对像元 DN 值进行排序存放。
BIL ( Band Interleaved by Line) 格式,又称为波段行交叉格式,在一个遥感数据文件内各像元 DN 值相当于以 “行”为主要关键字、以 “波段”为次要关键字、以 “列”( 像元号) 为第三关键字对像元 DN 值进行排序存放。
BIP ( Band Interleaved by Pixels) 格式,又称为波段像元交叉格式,在一个遥感数据文件内各像元 DN 值相当于以 “行”为主要关键字、以 “列” ( 像元号) 为次要关键字、以 “波段”为第三关键字对像元 DN 值进行排序存放。
上述遥感数据基本格式具有不同的特点和适用范围。BSQ 格式最适合于对单个波段的整个或部分图像空间区域进行存储和读取等处理操作,如图像对比度增强、平滑、锐化等; BIP 格式为图像数据单个像元波谱特性的存储与读取提供最佳性能,如在最大似然比分类法、波段之间的加减乘除代数运算等亦宜采用该格式; BIL 方式具有以上两种方式的中间特征,提供了图像空间和像元波谱处理之间的一种折中的方式,适用于以行 ( 图像扫描行) 为单位的处理操作,如水平方向的线性影像特征增强处理等。
2. Fast - L7A 格式
该格式是美国 EDC 在沿用了以往 Landsat 数据产品快速格式的基础上而选用的记录Landsat-7 / ETM + 数据的格式之一。Fast - L7A 格式的数据由 3 个头文件及 8 个数据文件组成,3 个头文件对应 Landsat-7 数据的三个波段组: 全色波段组、可见光及近红外波段组、热红外波段组; 8 个数据文件对应 Landsat-7 数据的 8 个波段。
3 个头文件中,每个头文件包含 3 个 1536 字节的记录,分别是管理记录、辐射记录和几何记录,它们记录了产品标识信息、图像标识信息、辐射校正系数、地图投影、地球模型、太阳高度角和方位角等图像数据辅助信息。8 个数据文件中,每个文件仅含一个波段的数据而不含头尾记录,图像数据按行顺序排列,并以 8 bit 无符号整数表示。
3. GeoTIFF 格式
GeoTIFF 是包含地理信息的一种 TIFF 格式的文件。GeoTIFF 格式的数据由 1 个头文件及相应的数据文件组成。其头文件与 Fast - L7A 头文件相似,8 个数据文件分别对应于Landsat-7 数据的 8 个波段数据。
4. HDF 格式
HDF ( Hierarchical Data Format,层次数据格式) 是由美国伊利诺伊大学 ( the Univer-sity of Illinois) 的国家超级计算应用中心 ( The National Center for Supercomputing Applica-tions,NCSA) 于 1987 年研制开发的一种软件和函数库,它使用 C 语言和 Fortran 语言编写,是一种超文本文件格式,能够存储不同种类的科学数据,包括图像、多维数组、指针及文本数据。HDF 格式还提供命令方式,分析现存 HDF 文件的结构,并即时显示图像内容。科学家可以用这种标准数据格式快速熟悉文件结构,摆脱不同数据格式之间相互转换的繁琐,而将更多的时间和精力用于数据管理和分析。目前,在国外各种卫星传感器上,已经广泛使用了这种标准数据格式,如 Landsat-7,EOS - TERRA,EOS - AQUA 等。
在物理存储结构上,一个 HDF 文件包括一个文件头 ( File Header) ,一个或多个描述块 ( Data Descriptor Block) ,若干个数据对象 ( Data Object) 。文件头位于 HDF 文件的头四个字节,其内容为四个控制字符的 ASCII 码值,四个控制字符为 N,C,S,A,可用于判断一个文件是否为 HDF 文件格式。数据对象是 HDF 文件最基本的存储元素,包括一个描述符和一个对应的数据元素。描述符长度为 12 个字节,主要用来描述这个数据元素的数据类型、位置偏移量、数据元素字节数。在实际的 HDF 文件中,描述符并不是和它对应的数据元素连在一起,而是把相关的许多描述符放在一起而构成一个描述块,在这个块的后面顺序存储了各个描述符所对应的数据元素。数据元素是数据对象中的裸数据部分,也就是数据本身,可以是字符、整数、浮点数、数组等。
1993 年美国航空航天局 ( NASA) 把 HDF 格式作为存储和发布 EOS ( Earth Observa-tion System,对地观测系统) 数据的标准格式,此后又在 HDF 标准的基础上共同开发了一种专门化的 HDF 格式———HDF - EOS,专门用于处理各种 EOS 产品。HDF - EOS 使用标准的 HDF 数据类型定义了点、条带、网格这三种特殊数据类型,并且引入了元数据( Metadata) ,简化了空间数据的访问过程,提高了科学研究和用户对 EOS 数据的访问速度。
遥感技术被应用以来,遥感数据采用过很多格式,以 Landsat-7 卫星的数据产品为例,该数据产品由美国地球观测系统数据中心 ( EDC) 提供,按照产品处理级别可分为 三类,即 Level 0R,Level 1R 和 Level 1G。三种产品的定义如下 :
Level 0R: 未经辐射校正和系统级几何校正的数据产品。
Level 1R: 经过辐射校正但未经系统级几何校正的数据产品。
Level 1G: 经过辐射校正和系统级几何校正的数据产品。
EDC 的各类产品所采用的数据格式共有三种,分别是 HDF,Fast - L7A 和 GeoTIFF,产品类型和数据格式之间的对应关系见表 4-1。
表 4-1 Landsat-7 数据产品类型及数据格式
在遥感数据中,除图像信息以外还附带有各种注记信息。这是提供数据结构在进行数据分发时,对存储方式用注记信息的形式来说明所提供的格式。以往曾使用多种格式,但从 1982 年起逐渐以世界标准格式的形式进行分发。因为这种格式是由 Landsat TechnicalWorking Group 确定的,所以也称 LTWG 格式。世界标准格式具有超结构 ( Super Struc-ture) 的构造,在它的描述符、文件指针、文件说明符的三种记录中记有数据的记录方法。其图像数据部分为 BSQ 方式或 BIL 方式。