头歌数据结构与算法——实验三:图

995 阅读5分钟

第一关 图的邻接矩阵创建和DFS

任务描述
本关任务:实现基于邻接矩阵的无向图的创建方法,以及深度优先遍历方法

编程要求
输入
多行数据
第一行是无向图的顶点个数和边个数
第二行是顶点信息
第三行开始是每条边依附的顶点信息

输出
从第一个顶点出发的DFS序列

测试说明
平台会对你编写的代码进行测试:

测试输入:
4 5
A B C D
A B
A C
A D
B C
C D

预期输出:
ABCD
#include <iostream>
#include <cstring> // for memset

using namespace std;

#define MVNum 100

// 定义图的结构体
typedef struct {
    char vexs[MVNum];    // 顶点集  
    int arcs[MVNum][MVNum];        // 邻接矩阵
    int vexnum, arcnum;    // 图当前的顶点数和边数
} AMGraph;

// 查找顶点在顶点表中的下标,若存在返回其下标,否则返回 -1
int LocateVex(AMGraph G, char u) {
    int i;
    for (i = 0; i < G.vexnum; ++i) {
        if (u == G.vexs[i]) {
            return i;
        }
    }
    return -1;
}

void CreateUDN(AMGraph &G, int vexnum, int arcnum) {
    G.vexnum = vexnum;  // 设置顶点数  
    G.arcnum = arcnum;  // 设置边数  
    // 初始化顶点集  
    for (int i = 0; i < G.vexnum; ++i) {
        cin >> G.vexs[i];
    }
    memset(G.arcs, 0, sizeof(G.arcs)); 

    // 读取边的信息并填充邻接矩阵  
    char u, v;
    for (int i = 0; i < G.arcnum; ++i) {
        cin >> u >> v;
        int indexU = LocateVex(G, u);
        int indexV = LocateVex(G, v);  
        if (indexU!= -1 && indexV!= -1) {
            G.arcs[indexU][indexV] = 1;
            G.arcs[indexV][indexU] = 1;
        }
    }
}

bool visited[MVNum] = { false };

void DFS(AMGraph G, int v) {
    cout << G.vexs[v];
    visited[v] = true;

    for (int i = 0; i < G.vexnum; ++i) {
        // 如果顶点 i 与当前顶点 v 相邻(邻接矩阵对应位置为 1)且未被访问
        if (G.arcs[v][i] == 1 &&!visited[i]) {
            DFS(G, i);
        }
    }
}

第二关 图的邻接表创建

任务描述
本关任务:实现基于邻接表的无向图的创建方法

编程要求
输入
多行数据
第一行是无向图的顶点个数和边个数
第二行是顶点信息
第三行开始是每条边依附的顶点信息

输出
从第一个顶点出发的DFS序列

测试说明
平台会对你编写的代码进行测试:

测试输入:
4 5
A B C D
A B
A C
A D
B C
C D

预期输出:
ADCB
#include <iostream>
using namespace std;

#define MVNum 100

typedef struct ArcNode{		//定义边结点
	int adjvex;           //存储邻接点在顶点数组中的下标
	struct ArcNode *nextarc;
}ArcNode;

typedef struct VNode{		//定义顶点结点
	char data;
	ArcNode *firstarc;
}VNode;

typedef struct ALGraph{	        //定义图的结构体类型
	VNode vertices[MVNum];      
	int vexnum, arcnum;	//图当前的顶点数和边数
}ALGraph;


//定位顶点下标
int LocateVex(ALGraph G, char v) 
{
	for (int i = 0; i < G.vexnum; i++) {
		if (G.vertices[i].data == v)
			return i;
	}
	return -1;
}



void insertArcNode(VNode &vnode, int adjvex) {
    ArcNode* newArc = new ArcNode;
    newArc->adjvex = adjvex;
    newArc->nextarc = vnode.firstarc;
    vnode.firstarc = newArc;
}

