图相关基础代码——考研备考篇

目录

图的存储结构

邻接矩阵

 邻接表

图的遍历算法

图的深度优先算法 

图的广度优先算法 

最小生成树

普利姆算法(Prim)

克鲁斯卡尔算法

拓扑序列


图的存储结构

邻接矩阵

typedef struct
{
    int no; //顶点编号
    char info; //顶点其他信息(一般不用)
}VertexType; //顶点类型

typedef struct //图的定义
{
    int edges[maxSize][maxSize]; //邻接矩阵定义
    int n,e; //顶点数和边数
    VertexType vex[maxSize]; //存放结点信息
}MGraph; //图的邻接矩阵类型

 邻接表

typedef struct ArcNode //边定义
{
    int adjvex; //该边所指向结点
    struct ArcNode *nextarc; //指向下一条边的指针
    int info; //边的其他信息(如权值)
}ArcNode;

typedef struct //点定义
{
    char data; //顶点信息
    ArcNode *firstarc; //指向第一条边的指针
}VNode;

typedef struct //邻接表定义
{
    VNode adjlist[maxSize]; //邻接表
    int n,e; //顶点数和边数
}AGraph;

图的遍历算法

图的深度优先算法 

以邻接表为存储结构的图的深度优先搜索遍历算法(天勤)

int visit[maxSize];            // 记录顶点是否被访问
void DFS(AGraph *G, int v)
{
	ArcNode *p;   
	visit[v]=1;   // 设置已访问标记
	Visit(v);     // 访问v
	p=G->adjlist[v].firstarc; //指向顶点的第一条边
	while(p!=NULL)
	{
		if(visit[p->adjvex]==0)   // 若顶点未访问,则递归它
			DFS(G,p->adjvex);
		p=p->nextarc;        // p指向顶点v的下一条边的终点
	}
}

//若为非联通图,外套一层循环
void dfs(AGraph *g)
{
    int i;
    for(i=0;i<g->n;++i)
        if(visit[i]=0)
            DFS(g,i);
}

以邻接表为存储结构的图的广度优先搜索遍历算法(王道)

bool visited[MAX_VERTEX_NUM]; // 标记访问数组

void DFSTraverse(Graph G) {
	for(v = 0; v < G.vexnum; v ++)
		visited[v] = FALSE;   			// 初始化已访问标记数据 
	for(v = 0; v < G.vexnum; v ++)    // 有可能是非联通图,所以需要遍历每一个顶点 
		if(!visited(v))
			DFS(G,v);
} 

void DFS(Graph G,int v) { // 从顶点 v 出发,深度优先遍历图 G 
	visit(v);			  // 访问顶点 v  		
	visited[v] = TRUE;	  // 标记已访问过该顶点
	for(w = FirstNeighbor(G,v);w >= 0; w = NextNeighor(G,v,w)) 
		if(!visited(w))
			DFS(G,w); 
} 

图的广度优先算法 

以邻接表为存储结构的图的广度优先搜索遍历算法(天勤)

void BFS(AGraph *G, int v, int visit[maxSize])
{
	ArcNode *p;
	int que[maxSize], front=0, rear=0;    // 队列定义
	int j;
	Visit(v);        // 任意访问顶点v的函数
	visit[v]=1;
	rear=(rear+1)%maxSize;      
	que[rear]=v; // 进队
	while(front!=rear)     // 队空的时候说明遍历完成
	{
		front=(front+1)%maxSize;
		j=que[front];
		p=G->adjlist[j].firstarc;    // p指向出队顶点j的第一条边
		while(p!=NULL)
        {
			if(visit[p->adjvex]==0)    // 当前结点未被访问,进队
			{
				Visit(p->adjvex);
				visit[p->adjvex]=1;
				rear=(rear+1)%maxSize;  
				que[rear]=p->adjvex; // 顶点进队
			}
			p=p->nextarc;        // p指向j的下一条边
		}
	}
}

//如果为非联通图,外套循环
void bfs(AGraph *g)
{
    int i;
    for(i=0;i<g->n;++i)
        if(visit[i]==0)
            BFS(g,i,visit);
}

以邻接表为存储结构的图的广度优先搜索遍历算法(王道)

bool visited[MAX_VERTEX_NUM]; // 标记访问数组
void BFSTraverse(Graph G) {
	for(int i = 0; i < G.vexnum; i ++) 
		visited[i] = FALSE; 	// 访问数组初始化  
	InitQueue(Q);
	for(int i = 0; i < G.vexnum; i ++)
		if(!visited[i])     // 对每个连通分量调用一次 BFS   		
			BFS(G,i);			// 对没有访问过的顶点进行BFS遍历 
} 

void BFS(Graph G,int v)     // 从顶点 v 出发,进行广度优先遍历
{	
	visit(v);
	visited[v] = TRUE;		// 标记顶点 v 已经访问过 
	EnQueue(Q,v); 			// 将顶点 v 进行入队
	while(!isEmpty(Q)) {
		DeQueue(Q,v);		// 顶点 v 出队
		for(w = FirstNeighbor(G,v); w >= 0; w = NextNeighbor(G,v,w)){//检测 v 所有的邻接点
			if(!visited[w]){
				visit(w);
				visited[w] = TRUE; 	
				EnQueue(Q,w); 
			}
		} 
	} 
}

西工大期末04-05 有向图邻接链表 DFS非递归 

