图——邻接矩阵基本操作算法实现

部署运行你感兴趣的模型镜像

一、存储结构

#include <stdio.h>
#include <stdlib.h>
#define INFINT 9999999  //最大int值,即无穷
#define MAXVertexNum 100	//最大顶点数
 
typedef char VerTexType;	//顶点对应的数据类型 
typedef int ArcType;	//边对应的数据类型 

typedef struct{
	VerTexType vexs[MAXVertexNum];	//顶点表
	ArcType arcs[MAXVertexNum][MAXVertexNum];	//邻接矩阵,边表
	int vexnum,arcnum;	//图的当前点数和边数
	bool isUndirected; //记录是否为无向图 
}MGraph;

二、初始化操作

对顶点数和边数初始化为0

同时考虑顶点自身的边数为0

初始所有顶点之间没有变,设为无穷∞

void InitGraph(MGraph &G) {
    int i, j;

    // 设置图的当前顶点数和边数
    G.vexnum = 0;  // 初始化顶点数为0
    G.arcnum = 0;  // 初始化边数为0
	G.isUndirected = 1;   //默认为无向图 

    // 初始化邻接矩阵,将所有边的值设为INFINITY
    for (i = 0; i < MAXVertexNum; i++) {
        for (j = 0; j < MAXVertexNum; j++) {
            if (i == j) {
                G.arcs[i][j] = 0; // 顶点到自身的边为0
            } else {
                G.arcs[i][j] = INFINT;  // 无穷大表示没有边
            }
        }
    }
}

三、插入顶点操作

// 插入顶点函数
void InsertVertex(MGraph &G, VerTexType v) {
    if (G.vexnum >= MAXVertexNum) {
        printf("顶点表已满");
        return;
    }

    // 在顶点数组中插入新顶点
    G.vexs[G.vexnum] = v;
    G.vexnum++;
    return;
}

四、插入边操作

如果是无向图,则ij位置交替再赋值一次

if(G.isUndirected)  G.arcs[j][i] = weight; 

// 插入边函数
int AddEdge(MGraph &G, VerTexType v1, VerTexType v2, ArcType weight=1) {
    int i = -1, j = -1;

    // 查找顶点v1和v2在顶点表中的索引
    for (int k = 0; k < G.vexnum; k++) {
        if (G.vexs[k] == v1) {
            i = k;
        }
        if (G.vexs[k] == v2) {
            j = k;
        }
    }

    // 如果找到顶点v1和v2
    if (i != -1 && j != -1) {
        G.arcs[i][j] = weight;  // 插入边,v1 -> v2
        if(G.isUndirected)  G.arcs[j][i] = weight;  // 如果是无向图,插入边,v2 -> v1
        G.arcnum++;
        return 1; 
    } else {
        printf("顶点不存在");
        return 0;
    }
}

五、输出查看邻接矩阵

// 查看邻接矩阵的函数
void DisplayAdjMatrix(MGraph &G) {
    int i, j;

    // 打印顶点
    printf("顶点表");
    printf("   ");
    for (i = 0; i < G.vexnum; i++) {
        printf("%c ", G.vexs[i]);
    }
    printf("\n");

    // 打印邻接矩阵
    for (i = 0; i < G.vexnum; i++) {
        printf("%c: ", G.vexs[i]);
        for (j = 0; j < G.vexnum; j++) {
            if (G.arcs[i][j] == INFINT) {
                printf("INF ");
            } else {
                printf("%d ", G.arcs[i][j]);
            }
        }
        printf("\n");
    }
}

六、主函数

int main() {

//=====================================================
//无向图
//========
    MGraph G;  // 创建一个图
    InitGraph(G);  // 初始化图

    // 插入顶点
    InsertVertex(G, 'A');
    InsertVertex(G, 'B');
    InsertVertex(G, 'C');
    InsertVertex(G, 'D');
    InsertVertex(G, 'E');

    // 插入边
    InsertEdge(G, 'A', 'B');  
    InsertEdge(G, 'A', 'D');  
    InsertEdge(G, 'A', 'C');  
    InsertEdge(G, 'B', 'E');  
    InsertEdge(G, 'C', 'D');  
    DisplayAdjMatrix(G);
    return 0;
//=====================================================


}

 七、判断图是否存在边<x,y>或(y,x)