//采用邻接表,创建无向图G
void CreateUDN(ALGraph &G, int vexnum, int arcnum) 
{
	G.vexnum = vexnum;      //初始化图的总顶点数  
	G.arcnum = arcnum;     //初始化图的总边数  
	for (int i = 0; i < G.vexnum; i++) 
	{	//初始图中的顶点信息
		cin>>G.vertices[i].data;
		G.vertices[i].firstarc = NULL;
	}
	char vex_one, vex_two;	//一条边依附的两个顶点vex_one和vex_two 
	//补全代码,接收边的输入信息,调用insertArcNode函数,将边结点插入到链表中
     for (int i = 0; i < G.arcnum; i++) {
        cin >> vex_one >> vex_two;

        // 定位顶点下标
        int v1 = LocateVex(G, vex_one);
        int v2 = LocateVex(G, vex_two);

        // 插入无向边
        insertArcNode(G.vertices[v1], v2);
        insertArcNode(G.vertices[v2], v1);
    }

}

第三关 K顶点

任务描述
本关任务:在基于邻接矩阵的有向图中寻找k顶点,k顶点即出度大于入度的顶点

编程要求
输入
多行数据
第一行是有向图的顶点个数和弧个数
第二行是顶点信息
第三行开始是每条边依附的顶点信息

输出
所有K顶点的名称,按顶点顺序输出

测试说明
平台会对你编写的代码进行测试:

测试输入:
4 5
A B C D
A B
A D
B C
B D
C D

预期输出:
AB
#include <iostream>
using namespace std;

#define MVNum 100

typedef struct {
	char vexs[MVNum];	//顶点集  
	int arcs[MVNum][MVNum];		//邻接矩阵
	int vexnum, arcnum;	//图当前的顶点数和边数
}AMGraph;

void printKv(AMGraph G)
{
	//按顶点顺序输出所有K顶点
	//在此处填入代码
    int outD[100] = {0};
	int inD[100] = {0};

    for(int i = 0;i < G.vexnum;i++) {
        for(int j = 0;j < G.vexnum;j++) {
            if(G.arcs[i][j] == 1) {
                outD[i]++;
            }
        }
    }
    for(int i = 0;i < G.vexnum;i++) {
        for(int j = 0;j < G.vexnum;j++) {
            if(G.arcs[j][i] == 1) {
                inD[i]++;
            }
        }
    }

    for(int i = 0;i < G.vexnum;i++) {
        if(outD[i] > inD[i]) {
            printf("%c",G.vexs[i]);
        }
    }
}

第四关 有向图路径判断

任务描述
本关任务:在基于邻接表的有向图中,判断顶点i与顶点j之间是否存在路径(i!=j)

编程要求
输入
多行数据
第一行是有向图的顶点个数n和弧个数e
第二行是n个顶点信息
第三行开始,到第e+2行是弧依附的两个顶点信息
第e+3行是要判断是否存在路径的顶点组合个数
第e+4行开始,是顶点名称vi和vj

输出
顶点vi和vj之间是否存在路径

测试说明
平台会对你编写的代码进行测试:

测试输入:
4 4
A B C D
A B
A C
C D
D A
3
A D
D C
B C

"其中,要判断是否存在路径的是AD,DC和BC三组顶点"

预期输出:
Yes
Yes
No

"输出结果表示AD和DC之间存在路径,BC之间不存在路径"
#include <iostream>
using namespace std;

#define MVNum 100

typedef struct ArcNode{		//定义边结点
	int adjvex;           //存储邻接点在顶点数组中的下标
	struct ArcNode *nextarc;
}ArcNode;

typedef struct VNode{		//定义顶点结点
	char data;
	ArcNode *firstarc;
}VNode;

typedef struct ALGraph{	        //定义图的结构体类型
	VNode vertices[MVNum];      
	int vexnum, arcnum;	//图当前的顶点数和边数
}ALGraph;


bool visited[MVNum] = {false};

bool DFS(ALGraph G, int v, int j) {
    if (v == j) {
        return true;
    }
    visited[v] = true;
    ArcNode *p;
    for (p = G.vertices[v].firstarc; p; p = p->nextarc) {
        if (!visited[p->adjvex]) {
            if (DFS(G, p->adjvex, j)) {
                return true;
            }
        }
    }
    return false;
}

int validPath(ALGraph G,int i,int j)
{
	//判断vertices数组中下标为i与j的顶点之间是否存在路径
	//存在路径返回1,不存在返回0
	//请实现此函数
    // 初始化visited数组,将所有元素置为false
    for (int k = 0; k < G.vexnum; k++) {
        visited[k] = false;
    }
    return DFS(G, i, j)? 1 : 0;
	
}