数据结构图的实现(邻接矩阵法和邻接表法)

目录

一、邻接矩阵法

1.结构体

2.操作函数

1)邻接矩阵法创建图

2)获取内容为e的结点下标

3)插入顶点

4)删除顶点v

5)找到v的第一个邻接点

6)找到v除了w后第一个邻接点

7)图的遍历

a.深度优先遍历

b.广度优先搜索,使用队列

8)基于BFS的单源最短路径

9)prim算法

10)kruskal算法

11)dijkstra求单源最短路径

12)floyd算法最短路径

13)拓扑排序

二、邻接表法

1.结构体

2.操作函数

1)返回顶点u的下标

2)创建邻接表

3)求顶点x的第一个邻接点

4)顶点v除去w后第一个邻接点

5)拓扑排序

6)图的遍历

a.广度优先遍历

b.深度优先遍历

三、其他存储结构

1.十字链表法  ------只针对有向图

2.邻接多重表 ---只针对无向图


一、邻接矩阵法

1.结构体

typedef struct{
    VertexType Vex[MaxVertexNum]; //顶点表
    int Edge[MaxVertexNum][MaxVertexNum]; //邻接矩阵,边表  如果带权图,就使用int类型
    int vexnum,arcnum;//当前的顶点数和边数
}MGraph;

2.操作函数

1)邻接矩阵法创建图

void CreatMGraph(MGraph &G,int i)  //i:0 无向图不带权值  1 无向带权  2 有向不带权  3 有向带权
{
    int v,e;
    cout<<"请输入顶点数和边数"<<endl;
    cin>>v>>e;
    G.vexnum=v;
    G.arcnum=e;
    cout<<"请输入顶点信息"<<endl;
    for (int i=0;i<G.vexnum;i++) {
        cin>>G.Vex[i];
    }
    for (int i=0;i<G.vexnum;i++) {
        for(int j=0;j<G.vexnum;j++){
            G.Edge[i][j]=INF;
        }
    }
    if(i==0){
        cout<<"请输入边的两端顶点值"<<endl;
        for (int i=0;i<G.arcnum;i++) {
                VertexType v1,v2;
                cin>>v1>>v2;
                int a1=GetIndexByElem(G,v1);
                int a2=GetIndexByElem(G,v2);
                G.Edge[a1][a2]=1;
                G.Edge[a2][a1]=1;
    }
    if(i==1){
        cout<<"请输入边的两端顶点值和权值"<<endl;
        for (int i=0;i<G.arcnum;i++) {
                VertexType v1,v2;
                int cost;
                cin>>v1>>v2>>cost;
                int a1=GetIndexByElem(G,v1);
                int a2=GetIndexByElem(G,v2);
                G.Edge[a1][a2]=cost;
                G.Edge[a2][a1]=cost;
        }
    }
    
        }
     if(i==2){
            cout<<"请输入弧尾到弧头"<<endl;
            for (int i=0;i<G.arcnum;i++) {
                    VertexType v1,v2;
                    cin>>v1>>v2;
                    int a1=GetIndexByElem(G,v1);
                    int a2=GetIndexByElem(G,v2);
                    G.Edge[a1][a2]=1;
        }
            }
         if(i==3){
                cout<<"请输入弧尾到弧头以及权值"<<endl;
                for (int i=0;i<G.arcnum;i++) {
                        VertexType v1,v2;
                        int w;
                        cin>>v1>>v2>>w;
                        int a1=GetIndexByElem(G,v1);
                        int a2=GetIndexByElem(G,v2);
                        G.Edge[a1][a2]=w;
            }


            }

}

2)获取内容为e的结点下标

int GetIndexByElem(MGraph G,VertexType e)
{
    //只用去顶点表遍历即可
    for (int i=0;i<G.vexnum;i++) {
        if(e==G.Vex[i]){
            return i;
        }
    }
    return -1;
}

3)插入顶点

bool InsertVex(MGraph &G)
{
    cout<<"请输入你要插入的顶点信息以及与其相关的边条数"<<endl;
    VertexType v;
    int e;
    cin>>v>>e;
    G.vexnum++;
    G.arcnum+=e;
    //vexnum-1为下标
    G.Vex[G.vexnum-1]=v;
    for (int i=0;i<G.vexnum;i++) {
        //行初始为0
        G.Edge[G.vexnum-1][i]=0;
        //列初始为0
        G.Edge[i][G.vexnum-1]=0;
    }
    cout<<"请输入该顶点相邻的顶点值"<<endl;
    for (int i=0;i<e;i++) {
        VertexType v1,v2;
        cin>>v1>>v2;
        int index1 = GetIndexByElem(G,v1);
        int index2 = GetIndexByElem(G,v2);
        G.Edge[index1][index2]=1;
        G.Edge[index2][index1]=1;
    }
    return true;

}

