用C语言写一段代码,有向无权图的增删改查,用邻接矩阵存储,可以从文件读取数据 并进行键盘操作
时间: 2023-12-21 16:07:19 浏览: 74
以下是一个简单的有向无权图的增删改查程序,使用邻接矩阵存储方式,可以从文件中读取数据,并进行键盘操作。代码中使用了图的遍历算法来实现图的遍历和查询功能。
```c
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX_VERTEX_NUM 100 //最大顶点数
typedef struct Graph{
int vertex[MAX_VERTEX_NUM]; //存储顶点
int edge[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //存储边
int vertex_num; //顶点数
int edge_num; //边数
}Graph;
//初始化图
void init(Graph *g){
g->vertex_num = 0;
g->edge_num = 0;
for(int i=0;i<MAX_VERTEX_NUM;i++){
g->vertex[i] = 0;
for(int j=0;j<MAX_VERTEX_NUM;j++){
g->edge[i][j] = 0;
}
}
}
//添加顶点
void add_vertex(Graph *g, int v){
g->vertex[g->vertex_num++] = v;
}
//添加边
void add_edge(Graph *g, int v1, int v2){
g->edge[v1][v2] = 1;
g->edge_num++;
}
//删除顶点
void delete_vertex(Graph *g, int v){
for(int i=0;i<g->vertex_num;i++){
if(g->vertex[i] == v){
for(int j=0;j<g->vertex_num;j++){
g->edge[i][j] = 0;
g->edge[j][i] = 0;
}
g->vertex[i] = 0;
g->vertex_num--;
for(int k=i;k<g->vertex_num;k++){
g->vertex[k] = g->vertex[k+1];
for(int j=0;j<g->vertex_num;j++){
g->edge[k][j] = g->edge[k+1][j];
g->edge[j][k] = g->edge[j][k+1];
}
}
}
}
}
//删除边
void delete_edge(Graph *g, int v1, int v2){
g->edge[v1][v2] = 0;
g->edge_num--;
}
//遍历图
void dfs(Graph *g, int v, bool visited[]){
visited[v] = true;
printf("%d ", g->vertex[v]);
for(int i=0;i<g->vertex_num;i++){
if(g->edge[v][i] == 1 && !visited[i]){
dfs(g, i, visited);
}
}
}
//查询顶点
int search_vertex(Graph *g, int v){
for(int i=0;i<g->vertex_num;i++){
if(g->vertex[i] == v){
return i;
}
}
return -1;
}
//从文件中读取数据
void read_data(Graph *g, char *filename){
FILE *fp = fopen(filename, "r");
if(fp == NULL){
printf("文件打开失败!\n");
return;
}
int v1, v2;
while(fscanf(fp, "%d %d", &v1, &v2) != EOF){
if(search_vertex(g, v1) == -1){
add_vertex(g, v1);
}
if(search_vertex(g, v2) == -1){
add_vertex(g, v2);
}
add_edge(g, search_vertex(g, v1), search_vertex(g, v2));
}
fclose(fp);
}
int main(){
Graph g;
init(&g);
read_data(&g, "data.txt");
int choice, v1, v2, v;
bool visited[MAX_VERTEX_NUM] = {false};
while(1){
printf("\n1. 添加顶点\n");
printf("2. 添加边\n");
printf("3. 删除顶点\n");
printf("4. 删除边\n");
printf("5. 遍历图\n");
printf("6. 退出程序\n");
printf("请选择操作:");
scanf("%d", &choice);
switch(choice){
case 1:
printf("请输入顶点:");
scanf("%d", &v);
add_vertex(&g, v);
break;
case 2:
printf("请输入边的两个顶点:");
scanf("%d %d", &v1, &v2);
add_edge(&g, search_vertex(&g, v1), search_vertex(&g, v2));
break;
case 3:
printf("请输入要删除的顶点:");
scanf("%d", &v);
delete_vertex(&g, search_vertex(&g, v));
break;
case 4:
printf("请输入要删除的边的两个顶点:");
scanf("%d %d", &v1, &v2);
delete_edge(&g, search_vertex(&g, v1), search_vertex(&g, v2));
break;
case 5:
printf("遍历结果:");
for(int i=0;i<g.vertex_num;i++){
if(!visited[i]){
dfs(&g, i, visited);
}
}
printf("\n");
for(int i=0;i<g.vertex_num;i++){
visited[i] = false;
}
break;
case 6:
printf("程序已退出!\n");
exit(0);
default:
printf("输入错误,请重新输入!\n");
break;
}
}
return 0;
}
```
注意事项:
1. 程序中使用了一个 `search_vertex` 函数来查找顶点在邻接矩阵中的索引,如果顶点不存在则返回 -1。
2. 程序中使用了一个 `visited` 数组来记录顶点是否已经被访问过,用于遍历图时的判断。遍历完成后需要将 `visited` 数组重新初始化为 `false`。
3. 程序中读取数据的函数中使用了 `fscanf` 函数来从文件中读取数据,文件格式为每行两个整数,表示一条边的两个顶点。
阅读全文