有向图和无向图算法一致

// 判断图是否存在边<x,y>或(y,x)
int Adjacent(MGraph G, VerTexType x, VerTexType y) {
    int i = -1, j = -1;
    
    // 查找顶点 x 和 y 的索引
    for (int k = 0; k < G.vexnum; k++) {
        if (G.vexs[k] == x) i = k;
        if (G.vexs[k] == y) j = k;
    }

    // 如果顶点存在并且存在边
    if (i != -1 && j != -1 && (G.arcs[i][j] != INFINT || G.arcs[j][i] != INFINT)) {
        return 1; // 存在边
    }
    return 0; // 不存在边
}

 八、列出图中节点 x 的邻接的边

考虑有向图的入边邻接点

// 列出图中节点 x 的邻接的边 
void Neighbors(MGraph G, VerTexType x) {
    int i = -1;

    // 查找顶点 x 的索引
    for (int k = 0; k < G.vexnum; k++) {
        if (G.vexs[k] == x) {
            i = k;
            break;
        }
    }

    if (i == -1) {
        printf("顶点 %c 不存在\n", x);
        return;
    }

    // 输出与顶点 x 相邻的所有顶点
    printf("顶点 %c 的邻接的边: ", x);
    for (int j = 0; j < G.vexnum; j++) {
        if (G.arcs[i][j] != INFINT && i != j) {
        	if(G.isUndirected==1) printf("(%c,%c) ", G.vexs[i],G.vexs[j]);
        	if(G.isUndirected==0) printf("<%c,%c> ", G.vexs[i],G.vexs[j]);
        }
        else (G.isUndirected==0 && G.arcs[j][i] != INFINT && i != j) { //考虑有向图的入边邻接点 
            printf("<%c,%c>", G.vexs[j],G.vexs[i]);
        }
    }
    printf("\n");
}

九、删除顶点操作

DeleteVertex(G,c) 在图中删除顶点x

有向图比无向图操作略有增加,主要体现在计算边数的时候

将图分成四块区域

按象限顺序,第二象限为不动组,

第一象限和第三象限为左移或上移一格组,

第四象限为先上移再左移组

操作示意图如下

// 删除顶点函数
void DeleteVertex(MGraph &G, VerTexType c) {
    int i, j;

    // 查找顶点 c 的索引
    for (i = 0; i < G.vexnum; i++) {
        if (G.vexs[i] == c) break;
    }

    if (i == G.vexnum) {
        printf("顶点 %c 不存在\n", c);
        return;
    }

    // 删除顶点 c 对应的行和列
    for (j = 0; j < G.vexnum - 1; j++) {
        G.vexs[j+i] = G.vexs[j + i + 1];
        for (int k = i; k < G.vexnum; k++) {
        	if(j<i) {
        		if(j<i && k==i && (G.arcs[j][k]!=INFINT && G.arcs[j][k]!=0)) G.arcnum--;
				
				// 如果是有向图,则需要判断双向         		
				if(G.isUndirected==0 &&j<i && k==i && (G.arcs[k][j]!=INFINT && G.arcs[k][j]!=0)) G.arcnum--;
        		
				G.arcs[j][k] = G.arcs[j][k+1];
        		G.arcs[k][j] = G.arcs[k+1][j];
			}
			if(j>=i){
				if(j==i && (G.arcs[j][k+1]!=INFINT && G.arcs[j][k+1]!=0)) G.arcnum--;
				
				//如果是有向图,则需要判断双向 
				if(G.isUndirected==0 && j==i && (G.arcs[k+1][j]!=INFINT && G.arcs[k+1][j]!=0)) G.arcnum--;
				if(G.isUndirected==0 && j==i && k==G.vexnum-1 && (G.arcs[k+1][j]!=INFINT && G.arcs[k+1][j]!=0)) G.arcnum--;
	            
				G.arcs[j][k+1] = G.arcs[j + 1][k+1];
	            G.arcs[j][k] = G.arcs[j][k+1];
	    	}
        }
    }

    G.vexnum--;
    
}