4)删除顶点v

bool DeleteVex(MGraph &G,VertexType v)
{
    //更新边表
    for (int i=GetIndexByElem(G,v);i<G.vexnum-1;i++) {
        for (int j=0;j<G.vexnum;j++) {
            G.Edge[i][j]=G.Edge[i+1][j];
            G.Edge[j][i]=G.Edge[i][j];
        }
    }
    //更新顶点表
    for (int i=GetIndexByElem(G,v);i<G.vexnum-1;i++) {
            G.Vex[i]=G.Vex[i+1];

    }
     G.vexnum--;
     return 1;
}

5)找到v的第一个邻接点

int FirstNeighbor(MGraph G, int v)
{
        int k;
        for(k=1;k<=G.vexnum;k++)
        {
            if(G.Edge[v][k]==1)
                break;
        }
        if(k<=G.vexnum)
            return k;
        else
            return -1;
}

6)找到v除了w后第一个邻接点

int NextNeighbor(MGraph G, int v, int w)
{
        int j;
        for(j=w+1;j<=G.vexnum;j++)
        {
            if(G.Edge[v][j]==1)
                break;
        }
        if(j<=G.vexnum)
            return j;
        else
            return -1;
}

7)图的遍历

a.深度优先遍历
void DFS(MGraph G, int i)
{
     visit(G,i);
     visited[i]=1;
     for (int w=FirstNeighbor(G,i);w>=0;w=NextNeighbor(G,i,w)) {
         if(!visited[w])
             DFS(G,w);
     }
}

void DFSTraverse(MGraph G)
{
  for (int i = 0; i < G.vexnum; i++)
         visited[i] = 0;     //初始化所有顶点都为未访问

        for (int i = 0; i < G.vexnum; i++)
            if (!visited[i])
                DFS(G, i);
}
b.广度优先搜索,使用队列
void BFS(MGraph G, int v)
{
    visit(G,v);
    visited[v]=1;

    EnLinkQueue(Q,v);

    while (!LinkQueueEmpty(Q)) {
       DeLinkQueue(Q,v);
        for (int w = FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w)) {
            if(!visited[w]){
                visit(G,w);
                visited[w]=1;
                EnLinkQueue(Q,w);
            }
        }
    }
}

void BFSTraverse(MGraph G)
{
    for(int i=0;i<G.vexnum;i++){
        visited[i]=0;
    }
    InitLinkQueue(Q);

    for(int i=0;i<G.vexnum;i++){
        if(!visited[i])
            BFS(G,i);
    }
}

8)基于BFS的单源最短路径

int D[];
int path[];
void BFS_MIN_Distance(MGraph G, int u)
{
    for(int i=0;i<G.vexnum;i++){
        D[i]=INF;
      path[i]=-1;
    }

    visited[u]=true;
    D[u]=0;

    EnLinkQueue(Q,u);

     while (!LinkQueueEmpty(Q)) {
     DeLinkQueue(Q,u);
     for (int w = FirstNeighbor(G,u);w>=0;w=NextNeighbor(G,u,w)) {
           if(!visited[w]){
                visit(G,w);
               visited[w]=1;
               D[w]=D[u]+1;
               path[w]=u;
               EnLinkQueue(Q,w);
              }
          }
      }

}

9)prim算法

void Prim(MGraph G, int v, int &sum)
{
    int *lowcost=(int *)malloc(sizeof(int)*G.vexnum);
    int *vset=(int *)malloc(sizeof(int)*G.vexnum);
    int i,j,k,min;


    for (i=0;i<G.vexnum;i++) {
        lowcost[i]=G.Edge[v][i];
        vset[i]=0;
    }
    vset[v]=1;
    sum=0;

    for (i=0;i<G.vexnum-1;i++) {
        min=999999;
        for (j=0;j<G.vexnum;j++) {
            if(vset[j]==0&&lowcost[j]<min){
                min=lowcost[j];
                k=j;
            }
        }

        vset[k]=1;
        sum+=min;

        for (j=0;j<G.vexnum;j++) {
            if(vset[j]==0&&G.Edge[k][j]<lowcost[j]){
                lowcost[j]=G.Edge[k][j];
            }
        }
    }

}

10)kruskal算法