void DFS(AGraph *g,int v)
{    
    ArcNode *p;
    int stack[maxSize],top=-1;    //定义一个栈来几率访问过程中的顶点
    int i,k;
    int visit[maxSize];
    for(i=0;i<g->n;++i) //g->n为图中的顶点总数
        visit[i]=0; //初始化数组
    visit(v); //包含对顶点v的各种操作
    visit[v]=1; //标记定义已被访问
    stack[++top]=v; //起始顶点入栈
    while(top!=-1)
    {
        k=stack[top]; //取栈顶元素
        p=g->adjlist[k].firstarc; //p指向该顶点的第一条边
        while(p!=NULL&&visit[p->adjvex]==1) //找到当前顶点第一个未被访问的邻接顶点
            p=p->nextarc;
        if(p==NULL) //如果p为空,代表当前顶点的所有邻接顶点都被访问过,当前顶点出栈
            --top;
        else //否则访问邻接点,并入栈
        {
            visit(p->adjvex);
            visit[p->adjvex]=1;
            stack[++top]=p->adjvex;
        }
    }
}

 西工大期末09-10 无向图邻接矩阵 DFS非递归 

bool visited[vexnum]; // 标记访问数组

void DFSTraverse(Graph G) {
	for(v = 0; v < G.vexnum; v ++)
    {
		visited[v] = FALSE;   			// 初始化已访问标记数据 
	}
	for(v = 0; v < G.vexnum; v ++)    // 有可能是非联通图,所以需要遍历每一个顶点 
    {	
		if(!visited(v))
        {
			DFS(G,v);
		}
	} 
} 

void DFS(Graph G,int v) // 从顶点 v 出发,深度优先遍历图 G 
{ 
	int w;
    initstack(s);    //用栈实现递归
    Push(s,v);  	//将顶点v入栈	
	visited[v] = TRUE;	  // 标记已访问过该顶点
    while(!IsEmpty(s)) //栈不空时循环
    {
        k=Pop(s);
        visit(k);
	    for(w = 0;w < G.vexnum;w ++) 
        {
		    if(G.Edge[k][w] == 1 && !visited(w))
            {
			    Push(s,w);
                visited[w] = TRUE;
		    }
	    }
    } 
} 

西工大07考研邻接矩阵DFS递归

bool visited[vexnum];
void DFS(Graph G,int v)
{
    visit(v);
    visit[v]=true;
    for(w=0;w<G.vexnum;w++)
    {
        if(G.edge[v][w] ==1 && !visited[w])
        {
            DFS(G,w);
        }
    }
}

最小生成树

普利姆算法(Prim)

void Prim(MGraph g, int v0, int &sum)
{
	int lowcost[maxSize],vset[maxSize], v; 
    //lowcost存放当前生成树到剩余各顶点最短边权值,vset表示顶点是否并入树中
	int i, j, k, min;
	v=v0;
	for(i = 0; i < g.n; i++)
	{
		lowcost[i] = g.edges[v0][i];
		vset[i] = 0; //初始化数组
	}
	vset[v0] = 1; //将v0并入树中
    sum=0; //sum清零用来累计树的权值
	for(i = 0; i < g.n-1; i++) //用于选出侯选边中的最小者
	{
		min = INF; //INF是已经定义过的一个巨大值
		for(j = 0; j < g.n; j++)
			if(vset[j]==0 && lowcost[j]<min) //选出当前生成树到其余顶点最短边中的最短的一条
			{
				min = lowcost[j];
				k = j;
			}
			
		vset[k] = 1;
        v=k;
		sum += min;
		for(j = 0; j < g.n; j++) //更新侯选边
			if(vset[j] == 0 && g.edges[v][j] < lowcost[j])
				lowcost[j] = g.edges[v][j];
	}
}

克鲁斯卡尔算法

void Kruskal(MGraph g, int &sum, Road road[])
{   int i, a, b;  

	sum = 0;
	
	for(i = 0; i < g.n; i++) //将各顶点设置为不同的连通分量
		v[i] = i;          
	
	sort(road,g.e);       //对所有边进行排序  
	
	for(i = 0; i < g.e; i++)
	{
		a = getRoot(road[i].a);          //使a等于边的始点所在的连通分量
		b = getRoot(road[i].b);          //使b等于边的终点所在的连通分量
		if(a != b)    //如果a、b非同一连通分量
		{
			v[a] = b; //将a并入b
			sum += road[i].w; //权值累计
		}
	}
}

拓扑序列

bool TopologicalSort(Graph G)
{
    InitStack(S);                        //初始化栈,将一开始入度为零的顶点入栈
    int i;
    for(i = 0;i < G.xevnum;++i){
        if(indegree[i] == 0)
            Push(S,i);
    }

    int count = 0;
    while(!IsEmpty(S)){                  //当栈不为空,说明还有顶点可以加入排序
        Pop(S,i);                       
        print[count ++] = i;                //将入度为0的结点放入打印数组中

        for(ArcNode *p = G.vertices[i].firstarc; p; p = p -> nextarc){ //删除顶点i的出边
            v = p -> adjvex;
            if(!(--indegree[v]))         //更新入度为0的数组,将数组内点入栈
                Push(S,v);
        }
    }

    if(count != G.vexnum)
        return false;                    //检查打印数组中元素数是否与图顶点一致
    else
        return true;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值