十、删除边操作

如果是无向图,则ij位置交替再删除一次,即删除两个方向的边

if(G.isUndirected)  G.arcs[j][i] = INFINT;

// 删除边函数
void RemoveEdge(MGraph &G, VerTexType x, VerTexType y) {
    int i = -1, j = -1;

    // 查找顶点 x 和 y 的索引
    for (int k = 0; k < G.vexnum; k++) {
        if (G.vexs[k] == x) i = k;
        if (G.vexs[k] == y) j = k;
    }

    if (i != -1 && j != -1) {
        G.arcs[i][j] = INFINT;
        if(G.isUndirected)  G.arcs[j][i] = INFINT; // 无向图需要删除两个方向的边
        G.arcnum--;
    } else {
        printf("边 (%c, %c) 不存在\n", x, y);
    }
}

 十一、求顶点 x 的第一个邻接点

求图中顶点x的第一个邻接点,若有则返回定点好,若x没有邻接点或图中不存在x,则返回-1

// 求顶点 x 的第一个邻接点
int FirstNeighbor(MGraph G, VerTexType x) {
    int i = -1;

    // 查找顶点 x 的索引
    for (int k = 0; k < G.vexnum; k++) {
        if (G.vexs[k] == x) {
            i = k;
            break;
        }
    }

    if (i == -1) {
        printf("顶点 %c 不存在\n", x);
        return -1;
    }

    // 查找第一个邻接点
    for (int j = 0; j < G.vexnum; j++) {
        if (G.arcs[i][j] != INFINT && i != j) {
            return j; // 返回邻接点的索引
        }
        
        //如果是有向图,第一个邻接点可能源自于入边 
        if (G.isUndirected==0 &&G.arcs[j][i] != INFINT && i != j) {
            return j; // 返回邻接点的索引
        }        
    }
    return -1; // 没有邻接点
}

十二、求顶点 x 的下一个邻接点 

假设图中顶点y是顶点x的一个邻接点,返回除y外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,则返回-1 

// 求顶点 x 的下一个邻接点
int NextNeighbor(MGraph G, VerTexType x, VerTexType y) {
    int i = -1, j = -1;

    // 查找顶点 x 和 y 的索引
    for (int k = 0; k < G.vexnum; k++) {
        if (G.vexs[k] == x) i = k;
        if (G.vexs[k] == y) j = k;
    }

    if (i == -1 || j == -1) {
        printf("顶点 %c 或 %c 不存在\n", x, y);
        return -1;
    }

    // 查找下一个邻接点
    for (int k = j + 1; k < G.vexnum; k++) {
        if (G.arcs[i][k] != INFINT && i != k) {
            return k;
        }
		 
        //如果是有向图,则下一个邻接点可能源自于入边 
        if (G.isUndirected==0 && G.arcs[k][i] != INFINT && i != k) {
            return k;
        }
    }

    return -1; // 没有下一个邻接点
}

十三、获取边的权值

// 获取边的权值
ArcType Get_edge_value(MGraph G, VerTexType x, VerTexType y) {
    int i = -1, j = -1;

    // 查找顶点 x 和 y 的索引
    for (int k = 0; k < G.vexnum; k++) {
        if (G.vexs[k] == x) i = k;
        if (G.vexs[k] == y) j = k;
    }

    if (i != -1 && j != -1) {
        return G.arcs[i][j];
    }

    printf("边 (%c, %c) 不存在\n", x, y);
    return -1;
}

十四、设置边的权值

// 设置边的权值
void Set_edge_value(MGraph &G, VerTexType x, VerTexType y, ArcType v) {
    int i = -1, j = -1;

    // 查找顶点 x 和 y 的索引
    for (int k = 0; k < G.vexnum; k++) {
        if (G.vexs[k] == x) i = k;
        if (G.vexs[k] == y) j = k;
    }

    if (i != -1 && j != -1) {
        G.arcs[i][j] = v;
        if(G.isUndirected)  G.arcs[j][i] = v;  // 无向图需设置两个方向
    } else {
        printf("边 (%c, %c) 不存在\n", x, y);
    }
}

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值