void getroad(MGraph g)
{
    int index = 0;
    for (int i=0;i<g.vexnum;i++) {
        for (int j=0;j<i;j++) {
            if(g.Edge[i][j]!=INF){
                roads[index].a=i;
                roads[index].b=j;
                roads[index].w=g.Edge[i][j];
                index++;
            }
        }
    }
}

void kruskal(MGraph G, int &sum, Road1 *road)
{
    for (int i=0;i<G.vexnum;i++) {
        v[i]=i;
    }

    sum=0;
    quicksort(road,0,G.arcnum-1);

    for (int i=0;i<G.arcnum;i++) {
        int av=getroot(road[i].a);
        int bv=getroot(road[i].b);
        if(av!=bv){
            v[av]=bv;
            sum+=road[i].w;
        }

    }
}

11)dijkstra求单源最短路径

void dijkstra(MGraph G, int v, int *dist, int* path1)
{
     int *set=(int*)malloc(sizeof(int)*G.vexnum);
     for (int i=0;i<G.vexnum;i++) {
         dist[i]=G.Edge[v][i];
         set[i]=0;

         if(G.Edge[v][i]!=INF){
             path1[i]=v;
         }
         else {
             path1[i]=-1;
         }
     }
     set[v]=1;
     path1[v]=-1;
     int u;
     for (int i=0;i<G.vexnum-1;i++) {
         int min=INF;
          u=-1;
         for (int j=0;j<G.vexnum;j++) {
             if(set[j]==0&&min>dist[j])
                 min=dist[j],u=j;

         }
     }
     set[u]=1;
     for (int j=0;j<G.vexnum;j++) {
         if(set[j]==0&&dist[j]>dist[u]+G.Edge[u][j]){
             dist[j]=dist[u]+G.Edge[u][j];
             path1[j]=u;
         }
     }
     free(set);
}

12)floyd算法最短路径

void floyd(MGraph G, int path[][20], int dist[][20])
{
    for (int i=0;i<G.vexnum;i++) {
        for (int j=0;j<G.vexnum;j++) {
            dist[i][j]=G.Edge[i][j];
            path[i][j]=-1;
        }
    }
    for (int k=1;k<G.vexnum;k++) {
        for (int i=0;i<G.vexnum;i++) {
            for (int j=0;j<G.vexnum;j++) {
                if(dist[i][j]>dist[i][k]+dist[k][j]){
                    dist[i][j]=dist[i][k]+dist[k][j];
                    path[i][j]=k;
                }
            }
        }
    }
}

13)拓扑排序

int *   GetIndegree(MGraph &G)
{
    int *indegree=(int*)malloc(sizeof (int)*G.vexnum);
    for (int i=0;i>G.vexnum;i++) {
        indegree[i]=0;
    }
    for (int i=0;i<G.vexnum;i++) {
        for (int j=0;j<G.vexnum;j++) {
            if(G.Edge[i][j]!=0)
                indegree[i]++;
        }
    }
    return indegree;
}
SqStack s;
bool topSort(MGraph &G)
{
    int count;
    int *indegree=GetIndegree(G);
    InitStack(s);
    for (int i=0;i<G.vexnum;i++) {
        if(indegree[i]==0)
            push(s,i);
    }
    while (StackEmpty(s)) {
        count++;
        int v;
        pop(s,v);
        cout<<v+1<<" ";
        for (int i=0;i<G.vexnum;i++) {
            if(G.Edge[v][i]==1)
                indegree[i]--;
            if(indegree[i]==0)
                push(s,i);
        }
    }
    free(indegree);
    return count==G.vexnum;
}

二、邻接表法

1.结构体

//边
typedef struct ArcNode{
    int adjvex; //邻接点在数组的下标
    ArcNode *next;//下一个邻接点
    int weight;
}ArcNode;

//顶点
typedef struct VNode{
    VertexType data; //顶点的数据
    ArcNode *first; //第一条边
    int count; //记录
}VNode,AdjList[MaxVertexNum];

//图
typedef  struct{
    AdjList vertices;
    int vexnum,arcnum;
    int kid;
}ALGraph;

2.操作函数

1)返回顶点u的下标

int LocateVex(ALGraph G, VertexType u)
{
        int i;
        for (i = 0; i < G.vexnum && G.vertices[i].data != u; i++);
        if (i == G.vexnum) return -1; //不存在该顶点
        else return i;
}

2)创建邻接表

