题解系列之图的存储

题解系列之图的存储(不定期更新)

邻接矩阵

1.题目描述

在邻接矩阵存储结构上实现图的基本操作 matrix_insert_vertex 和matrix_insert_arc,有关定义如下:

typedef int VertexType;

typedef enum{
    DG, UDG
}GraphType;

typedef struct{
    VertexType vertex[MAX_VERTEX_NUM]; //顶点向量
    int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //邻接矩阵
    int vexnum, arcnum;   //图的当前顶点数和弧数
    GraphType type;     //图的种类标志
}MatrixGraph;

int matrix_locate_vertex(MatrixGraph MG, VertexType vex); //返回顶点 v 在vertex数组中的下标,如果v不存在,返回-1
bool matrix_insert_vertex(MatrixGraph G, VertexType v);
bool matrix_insert_arc(MatrixGraph *G, VertexType v, VertexType w);

当成功插入顶点或边时,函数返回true,否则返回false。

2.题解

分析知如顶点或边已存在、插入边时顶点v或w不存在时两个函数返回false,同时要特别注意边界条件和细节!比如防止数组溢出。

bool matrix_insert_vertex(MatrixGraph* G, VertexType v)
{
    if (G->vexnum + 1 > MAX_VERTEX_NUM) {
        return false;
    }                         			
    if (matrix_locate_vertex(G, v) == -1) {
        G->vertex[G->vexnum] = v;
        for (int count = 0; count <= G->vexnum; count++) {
            G->arcs[count][G->vexnum] = 0;
            G->arcs[G->vexnum][count] = 0;
        }
        ++G->vexnum;
        return true;
    }
    return false;
}

bool matrix_insert_arc(MatrixGraph* G, VertexType v, VertexType w)
{
    if (G->type == DG) {
        if ((matrix_locate_vertex(G, v) != -1) && (matrix_locate_vertex(G, w) != -1)) {
            int x = matrix_locate_vertex(G, v);
            int y = matrix_locate_vertex(G, w);
            G->arcs[x][y] = 1;
            ++G->arcnum;
            return true;
        } else {
            return false;
        }
    }
    if (G->type == UDG) {
        if ((matrix_locate_vertex(G, v) != -1) && (matrix_locate_vertex(G, w) != -1)) {
            int x = matrix_locate_vertex(G, v);
            int y = matrix_locate_vertex(G, w);
            G->arcs[x][y] = 1;
            G->arcs[y][x] = 1;
            ++G->arcnum;
            return true;
        } else {
            return false;
        }
    }
    return false;
}

邻接表1

1.题目描述

试在邻接表存储结构上实现图的基本操作 insert_vertex(插入顶点) 和 insert_arc(插入边),相关定义如下:

typedef int VertexType;

typedef enum{
    DG, UDG
}GraphType;

typedef struct ArcNode
{
    int adjvex;
    InfoPtr *info;
    struct ArcNode *nextarc;

}ArcNode;

typedef struct VNode
{
    VertexType data;
    ArcNode *firstarc;
}VNode;
typedef struct
{
    VNode vertex[MAX_VERTEX_NUM];
    int vexnum, arcnum;
    GraphType type;
}ListGraph;

int locate_vertex(ListGraph* G, VertexType v); //返回顶点 v 在vertex数组中的下标,如果v不存在,返回-1
bool insert_vertex(ListGraph *G, VertexType v);
bool insert_arc(ListGraph *G, VertexType v, VertexType w);

当成功插入顶点或边时,函数返回true,否则返回false。

2.题解

​ 思路是分有向图的无向图两种情况讨论

bool insert_vertex(ListGraph* G, VertexType v)//插入顶点
{
    if (G->vexnum + 1 > MAX_VERTEX_NUM) {
        return false;
    }
    if (locate_vertex(G, v) == -1) {
        G->vertex[G->vexnum].data = v;
        G->vertex[G->vexnum].firstarc = NULL;
        ++G->vexnum;
        return true;
    }
    return false;
}
bool insert_arc(ListGraph* G, VertexType v, VertexType w)//插入边
{
    if (G->type == DG) {//无向图的情况
        if ((locate_vertex(G, v) != -1) && (locate_vertex(G, w) != -1)) {
            int a = locate_vertex(G, v);
            int b = locate_vertex(G, w);
            struct ArcNode* p = G->vertex[a].firstarc;
            while (p != NULL) {
                p = p->nextarc;
            }
            p->nextarc->adjvex = G->vertex[b].data;//把b的值插入到a的邻接表中
            return true;
        } else {
            return false;
        }
    }
    if (G->type == UDG) {//有向图的情况
        if ((locate_vertex(G, v) != -1) && (locate_vertex(G, w) != -1)) {
            int a = locate_vertex(G, v);
            int b = locate_vertex(G, w);
            struct ArcNode* p = G->vertex[a].firstarc;
            struct ArcNode* q = G->vertex[b].firstarc;
            while (q != NULL) {
                q = q->nextarc;
            }
            while (p != NULL) {
                p = p->nextarc;
            }
            p->nextarc->adjvex = G->vertex[b].data;
            q->nextarc->adjvex = G->vertex[a].data;
            return true;
        } else {
            return false;
        }
    }
}

