邻接表、邻接矩阵(考研)--------王道

 邻接表:

 代码:(理解了一遍)

数组(静态链表)

#include <iostream>
#inclue  <cstring>
#include <algorithm>
using namespace std;
const int N=10010,M=N*2;
//因为有N个头节点所以定义N个数组,单链表可以直接int h
int h[N],e[M],ne[M],idx;
void add(int a,int b){
//插入操作即在h[a]头结点后插入节点b
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
int main(){
//初始化让所有的头结点指向空节点(下标为-1)
memset(h,-1,sizeof h);
}

结构体:

#define MaxVertexNum 100
typedef char vertexType ;//顶点中存字符类型数据
 
/*边表节点*/
typedef struct ArcNode{
	int adjvex;//弧指向的顶点下标
	struct ArcNode *next;//指向下一条弧的指针
}ArcNode;
 
/*顶点表节点*/
typedef struct VNode {
	vertexType data;//顶点信息(char)
	ArcNode* first;//指向第一个依附该顶点的弧的指针
}VNode,AdjList[MaxVertexNum];
 
/*图*/
typedef struct {
	AdjList vertices;
	int vecnum, arcnum;
}ALGraph;
 
void create(ALGraph *G) {
	cout << "-----------------------------------------------------" << endl;
	cout << "请输入顶点数和边数" << endl;
	cin >> G->vecnum >> G->arcnum;
	cout << "请输入顶点" << endl;
 
	for (int i = 0; i < G->vecnum; i++) {
		cin >> G->vertices[i].data;
		G->vertices[i].first = NULL;
	}
 
	cout << "请输入边(Vi,Vj)的下标i,j"<<endl;
	int i, j;
	ArcNode* p;
	for (int k = 0; k < G->arcnum; k++) {	
                cin>>i>>j;
		p = (ArcNode*)malloc(sizeof(ArcNode));//创建新的边表结点
        //adjvex弧指向节点的下标
		p->adjvex = j;
        //p->next是指向下一条弧的指针
		p->next = G->vertices[i].first;//头插法
        //该顶点依附的第一条边就是p
		G->vertices[i].first = p;
 
		/*如果是无向图还应该加入下面这一段*/
		p = (ArcNode*)malloc(sizeof(ArcNode));
        //adjvex弧指向节点的下标
		p->adjvex = i;
		p->next = G->vertices[j].first;
		G->vertices[j].first = p;
	}
 
	cout << "邻接表如下:" << endl;
    //vecnum顶点的个数
	for (int i = 0; i < G->vecnum; i++) {
        //p是边表节点
		p = G->vertices[i].first;
		while (p)
		{
			cout <<"<"<< G->vertices[i].data << ","<<G->vertices[p->adjvex].data<<"> ";
            //p->next是指向下一条弧的指针
			p = p->next;
		}
		cout << endl;
	}
	cout << "-----------------------------------------------------" << endl;
}
int main()
{
	ALGraph G;
	create(&G);
}

 

邻接矩阵

代码:

//邻接矩阵
#include<stdio.h>
#include<stdlib.h>
#define Status int
#define OVERFLOW -2
#define OK 1
#define ERROR -1
//邻阶矩阵
#define MaxInt 32767
#define MVNum 100
typedef char VerTexType;//顶点的数据类型
typedef int ArcType;//边的权值类型
typedef struct
{
	VerTexType vexs[MVNum];//顶点表
	ArcType arcs[MVNum][MVNum];//邻阶矩阵
	int vexnum,arcnum;//图当前的点数和边数
}AMGraph;
int LocateVex(AMGraph &G,char v)
{
	for(int i=0;i<G.vexnum;i++)
	{
		if(v==G.vexs[i])
			return i;
	}
}
Status CreateUDN(AMGraph &G)
{
	char v1,v2;int w;int j;
	scanf("%d %d",&G.vexnum,&G.arcnum);//输入总顶点数,总边数
	for(int i=0;i<G.vexnum;++i)
	{
		scanf(" %c",&G.vexs[i]);//printf("bbb\n");
	}
	for(i=0;i<G.vexnum;++i)//初始化邻阶矩阵,边的权值均置为极大值MaxInt
	{
		for(j=0;j<G.vexnum;++j)
		{
			G.arcs[i][j]=MaxInt;//printf("aaa\n");
		}
	}
	for(int k=0;k<G.arcnum;++k)//构造邻阶矩阵
	{
		scanf(" %c %c %d",&v1,&v2,&w);
		i=LocateVex(G,v1);
		j=LocateVex(G,v2);
		G.arcs[i][j]=w;
		G.arcs[j][i]=G.arcs[i][j];
	}
	return OK;
}
int main()
{
	AMGraph G;
	CreateUDN(G);
	printf("%d\n",G.arcs[1][2]);//为测试而输出
	return 0;
}

Floyd算法基于邻接矩阵:

详细题解:

https://blog.csdn.net/qq_52934831/article/details/120013082

代码:

#include <iostream>  
#include <iomanip>  
#include <string>  
using namespace std;  
  
#define INFINITY 65535//无边时的权值  
#define MAX_VERTEX_NUM 10//最大顶点数  
  
typedef struct MGraph{  
    string vexs[10];//顶点信息  
    int arcs[10][10];//邻接矩阵  
    int vexnum, arcnum;//顶点数和边数  
}MGraph;  
  
int LocateVex(MGraph G, string u)//返回顶点u在图中的位置  
{  
    for(int i=0; i<G.vexnum; i++)  
        if(G.vexs[i]==u)  
            return i;  
    return -1;  
}  
  
void CreateDN(MGraph &G)//构造有向网  
{  
    string v1, v2;  
    int w;  
    int i, j, k;  
    cout<<"请输入顶点数和边数:";  
    cin>>G.vexnum>>G.arcnum;  
  
    cout<<"请输入顶点:";  
    for(i=0; i<G.vexnum; i++)  
        cin>>G.vexs[i];  
  
    for(i=0; i<G.vexnum; i++)  
        for(j=0; j<G.vexnum; j++)  
            G.arcs[i][j]=INFINITY;  
  
    cout<<"请输入边和权值:"<<endl;  
    for(k=0; k<G.arcnum; k++)  
    {  
        cin>>v1>>v2>>w;  
        i=LocateVex(G, v1);  
        j=LocateVex(G, v2);  
        G.arcs[i][j]=w;  
    }  
}  
  
//迪杰斯特拉算法求有向网G的v0顶点到其余顶点v的最短路径p[v]及带权长度D[v]  
//p[][]=-1表示没有路径,p[v][i]存的是从v0到v当前求得的最短路径经过的第i+1个顶点(这是打印最短路径的关键),则v0到v的最短路径即为p[v][0]到p[v][j]直到p[v][j]=-1,路径打印完毕。  
//final[v]为true当且仅当v∈S,即已经求得从v0到v的最短路径。  
void ShortestPath_DIJ(MGraph G, int v0, int p[][MAX_VERTEX_NUM], int D[])  
{  
    int v, w, i, j, min;  
    bool final[10];  
      
    for(v=0; v<G.vexnum; v++)  
    {  
        final[v]=false;//设初值  
        D[v]=G.arcs[v0][v];//D[]存放v0到v得最短距离,初值为v0到v的直接距离  
        for(w=0; w<G.vexnum; w++)  
            p[v][w]=-1;//设p[][]初值为-1,即没有路径  
        if(D[v]<INFINITY)//v0到v有直接路径  
        {  
            p[v][0]=v0;//v0到v最短路径经过的第一个顶点  
            p[v][1]=v;//v0到v最短路径经过的第二个顶点  
        }  
    }  
      
    D[v0]=0;//v0到v0距离为0  
    final[v0]=true;//v0顶点并入S集  
      
    for(i=1; i<G.vexnum; i++)//其余G.vexnum-1个顶点  
    {//开始主循环,每次求得v0到某个顶点v的最短路径,并将v并入S集,然后更新p和D  
        min=INFINITY;  
        for(w=0; w<G.vexnum; w++)//对所有顶点检查  
            if(!final[w] && D[w]<min)//在S集之外(即final[]=false)的顶点中找离v0最近的顶点,将其赋给v,距离赋给min  
            {  
                v=w;  
                min=D[w];  
            }  
            final[v]=true;//v并入S集  
            for(w=0; w<G.vexnum; w++)//根据新并入的顶点,更新不在S集的顶点到v0的距离和路径数组  
            {  
                if(!final[w] && min<INFINITY && G.arcs[v][w]<INFINITY && (min+G.arcs[v][w]<D[w]))  
                {//w不属于S集且v0->v->w的距离<目前v0->w的距离  
                    D[w]=min+G.arcs[v][w];//更新D[w]  
                    for(j=0; j<G.vexnum; j++)//修改p[w],v0到w经过的顶点包括v0到v经过的所有顶点再加上顶点w  
                    {  
                        p[w][j]=p[v][j];  
                        if(p[w][j]==-1)//在p[w][]第一个等于-1的地方加上顶点w  
                        {  
                            p[w][j]=w;  
                            break;  
                        }  
                    }                     
                      
                }  
            }  
    }     
}  
  
void main()  
{  
    int i, j;  
    MGraph g;  
    CreateDN(g);  
    int p[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//最短路径数组p  
    int D[MAX_VERTEX_NUM];//最短距离数组D  
    ShortestPath_DIJ(g, 0, p, D);  
      
    cout<<"最短路径数组p[i][j]如下:"<<endl;  
    for(i=0; i<g.vexnum; i++)  
    {  
        for(j=0; j<g.vexnum; j++)  
            cout<<setw(3)<<p[i][j]<<" ";  
        cout<<endl;  
    }  
  
    cout<<g.vexs[0]<<"到各顶点的最短路径及长度为:"<<endl;  
    for(i=0; i<g.vexnum; i++)  
    {  
        if(i!=0 && D[i]!=INFINITY)  
        {  
            cout<<g.vexs[0]<<"-"<<g.vexs[i]<<"的最短路径长度为:"<<D[i];  
            cout<<"  最短路径为:";  
            for(j=0; j<g.vexnum; j++)  
            {  
                if(p[i][j]>-1)  
                    cout<<g.vexs[p[i][j]]<<" ";  
            }  
            cout<<endl;             
        }  
        else if(D[i]==INFINITY)  
            cout<<g.vexs[0]<<"-"<<g.vexs[i]<<":"<<"不可达"<<endl;  
    }  
  
}  

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值