图的遍历和最小生成树

图的遍历及最小生成树

深度优先搜索

假设初始状态是图中所有顶点未曾被访问,则深度优先搜索可从图中某个顶点v出发,访问此顶点,然后依次从v的未被访问的邻接点出发深度优先遍历图,直至图中所有和v有路径相通的顶点都被访问;若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点.

Boolean visited[MAX];  //访问标志数组
Status(*VisitFunc)(int v); //函数变量

void DFSTraverse(Graph G,Status(*Visit)(int v)){
    /**对图G作深度遍历**/
    VisitFunc = Visit ; //使用全局变量VisitFunc,使DFS不必设函数指针参数
    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))\
        if(!visited[w]) DFS(G,w);
} 

广度优先搜索

假设从图中某顶点v出发,在访问了v之后依次访问v地各个未曾访问过的邻接点,然后分别从这些邻接点出发依次访问它们的邻接点.并使"先被访问的顶点的邻接点"先于"未后被访问的顶点的邻接点"被访问,直至图中所有已被访问的顶点的邻接点都被访问到.若此时图中尚有未被访问到的顶点,则从尚未被访问到的顶点作为起始点,重复上述过程.


void BFS_AM(AMGraph &G,char v0)
{
/*从v0元素开始访问图*/
 
	int u,i,v,w;
	v = LocateVex(G,v0);                            //找到v0对应的下标
	printf("%c ", v0);                              //打印v0
	visited[v] = 1;		                        //顶点v0已被访问
	q.push(v0);			                //将v0入队
 
	while (!q.empty())
	{
		u = q.front();				//将队头元素u出队,开始访问u的所有邻接点
		v = LocateVex(G, u);			//得到顶点u的对应下标
		q.pop();				//将顶点u出队
		for (i = 0; i < G.vexnum; i++)
		{
			w = G.vexs[i];
			if (G.arcs[v][i] && !visited[i])//顶点u和w间有边,且顶点w未被访问
			{
				printf("%c ", w);	//打印顶点w
				q.push(w);		//将顶点w入队
				visited[i] = 1;		//顶点w已被访问
			}
		}
	}
}

最小生成树

在一个连通网的所有生成树中,各边的代价之和最小的那棵生成树称为该连通网的

最小代价生成树(MinimumCost Spanning Tree), 简称为最小生成树

普里姆算法

把顶点分成两个类型:一个已经访问的顶点集合U,一个未访问的顶点集合V-U

在实际运行时,可以通过建立一个visited数组,用true和false来分类两个集合中的顶点。

/**
     * 通过普利姆算法获取图形的最小支撑树
     *
     * @param vertex 普利姆算法的起始顶点
     * @return 返回当前图形的最小支撑树,注意:这要求当前图形是连通图
     */
    public MinTree prim(int vertex) {
        boolean[] visited = new boolean[numberOfVertex];
        Arrays.fill(visited, false);

        // 表示vertex结点已经加入最小支撑树
        visited[vertex] = true;
        MinTree minTree = new MinTree(numberOfVertex);


        // 感觉这个过程还是不太好理解。
        // 注意选择排序的运用
        while (minTree.numberOfMstEdge() < numberOfVertex - 1) {
            MSTEdge edge = getShortestEdge(visited);
            minTree.addMstEdge(edge);
            visited[edge.getEnd()] = true;

        }
        return minTree;
    }

    /**
     * 获取已访问顶点和未访问顶点之间相连的最短边
     * @param visited 辅助遍历数组
     * @return 获取最短边,一端是已经访问的点,一端是未访问的顶点。通过遍历求出最短的边
     */
    private MSTEdge getShortestEdge(boolean[] visited) {
        int minWeight = Integer.MAX_VALUE;
        int minStart = Integer.MAX_VALUE;
        int minEnd = Integer.MAX_VALUE;

        // i 表示已经访问过的集合中的顶点
        for (int i = 0; i < numberOfVertex; i++) {
            // 表示未访问的顶点集合中的顶点
            for (int j = 0; j < numberOfVertex; j++) {
                if (visited[i] && !visited[j] && edges[i][j] < minWeight) {
                    minWeight = edges[i][j];
                    minStart = i;
                    minEnd = j;
                }
            }
        }

        return new MSTEdge(minStart, minEnd, minWeight);
    }


class MinTree {
    ArrayList<MSTEdge> mstEdges;

    public MinTree(int numberOfVertex) {
        mstEdges = new ArrayList<>(numberOfVertex - 1);
    }

    public void show() {
        System.out.println("MinTree.show");
        System.out.println("最小支撑树如下所示:");
        mstEdges.stream()
                .forEach(System.out::println);
    }

    public void addMstEdge(MSTEdge mstEdge)  {
        mstEdges.add(mstEdge);
    }

    public int numberOfMstEdge() {
        return mstEdges.size();
    }
}

class MSTEdge {
    int start;
    int end;
    int weight;

    public MSTEdge(int start, int end, int weight) {
        this.start = start;
        this.end = end;
        this.weight = weight;
    }

    @Override
    public String toString() {
        return "MSTEdge{" +
                "start=" + start +
                ", end=" + end +
                ", weight=" + weight +
                '}';
    }

    public int getEnd() {
        return end;
    }
}

posted @   RigelStar  阅读(47)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示