邻接表2

1.题目描述

试在邻接表存储结构上实现图的基本操作 del_vertex(删除顶点),相关定义如下:

typedef int VertexType;

typedef enum{
    DG, UDG
}GraphType;

typedef struct ArcNode{
    int adjvex;
    InfoPtr info;
    struct ArcNode nextarc;
}ArcNode;

typedef struct VNode{
    VertexType data;
    ArcNode firstarc;
}VNode;
typedef struct{
    VNode vertex[MAX_VERTEX_NUM];
    int vexnum, arcnum;
    GraphType type;
}ListGraph;

int locate_vertex(ListGraph *G, VertexType v); //返回顶点 v 在vertex数组中的下标,如果v不存在,返回-1
bool del_vertex(ListGraph *G, VertexType v); //删除顶点 v

当成功删除顶点或边时,函数返回true,否则返回false。

2.题解

​ 思路是分出度和入度的两种情况进行删除,在出度的情况下,应该删除这个顶点的所有后继邻接表;在入度的情况下,删除其他顶点和这个顶点所有的边。

bool del_vertex(ListGraph* G, VertexType v)
{
   	ArcNode *p, *pre, *del;
    if (locate_vertex(G, v) != -1) {
        int i = locate_vertex(G, v);
        G->vertex[i].data = 0; //删除顶点信息
        p = G->vertex[i].firstarc;
        G->vertex[i].firstarc = NULL;
        while (p) { //删除出度的弧
            del = p;
            p = p->nextarc;
            free(del);
            --G->arcnum; //弧数量减一
        }
        for (int j = 0; j < G->vexnum; j++) { //删除入度的弧
            p = G->vertex[j].firstarc;
            while (p) {
                if (p->adjvex == i) {
                    if (p == G->vertex[j].firstarc) { //被删除弧结点为第一个结点
                        del = p;
                        p = p->nextarc;
                        G->vertex[j].firstarc = p;
                        pre = NULL;
                        free(del);
                        G->arcnum--; //弧数量减一
                        break;
                    } else {
                        del = p;
                        p = p->nextarc;
                        pre->nextarc = p;
                        free(del);
                        G->arcnum--; //弧数量减一
                        break;
                    }
                }
                pre = p;
                p = p->nextarc;
            }
        }
        G->vexnum--; //顶点数减一
        return true;
    } else {
        return false;
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
...... ( B )3. 有8个结点的无向最多有 条边。 A.14 B. 28 C. 56 D. 112 ( C )4. 有8个结点的无向连通最少有 条边。 A.5 B. 6 C. 7 D. 8 ( C )5. 有8个结点的有向完全有 条边。 A.14 B. 28 C. 56 D. 112 ( B )6. 用邻接表表示进行广度优先遍历时,通常是采用 来实现算法的。 A.栈 B. 队列 C. 树 D. ...... 二、填空题(每空1分,共20分) 1. 邻接矩阵 、 邻接表 等存储结构,遍历有 深度优先遍历 、 广度优先遍历 等方法。 2. 有向G用邻接表矩阵存储,其第i行的所有元素之和等于顶点i的 出度 。 3. 如果n个顶点的是一个环,则它有 n 棵生成树。 4. n个顶点e条边的,若采用邻接矩阵存储,则空间复杂度为 O(n2) 。 5. n个顶点e条边的,若采用邻接表存储,则空间复杂度为 O(n+e) 。 ....... 1. 【严题集7.1①】已知如所示的有向,请给出该的: 每个顶点的入/出度; 邻接矩阵; 邻接表; 逆邻接表。 2. 【严题集7.7②】请对下的无向带权: 写出它的邻接矩阵,并按普里姆算法求其最小生成树; 写出它的邻接表,并按克鲁斯卡尔算法求其最小生成树。 ........ 五、算法设计题(每题10分,共30分) 1. 【严题集7.14③】编写算法,由依次输入的顶点数目、弧的数目、各顶点的信息和各条弧的信息建立有向的邻接表。 解:Status Build_AdjList(ALGraph &G) //输入有向的顶点数,边数,顶点信息和边的信息建立邻接表 { InitALGraph(G); scanf("%d",&v); if(v<0) return ERROR; //顶点数不能为负 G.vexnum=v; scanf("%d",&a); if(a<0) return ERROR; //边数不能为负 G.arcnum=a; for(m=0;m<v;m++) G.vertices[m].data=getchar(); //输入各顶点的符号 for(m=1;m<=a;m++) { t=getchar();h=getchar(); //t为弧尾,h为弧头 if((i=LocateVex(G,t))<0) return ERROR; if((j=LocateVex(G,h))nextarc;q=q->nextarc); q->nextarc=p; } p->adjvex=j;p->nextarc=NULL; }//while return OK; }//Build_AdjList 2. 【严题集7.15③】试在邻接矩阵存储结构实现基本操作:DeleteArc(G,v,w)。 (刘提示:删除所有从第i个顶点出发的边的方法是 将邻接矩阵的第i行全部置0 ) ........

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值