bool CreatALGraph(ALGraph &G)
{
    cout<<"请输入结点数和边数"<<endl;
    cin>>G.vexnum>>G.arcnum;
    cout<<"请输入各结点值"<<endl;
    for (int i=0;i<G.vexnum;i++) {
        cin>>G.vertices[i].data;
        G.vertices[i].first=NULL;
        G.vertices[i].count=0;
    }
    cout<<"请输入一条边依附的两个顶点值"<<endl;
    for (int j=0;j<G.arcnum;j++) {
        VertexType v1,v2;
        cin>>v1>>v2;
        int a=LocateVex(G,v1);
        int b=LocateVex(G,v2);
        ArcNode *p1=(ArcNode *)malloc(sizeof (ArcNode));
        p1->adjvex=b;
        p1->next=G.vertices[a].first;
        G.vertices[b].count++;
        G.vertices[a].first=p1;

        ArcNode*p2=(ArcNode *)malloc(sizeof (ArcNode));
        p2->adjvex=a;
        p2->next=G.vertices[b].first;
        G.vertices[b].first=p2;
    }
    return true;

}

3)求顶点x的第一个邻接点

int FirstNeighbor(ALGraph G, VertexType x)
{
    if(x != -1){
            ArcNode *p = G.vertices[x].first; //对应边链表的第一个结点
            if(p!=NULL){
                return p->adjvex;
            }
        }
}

4)顶点v除去w后第一个邻接点

int NextNeighbor(ALGraph G, VertexType v, VertexType w)
{
    if(v!=-1 && w!=-1){
            ArcNode *p = G.vertices[v].first; //对应边链表的第一个结点
            while(p!=NULL && p->adjvex!=w) 
                p=p->next; //找到v的邻接点w
            if(p!=NULL && p->next!=NULL) //w存在且w的邻接点存在
                return p->next->adjvex;
        }
        return -1; 
}

5)拓扑排序

int topSort(ALGraph *G)
{
    int i,j,count=0;
    ArcNode *p;

    InitStack(s);
    for (int i=0;i<G->vexnum;i++) {
        if(G->vertices[i].count==0)
            push(s,i);
    }
    while (StackEmpty(s)) {
            pop(s,i);

        ++count;
        cout<<i+1<<",";
        p=G->vertices[i].first;
        while (p!=NULL) {
            j=p->adjvex;
            --G->vertices[j].count;
            if(G->vertices[j].count==0)
                push(s,j);
        }
        p=p->next;
    }
    return  count==G->vexnum?1:0;
}

6)图的遍历

a.广度优先遍历
void BFS(ALGraph G, int v)
{
    visit(G,v);
    visited[v]=1;

    EnLinkQueue(Q,v);


    while (!LinkQueueEmpty(Q)) {
       DeLinkQueue(Q,v);
        for (int w = FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w)) {
            if(!visited[w]){
                visit(G,w);
                visited[w]=1;
                EnLinkQueue(Q,w);
            }
        }
    }
}

void BFSTraverse(ALGraph G)
{
    for(int i=0;i<G.vexnum;i++){
        visited[i]=0;
    }
    InitLinkQueue(Q);

    for(int i=0;i<G.vexnum;i++){
        if(!visited[i])
            BFS(G,i);
    }
}
b.深度优先遍历
void DFS(ALGraph G, int v)
{
    visit(G,v);
    visited[v]=true;
    for (int w = FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w)) {
      if(!visited[w]){
      DFS(G,w);
      }

}
}

void DFSTraverce(ALGraph G)
{
    for (int v=0;v<G.vexnum;v++) {
        visited[v]=false;
    }
    for(int v=0;v<G.vexnum;v++){
        if(!visited[v])
            DFS(G,v);
    }

}

三、其他存储结构

1.十字链表法  ------只针对有向图

//十字链表法 --- 有向图
typedef  struct AcrNode{
    int tailvex,headvex;
    AcrNode *hlink,*tlink;//指向弧尾和弧头相同的结点。
    int info;
}ArcNode;

//顶点表结点
typedef  struct VNode{
    VertexType data;
    AcrNode *firstin,*firstout;//第一条入弧和出弧
}VNode;

typedef struct{
    VNode xlist[MaxVertexNum];
    int vexnum,arcnum;
}Graph;

2.邻接多重表 ---只针对无向图

//邻接多重表---无向图
typedef struct ArcNode{
    bool mark;
    int ivex,jvex;
    ArcNode *ilink,*jLink; //依附于顶点i,j的下一条边
}ArcNode;

typedef struct VNode{
    VertexType data;
    ArcNode *firstEdge;
}VNode;

typedef struct {
    VNode adjMuList[MaxVertexNum];
    int acrnum,vexnum;
}Graph;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值