⑴ 求常用的图算法(C语言描述)
/*Bezier曲线的Casteljau算法*/
float decas(degree,codff,t)
float coeff[];
float t;
int degree;
{
int r,i;
float t1;
float codffa[10];
t1=1.0-t;
for(i=0;i<=degree;i++)
coeffa[i]=coeff[i];
for(r=1;r<degree;r++)
for(i=0;i<=degree-r;i++)
{
coeffa[i]=t1*coeffa[i]+t*coeffa[i+1];
}
return (coeffa[0]);
}
/*B样条曲线—deBoor分割算法*/
float deboor(degree,coeff,knot,u,i)
float coeff[],knot[];
float u;
int degree,i;
{
int k,j;
float t1,t2;
float coeffa[30];
for(j=i-degree+1;j<=i+1;j++)
coeffa[j]=coeff[j-i+degree-1];
for(k=1;i<=degree;k++)
forj=i+1;j>=i-degree+k+1;j--)
{
t1=(knot[j+degree-k]-u)/(knot[j+degree-k]-knot[j-1]);
t2=1.0-t1;
coeffa[j]=t1*coeffa[j-1]+t2*coeffa[j];
}
return (coeffa[i+1]);
}
/*Bezier曲线的Horner算法*/
float hornbez(degree,coeff,t)
int degree;
float coff[];
float t;
{
int i,n;
float fact,t1,aux;
t1=1.0-t;fact=1.0;n=1;
aux=coeff[0]*t1;
for(i=1;i<degree;i++)
{
face=fact*t;
n=n*(degree-i+1)/i;
aux=(aux+fact*n*coeff[i])*t1;
}
aux=aux+fact*t*codff[degree];
return aux;
}
⑵ 工程图纸大小的老算法,如0.625、0.75、1.125、0.250等各代表多少请用mm*mm表示。
工程图纸推荐使用规格一般是:
2.0即A0:841*1189mm
1.0即A1:594*841mm
0.5即A2:420*594mm
0.25即A3:297*420mm
0.125即A4:210*297mm。
你提出的问题中:
0.25的是A3的图,297*420mm的
1.125、0.75和0.625都是加长图纸,一般不推荐使用。
1.125可能是A1加长或A2加长
0.625和0.75可能是A2加长。
加长的图纸直接这样表示一般太容易推断是哪种规格的图纸加长。
在工程设计中尽量使用A1即1.0的图纸。
我们在办公室中常用的打印机可以打A4和A3的图纸,即0.125和0.25的图。一般我一般用A3的纸打印A3、A2、A1的标准图(即0.25、0.5和1.0)的图,加长的图纸打印效果不太好,我曾经画过最长的图纸时4.75(A1加长),分成两段用A3的纸打印的。
如果要打印你上面说的图纸,可以去专门的文印部(即专门负责大字、排版、打印、晒图和装订的部门,大型设计单位一般都有)打印,他们的打印机可以打印几乎任意规格的图纸,包括标准和加长的。
⑶ 数据结构中五种算法(冒泡法,快速排序法,插入法,选择法,希尔法)系统架构图如何画
上网络搜
⑷ 图遍历的算法
图的遍历方法目前有深度优先搜索法和广度(宽度)优先搜索法两种算法。 深度优先搜索法是树的先根遍历的推广,它的基本思想是:从图G的某个顶点v0出发,访问v0,然后选择一个与v0相邻且没被访问过的顶点vi访问,再从vi出发选择一个与vi相邻且未被访问的顶点vj进行访问,依次继续。如果当前被访问过的顶点的所有邻接顶点都已被访问,则退回到已被访问的顶点序列中最后一个拥有未被访问的相邻顶点的顶点w,从w出发按同样的方法向前遍历,直到图中所有顶点都被访问。其递归算法如下:
Boolean visited[MAX_VERTEX_NUM]; //访问标志数组
Status (*VisitFunc)(int v); //VisitFunc是访问函数,对图的每个顶点调用该函数
void DFSTraverse (Graph G, Status(*Visit)(int v)){
VisitFunc = Visit;
for(v=0; v<G.vexnum; ++v)
visited[v] = FALSE; //访问标志数组初始化
for(v=0; v<G.vexnum; ++v)
if(!visited[v])
DFS(G, v); //对尚未访问的顶点调用DFS
}
void DFS(Graph G, int v){ //从第v个顶点出发递归地深度优先遍历图G
visited[v]=TRUE; VisitFunc(v); //访问第v个顶点
for(w=FirstAdjVex(G,v); w>=0; w=NextAdjVex(G,v,w))
//FirstAdjVex返回v的第一个邻接顶点,若顶点在G中没有邻接顶点,则返回空(0)。
//若w是v的邻接顶点,NextAdjVex返回v的(相对于w的)下一个邻接顶点。
//若w是v的最后一个邻接点,则返回空(0)。
if(!visited[w])
DFS(G, w); //对v的尚未访问的邻接顶点w调用DFS
} 图的广度优先搜索是树的按层次遍历的推广,它的基本思想是:首先访问初始点vi,并将其标记为已访问过,接着访问vi的所有未被访问过的邻接点vi1,vi2,…, vi t,并均标记已访问过,然后再按照vi1,vi2,…, vi t的次序,访问每一个顶点的所有未被访问过的邻接点,并均标记为已访问过,依次类推,直到图中所有和初始点vi有路径相通的顶点都被访问过为止。其非递归算法如下:
Boolean visited[MAX_VERTEX_NUM]; //访问标志数组
Status (*VisitFunc)(int v); //VisitFunc是访问函数,对图的每个顶点调用该函数
void BFSTraverse (Graph G, Status(*Visit)(int v)){
VisitFunc = Visit;
for(v=0; v<G.vexnum, ++v)
visited[v] = FALSE;
initQueue(Q); //置空辅助队列Q
for(v=0; v<G.vexnum; ++v)
if(!visited[v]){
visited[v]=TRUE; VisitFunc(v);
EnQueue(Q, v); //v入队列
while(!QueueEmpty(Q)){
DeQueue(Q, u); //队头元素出队并置为u
for(w=FirstAdjVex(G,u); w>=0; w=NextAdjVex(G,u,w))
if(!Visited[w]){ //w为u的尚未访问的邻接顶点
Visited[w]=TRUE; VisitFunc(w);
EnQueue(Q, w);
}
}
}
}
⑸ 百度地图的路径搜索算法
这个还是要问程序猿,现在比较流行A*算法,至于网络是否开发出了新的算法不得而知,毕竟没有完全相同的程序。
给你看一篇文献:
地图中最短路径的搜索算法研究
学生:李小坤 导师:董峦
摘要:目前为止, 国内外大量专家学者对“最短路径问题”进行了深入的研究。本文通过理论分析, 结合实际应用,从各个方面较系统的比较广度优先搜索算法(BFS)、深度优先搜索算法(DFS)、A* 算法的优缺点。
关键词:最短路径算法;广度优先算法;深度优先算法;A*算法;
The shortest path of map's search algorithm
Abstract:So far, a large number of domestic and foreign experts and scholars on the" shortest path problem" in-depth study. In this paper, through theoretical analysis and practical application, comprise with the breadth-first search algorithm ( BFS ), depth-first search algorithm ( DFS ) and the A * algorithms from any aspects of systematic.
Key words: shortest path algorithm; breadth-first algorithm; algorithm; A * algorithm;
前言:
最短路径问题是地理信息系统(GIS)网络分析的重要内容之一,而且在图论中也有着重要的意义。实际生活中许多问题都与“最短路径问题”有关, 比如: 网络路由选择, 集成电路设计、布线问题、电子导航、交通旅游等。本文应用深度优先算法,广度优先算法和A*算法,对一具体问题进行讨论和分析,比较三种算的的优缺点。
在地图中最短路径的搜索算法研究中,每种算法的优劣的比较原则主要遵循以下三点:[1]
(1)算法的完全性:提出一个问题,该问题存在答案,该算法能够保证找到相应的答案。算法的完全性强是算法性能优秀的指标之一。
(2)算法的时间复杂性: 提出一个问题,该算法需要多长时间可以找到相应的答案。算法速度的快慢是算法优劣的重要体现。
(3)算法的空间复杂性:算法在执行搜索问题答案的同时,需要多少存储空间。算法占用资源越少,算法的性能越好。
地图中最短路径的搜索算法:
1、广度优先算法
广度优先算法(Breadth-First-Search),又称作宽度优先搜索,或横向优先搜索,是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型,Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。广度优先算法其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位址,彻底地搜索整张图,直到找到结果为止。BFS并不使用经验法则算法。
广度优先搜索算法伪代码如下:[2-3]
BFS(v)//广度优先搜索G,从顶点v开始执行
//所有已搜索的顶点i都标记为Visited(i)=1.
//Visited的初始分量值全为0
Visited(v)=1;
Q=[];//将Q初始化为只含有一个元素v的队列
while Q not null do
u=DelHead(Q);
for 邻接于u的所有顶点w do
if Visited(w)=0 then
AddQ(w,Q); //将w放于队列Q之尾
Visited(w)=1;
endif
endfor
endwhile
end BFS
这里调用了两个函数:AddQ(w,Q)是将w放于队列Q之尾;DelHead(Q)是从队列Q取第一个顶点,并将其从Q中删除。重复DelHead(Q)过程,直到队列Q空为止。
完全性:广度优先搜索算法具有完全性。这意指无论图形的种类如何,只要目标存在,则BFS一定会找到。然而,若目标不存在,且图为无限大,则BFS将不收敛(不会结束)。
时间复杂度:最差情形下,BFS必须寻找所有到可能节点的所有路径,因此其时间复杂度为,其中|V|是节点的数目,而 |E| 是图中边的数目。
空间复杂度:因为所有节点都必须被储存,因此BFS的空间复杂度为,其中|V|是节点的数目,而|E|是图中边的数目。另一种说法称BFS的空间复杂度为O(B),其中B是最大分支系数,而M是树的最长路径长度。由于对空间的大量需求,因此BFS并不适合解非常大的问题。[4-5]
2、深度优先算法
深度优先搜索算法(Depth First Search)英文缩写为DFS,属于一种回溯算法,正如算法名称那样,深度优先搜索所遵循的搜索策略是尽可能“深”地搜索图。[6]其过程简要来说是沿着顶点的邻点一直搜索下去,直到当前被搜索的顶点不再有未被访问的邻点为止,此时,从当前辈搜索的顶点原路返回到在它之前被搜索的访问的顶点,并以此顶点作为当前被搜索顶点。继续这样的过程,直至不能执行为止。
深度优先搜索算法的伪代码如下:[7]
DFS(v) //访问由v到达的所有顶点
Visited(v)=1;
for邻接于v的每个顶点w do
if Visited(w)=0 then
DFS(w);
endif
endfor
end DFS
作为搜索算法的一种,DFS对于寻找一个解的NP(包括NPC)问题作用很大。但是,搜索算法毕竟是时间复杂度是O(n!)的阶乘级算法,它的效率比较低,在数据规模变大时,这种算法就显得力不从心了。[8]关于深度优先搜索的效率问题,有多种解决方法。最具有通用性的是剪枝,也就是去除没有用的搜索分支。有可行性剪枝和最优性剪枝两种。
BFS:对于解决最短或最少问题特别有效,而且寻找深度小,但缺点是内存耗费量大(需要开大量的数组单元用来存储状态)。
DFS:对于解决遍历和求所有问题有效,对于问题搜索深度小的时候处理速度迅速,然而在深度很大的情况下效率不高。
3、A*算法
1968年的一篇论文,“P. E. Hart, N. J. Nilsson, and B. Raphael. A formal basis for the heuristic determination of minimum cost paths in graphs. IEEE Trans. Syst. Sci. and Cybernetics, SSC-4(2):100-107, 1968”。[9]从此,一种精巧、高效的算法——A*算法问世了,并在相关领域得到了广泛的应用。A* 算法其实是在宽度优先搜索的基础上引入了一个估价函数,每次并不是把所有可扩展的结点展开,而是利用估价函数对所有未展开的结点进行估价, 从而找出最应该被展开的结点,将其展开,直到找到目标节点为止。
A*算法主要搜索过程伪代码如下:[10]
创建两个表,OPEN表保存所有已生成而未考察的节点,CLOSED表中记录已访问过的节点。
算起点的估价值;
将起点放入OPEN表;
while(OPEN!=NULL) //从OPEN表中取估价值f最小的节点n;
if(n节点==目标节点) break;
endif
for(当前节点n 的每个子节点X)
算X的估价值;
if(X in OPEN)
if(X的估价值小于OPEN表的估价值)
把n设置为X的父亲;
更新OPEN表中的估价值; //取最小路径的估价值;
endif
endif
if(X inCLOSE)
if( X的估价值小于CLOSE表的估价值)
把n设置为X的父亲;
更新CLOSE表中的估价值;
把X节点放入OPEN //取最小路径的估价值
endif
endif
if(X not inboth)
把n设置为X的父亲;
求X的估价值;
并将X插入OPEN表中; //还没有排序
endif
end for
将n节点插入CLOSE表中;
按照估价值将OPEN表中的节点排序; //实际上是比较OPEN表内节点f的大小,从最小路径的节点向下进行。
end while(OPEN!=NULL)
保存路径,即 从终点开始,每个节点沿着父节点移动直至起点,这就是你的路径;
A *算法分析:
DFS和BFS在展开子结点时均属于盲目型搜索,也就是说,它不会选择哪个结点在下一次搜索中更优而去跳转到该结点进行下一步的搜索。在运气不好的情形中,均需要试探完整个解集空间, 显然,只能适用于问题规模不大的搜索问题中。而A*算法与DFS和BFS这类盲目型搜索最大的不同,就在于当前搜索结点往下选择下一步结点时,可以通过一个启发函数来进行选择,选择代价最少的结点作为下一步搜索结点而跳转其上。[11]A *算法就是利用对问题的了解和对问题求解过程的了解, 寻求某种有利于问题求解的启发信息, 从而利用这些启发信息去搜索最优路径.它不用遍历整个地图, 而是每一步搜索都根据启发函数朝着某个方向搜索.当地图很大很复杂时, 它的计算复杂度大大优于D ijks tr a算法, 是一种搜索速度非常快、效率非常高的算法.但是, 相应的A*算法也有它的缺点.启发性信息是人为加入的, 有很大的主观性, 直接取决于操作者的经验, 对于不同的情形要用不同的启发信息和启发函数, 且他们的选取难度比较大,很大程度上找不到最优路径。
总结:
本文描述了最短路径算法的一些步骤,总结了每个算法的一些优缺点,以及算法之间的一些关系。对于BFS还是DFS,它们虽然好用,但由于时间和空间的局限性,以至于它们只能解决规模不大的问题,而最短或最少问题应该选用BFS,遍历和求所有问题时候则应该选用DFS。至于A*算法,它是一种启发式搜索算法,也是一种最好优先的算法,它适合于小规模、大规模以及超大规模的问题,但启发式搜索算法具有很大的主观性,它的优劣取决于编程者的经验,以及选用的启发式函数,所以用A*算法编写一个优秀的程序,难度相应是比较大的。每种算法都有自己的优缺点,对于不同的问题选择合理的算法,才是最好的方法。
参考文献:
[1]陈圣群,滕忠坚,洪亲,陈清华.四种最短路径算法实例分析[J].电脑知识与技术(学术交流),2007(16):1030-1032
[2]刘树林,尹玉妹.图的最短路径算法及其在网络中的应用[J].软件导刊,2011(07):51-53
[3]刘文海,徐荣聪.几种最短路径的算法及比较[J].福建电脑,2008(02):9-12
[4]邓春燕.两种最短路径算法的比较[J].电脑知识与技术,2008(12):511-513
[5]王苏男,宋伟,姜文生.最短路径算法的比较[J].系统工程与电子技术,1994(05):43-49
[6]徐凤生,李天志.所有最短路径的求解算法[J].计算机工程与科学,2006(12):83-84
[7]李臣波,刘润涛.一种基于Dijkstra的最短路径算法[J].哈尔滨理工大学学报,2008(03):35-37
[8]徐凤生.求最短路径的新算法[J].计算机工程与科学,2006(02).
[9] YanchunShen . An improved Graph-based Depth-First algorithm and Dijkstra algorithm program of police patrol [J] . 2010 International Conference on Electrical Engineering and Automatic Control , 2010(3) : 73-77
[10]部亚松.VC++实现基于Dijkstra算法的最短路径[J].科技信息(科学教研),2008(18):36-37
[11] 杨长保,王开义,马生忠.一种最短路径分析优化算法的实现[J]. 吉林大学学报(信息科学版),2002(02):70-74
⑹ C语言图的创建和遍历算法,紧急
图的遍历是指按某条搜索路径访问图中每个结点,使得每个结点均被访问一次,而且仅被访问一次。图的遍历有深度遍历算法和广度遍历算法,最近阿杰做了关于图的遍历的算法,下面是图的遍历深度优先的算法(C语言程序):
#include<stdio.h>
#include<malloc.h>
#define MaxVertexNum 5
#define m 5
#define TRUE 1
#define NULL 0
typedef struct node
{
int adjvex;
struct node *next;
}JD;
typedef struct EdgeNode
{
int vexdata;
JD *firstarc;
}TD;
typedef struct
{
TD ag[m];
int n;
}ALGRAPH;
void DFS(ALGRAPH *G,int i)
{
JD *p;
int visited[80];
printf("visit vertex:%d->",G->ag[i].vexdata);
visited[i]=1;
p=G->ag[i].firstarc;
while(p)
{
if (!visited[p->adjvex])
DFS(G,p->adjvex);
p=p->next;
}
}
void creat(ALGRAPH *G)
{
int i,m1,j;
JD *p,*p1;
printf("please input the number of graph\n");
scanf("%d",&G->n);
for(i=0;i<G->n;i++)
{
printf("please input the info of node %d",i);
scanf("%d",&G->ag[i].vexdata);
printf("please input the number of arcs which adj to %d",i);
scanf("%d",&m1);
printf("please input the adjvex position of the first arc\n");
p=(JD *)malloc(sizeof(JD));
scanf("%d",&p->adjvex);
p->next=NULL;
G->ag[i].firstarc=p;
p1=p;
for(j=2 ;j<=m1;j++)
{
printf("please input the position of the next arc vexdata\n");
p=(JD *)malloc(sizeof(JD));
scanf("%d",&p->adjvex);
p->next=NULL;
p1->next=p;
p1=p;
}
}
}
int visited[MaxVertexNum];
void DFSTraverse(ALGRAPH *G)
{
int i;
for(i=0;i<G->n;i++)
visited[i]=0;
for(i=0;i<G->n;i++)
if(!visited[i])
DFS(G,i);
}
int main()
{
ALGRAPH *G;
printf("下面以临接表存储一个图;\n");
creat(G);
printf("下面以深度优先遍历该图 \n");
DFSTraverse(G);
getchar();
}
⑺ 图的深度优先搜索和广度优先搜索算法的实现
//图的遍历算法程序
//图的遍历是指按某条搜索路径访问图中每个结点,使得每个结点均被访问一次,而且仅被访问一次。图的遍历有深度遍历算法和广度遍历算法,程序如下:
#include <iostream>
//#include <malloc.h>
#define INFINITY 32767
#define MAX_VEX 20 //最大顶点个数
#define QUEUE_SIZE (MAX_VEX+1) //队列长度
using namespace std;
bool *visited; //访问标志数组
//图的邻接矩阵存储结构
typedef struct{
char *vexs; //顶点向量
int arcs[MAX_VEX][MAX_VEX]; //邻接矩阵
int vexnum,arcnum; //图的当前顶点数和弧数
}Graph;
//队列类
class Queue{
public:
void InitQueue(){
base=(int *)malloc(QUEUE_SIZE*sizeof(int));
front=rear=0;
}
void EnQueue(int e){
base[rear]=e;
rear=(rear+1)%QUEUE_SIZE;
}
void DeQueue(int &e){
e=base[front];
front=(front+1)%QUEUE_SIZE;
}
public:
int *base;
int front;
int rear;
};
//图G中查找元素c的位置
int Locate(Graph G,char c){
for(int i=0;i<G.vexnum;i++)
if(G.vexs[i]==c) return i;
return -1;
}
//创建无向网
void CreateUDN(Graph &G){
int i,j,w,s1,s2;
char a,b,temp;
printf("输入顶点数和弧数:");
scanf("%d%d",&G.vexnum,&G.arcnum);
temp=getchar(); //接收回车
G.vexs=(char *)malloc(G.vexnum*sizeof(char)); //分配顶点数目
printf("输入%d个顶点.\n",G.vexnum);
for(i=0;i<G.vexnum;i++){ //初始化顶点
printf("输入顶点%d:",i);
scanf("%c",&G.vexs[i]);
temp=getchar(); //接收回车
}
for(i=0;i<G.vexnum;i++) //初始化邻接矩阵
for(j=0;j<G.vexnum;j++)
G.arcs[i][j]=INFINITY;
printf("输入%d条弧.\n",G.arcnum);
for(i=0;i<G.arcnum;i++){ //初始化弧
printf("输入弧%d:",i);
scanf("%c %c %d",&a,&b,&w); //输入一条边依附的顶点和权值
temp=getchar(); //接收回车
s1=Locate(G,a);
s2=Locate(G,b);
G.arcs[s1][s2]=G.arcs[s2][s1]=w;
}
}
//图G中顶点k的第一个邻接顶点
int FirstVex(Graph G,int k){
if(k>=0 && k<G.vexnum){ //k合理
for(int i=0;i<G.vexnum;i++)
if(G.arcs[k][i]!=INFINITY) return i;
}
return -1;
}
//图G中顶点i的第j个邻接顶点的下一个邻接顶点
int NextVex(Graph G,int i,int j){
if(i>=0 && i<G.vexnum && j>=0 && j<G.vexnum){ //i,j合理
for(int k=j+1;k<G.vexnum;k++)
if(G.arcs[i][k]!=INFINITY) return k;
}
return -1;
}
//深度优先遍历
void DFS(Graph G,int k){
int i;
if(k==-1){ //第一次执行DFS时,k为-1
for(i=0;i<G.vexnum;i++)
if(!visited[i]) DFS(G,i); //对尚未访问的顶点调用DFS
}
else{
visited[k]=true;
printf("%c ",G.vexs[k]); //访问第k个顶点
for(i=FirstVex(G,k);i>=0;i=NextVex(G,k,i))
if(!visited[i]) DFS(G,i); //对k的尚未访问的邻接顶点i递归调用DFS
}
}
//广度优先遍历
void BFS(Graph G){
int k;
Queue Q; //辅助队列Q
Q.InitQueue();
for(int i=0;i<G.vexnum;i++)
if(!visited[i]){ //i尚未访问
visited[i]=true;
printf("%c ",G.vexs[i]);
Q.EnQueue(i); //i入列
while(Q.front!=Q.rear){
Q.DeQueue(k); //队头元素出列并置为k
for(int w=FirstVex(G,k);w>=0;w=NextVex(G,k,w))
if(!visited[w]){ //w为k的尚未访问的邻接顶点
visited[w]=true;
printf("%c ",G.vexs[w]);
Q.EnQueue(w);
}
}
}
}
//主函数
void main(){
int i;
Graph G;
CreateUDN(G);
visited=(bool *)malloc(G.vexnum*sizeof(bool));
printf("\n广度优先遍历: ");
for(i=0;i<G.vexnum;i++)
visited[i]=false;
DFS(G,-1);
printf("\n深度优先遍历: ");
for(i=0;i<G.vexnum;i++)
visited[i]=false;
BFS(G);
printf("\n程序结束.\n");
}
输出结果为(红色为键盘输入的数据,权值都置为1):
输入顶点数和弧数:8 9
输入8个顶点.
输入顶点0:a
输入顶点1:b
输入顶点2:c
输入顶点3:d
输入顶点4:e
输入顶点5:f
输入顶点6:g
输入顶点7:h
输入9条弧.
输入弧0:a b 1
输入弧1:b d 1
输入弧2:b e 1
输入弧3:d h 1
输入弧4:e h 1
输入弧5:a c 1
输入弧6:c f 1
输入弧7:c g 1
输入弧8:f g 1
广度优先遍历: a b d h e c f g
深度优先遍历: a b c d e f g h
程序结束.
已经在vc++内运行通过,这个程序已经达到要求了呀~
⑻ 图像匹配的算法
迄今为止,人们已经提出了各种各样的图像匹配算法,但从总体上讲,这些匹配算法可以分成关系结构匹配方法、结合特定理论工具的匹配方法、基于灰度信息的匹配方法、基于亚像元匹配方法、基于内容特征的匹配方法五大类型 基于内容特征的匹配首先提取反映图像重要信息的特征,而后以这些特征为模型进行匹配。局部特征有点、边缘、线条和小的区域,全局特征包括多边形和称为结构的复杂的图像内容描述。特征提取的结果是一个含有特征的表和对图像的描述,每一个特征由一组属性表示,对属性的进一步描述包括边缘的定向和弧度,边与线的长度和曲率,区域的大小等。除了局部特征的属性外,还用这些局部特征之间的关系描述全局特征,这些关系可以是几何关系,例如两个相邻的三角形之间的边,或两个边之间的距离可以是辐射度量关系,例如灰度值差别,或两个相邻区域之间的灰度值方差或拓扑关系,例如一个特征受限于另一个特征。人们一般提到的基于特征的匹配绝大多数都是指基于点、线和边缘的局部特征匹配,而具有全局特征的匹配实质上是我们上面提到的关系结构匹配方法。特征是图像内容最抽象的描述,与基于灰度的匹配方法比,特相对于几何图像和辐射影响来说更不易变化,但特征提取方法的计算代价通常较,并且需要一些自由参数和事先按照经验选取的闭值,因而不便于实时应用同时,在纹理较少的图像区域提取的特征的密度通常比较稀少,使局部特征的提 取比较困难。另外,基于特征的匹配方法的相似性度量也比较复杂,往往要以特征属性、启发式方法及闭方法的结合来确定度量方法。基于图像特征的匹配方法可以克服利用图像灰度信息进行匹配的缺点,由于图像的特征点比象素点要少很多,因而可以大大减少匹配过程的计算量同时,特征点的匹配度量值对位置的变化比较敏感,可以大大提高匹配的精确程度而且,特征点的提取过程可以减少噪声的影响,对灰度变化,图像形变以及遮挡等都有较好的适应能力。所以基于图像特征的匹配在实际中的应用越来越广-泛。所使用的特征基元有点特征明显点、角点、边缘点等、边缘线段等。
⑼ 图的矩阵深度和广度遍历算法
图的遍历是指从图中任一给定顶点出发,依次访问图中的其余顶点。如果给定的图是连通图,则从图中的任意一点出发,按照一个指定的顺序就可以访问到图中的所有顶点,且每个顶点只访问一次。这个过程称为图的遍历。
图的遍历比树的遍历复杂的多。树是一种特殊类型的图,即无圈(无回路)连通图。树中的任意两个顶点间都有唯一的路径相通。在一个顶点被访问过之后,不可能又沿着另外一条路径访问到已被访问过的结点。而图中的顶点可能有边与其他任意顶点相连
。因此在访问了某个顶点之后,可能沿着另一条边访问已被访问过的顶点。例如图(a)中的G1,在访问了V1,V2和V3之后,有可能沿着边(V3,V1)访问到V1。为了避免一顶点被多次访问,可以设立一个集合Visited,用来记录已被访问过的顶点。它的初值为空
集。一旦V1被访问过,即把V1加到集合Visited中。图的遍厉通常有两种:图的深度优先
搜索和图的广度优先搜索。
1)图的深度优先搜索
从图G=(V,E)的一个顶点V0出发,在访问了任意一个与V0相邻且未被访问过的顶点W1之后,再从W1出发,访问和W1相邻且未被访问过的顶点W2,然后再从W2出发进行如上所述访问,直到找到一个它相邻的结点,都被访问过的结点为止。然后退回到尚有相
邻结点未被访问过的顶点,再从该顶点出发,重复上述搜索过程,直到所有被访问过的顶点的邻接点都被访问过为止。图的这种遍历过程就称为图的深度优先搜索。例如从顶点V1出发对图3.3.5进行深度优先搜索,遍历的顺序为 V1,V2,V5,V10,V6,V7,V3,V12,V1
1,V8,V4,V9。(与邻接表中的邻接点排列顺序有关,即p->next.vertex=v2 or v3对遍历
顺序有影响 )
例25.(p194.c)图的深度优先搜索。从图G的顶点V0
发进行深度优先搜索,打印出各个顶点的遍历顺序。
解:图的深度优先搜索法为:
(1)首先访问V0并把V0加到集合visited中;
(2)找到与V0相邻的顶点W,若W未进入
visited中,则以深度优先方法从W开始搜索。
(3)重复过程(2)直到所有于V0相邻的顶点
都被访问过为止。
下面是对用邻接表表示的图G进行深度优先搜索的程序
int rear=0; /*Visit和rear都为全局变量*/
int visit[500];
depth_first_search(g,v0) /*从V0开始对图G进行深度
优先搜索*/
graphptr g[ ]; /*指针数组,为邻接表表头顶点指针
g[vi]...g[vn]*/
int v0; /*这里V0和W都是顶点标号,如V0=0或1*/
{ /*g[v0]是顶点V0的表头指针*/
int w;
graphptr p; /*链表的结点指针*/
visit [++rear]=v0;
printf("%d\n",v0);
p=g[v0];/*指定一个顶点,通过邻接表表头指针
,访问v0的邻接顶点*/
while (p!=NULL)
{
w=p->vertex ;/*这里W是与V0相邻的一个顶点*/
if (!visited(w))/*当V0的相邻结点,W未被访问时,从W开始遍厉*/
depth_first_search(g,w);
p=p->next;/*接着访问另一个相邻顶点*/
}
}
int visited(w) /*检查顶点w是否进入visited(w)*/
int w ;
{
int i;
for (i=1;i<=rear;i++)
if (visit [ i ] == w) return(1);/*W在visit[]中,说明被访问过*/
return(0); /*W不在visit[]中,说明未被访问过,返回0*/
}
2)图的广度优先搜索
从图G的一个顶点V0出发,依次访问V0的邻接点K1,K2...Kn。然后再顺序访问K1,K2...Kn的所有尚未被访问过的邻接点。如此重复,直到图中的顶点都被访问过为止。图的这种搜索称为图的广度优先搜索。例如:从V1出发按广度优先搜索方法遍历图3.3.5,顶
点的访问顺序为V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12。
图的广度优先搜索类似树的按层次遍历,需要有一个队列来存放还没
有来得及处理的顶点。图的广度优先搜索算法为:
(1)首先把V0放入队列;
(2)若队列为空则结束,否则取出队列的头V;
(3)访问V并把所有与V相邻且未被访问的顶点插入队列;
(4)重复(2)-(3)直到队列为空。
上述算法中所有已被访问过的顶点都放在队列中,因此只要检查某个顶点是否在队列中就可以判断出该顶点是否已被访问过。
广度搜索法的程序如下:
broad_first_search(g,v0) /*从V0开始对图g进行广度优先搜索*/
graphptr g[ ]; /*为邻接表,表头顶点指针*/
int v0;
{
int queue[500],front =1, tail=1,v;
graphptr p;
queue [tail]=v0; /*把V0插入队列queue*/
while (front <=tail)/*当队列不为空*/
{
v=queue[front++]; /*取出队列中的顶点*/
printf("%d\n",v); /*访问该顶点*/
p=g[v]; /*从顶点V的链表来考虑与V相邻的顶点*/
while (p!=NULL)
{
v=p->vertex; /*从第一个结点(即边)中找出相邻的顶点*/
if (!visited(queue,tail,v))/*判断顶点是否进入队列,如进入队列
说明已被访问或将要访问*/
queue[++tail]=v;/*如果该顶点未被访问过,将此相邻顶点插入队列*/
p=p-->next;/*再考虑该结点的下一个相邻顶点*/
}
}
}
visited (q,tail,v)/*判断顶点是否被访问过,访问过时,返回1,否则返回0*/
int q[ ],tail,v;/*进入队列的顶点,在front之前的顶点已被访问过打印输出,
在front和tail之间的顶点是即将要访问顶点*/
{
int i;
for(i=1;i<=tail;i++)/*扫描队列,确定v是否在队列中,在队列中返回1,否则返回0*
/
if (q[i]==v)return(1);/*队列中的顶点都认为已被访问过*/
return(0);
}
深度优先的非递归算法
/*设当前图(或图的某个连通分枝)的起始访问点为p*/
NodeType stackMain,stackSec
visit(p)
p->mark=true;
do
{
for(all v isTheConnectNode of (G,p))//将当前点的邻接点中的所有结点压入副栈中
if(v.marked==false)
statckSec.push(v)
//将副栈中的点依次弹出,压入主栈中,这与非递归算法中使用队列的意图类似
while(!stackSec.isEmpty())
stackMain.push(statckSec.pop());
do//找出下一个未访问的结点或者没找到,直到栈为空
{
if(!stackMain.isEmpty())
{
p=stackMain.pop();
}
}while(p.marked==true&&!stackMain.isEmpty())
if(p.marked==false)//访问未访问结点.
{
visit(p);
p.marked=true;
}
}while(!stackMain.isEmpty())
⑽ 请教无向无环图最长路径算法
无向无环图就是树,
从根出发:
如果是计算最多的路径,就用广度优先(层次遍历)就可以了,最后访问的顶点一定是最多的路径的
如果是计算最长的路径长度,直接将上面的算法改一下,每个顶点时记下前面的来路的值加上现在的,就可以求出最大值
或者直接用Dijkstra 算法就可以了