【数据结构】【图】【邻接矩阵】一道题实现邻接矩阵的插入边和删除边和反思

假设无向、非加权图的数据元素为字符,采用邻接表存储结构。图的创建、存储结构输出等大部分操作的实现代码操作已经给出,请分别补充写出操作插入边、删除边的实现函数代码。

一、有关说明:

1.插入边,int Insert_Edge(g,vi,vj)

输入:图g,要插入边的两个顶点元素vi,vj;

输出:返回插入的状态(成功、错误:边顶点不存在、错误:边重复),根据不同的状态会输出:

​ Error:Vertex does not exist!

​ Error:Edge repetition!

​ Edge insertion succeeded!

注:为了统一,邻接点链入链表时,链入在前面(表头位置)

2.删除边, int Delete_Edge(g,vi,vj)

输入:图g,要删除边的两个顶点元素vi,vj;

输出:返回删除的状态(成功、错误:边顶点不存在、错误:边不存在),根据不同的状态会输出:

​ Error:Vertex does not exist!

​ Error:Edge does not exist!

​ Edge deletion succeeded!

3.主函数中操作的控制: 1—创建图 2—输出图的存储结构 3—插入边 4—删除边 0—退出

创建图时,需要输入顶点个数、各个顶点元素、各条边,具体见样例;

输出存储结构时,输出格式见样例;

插入或删除边时,需要输入边的两个顶点元素;

二、给出代码如下请补全:

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 
using namespace std;
#define   Max_VertexNum 50     //允许图的顶点个数的最大值
typedef   char  VertexType;  //定义数据元素(顶点)类型为char
//********************************************************************************
//邻接表存储结构
struct  EdgeNode   //定义边存储结点
{ int adjvex;        //邻接点的存储位置
EdgeNode  *next;   //指向下邻接点
};      

struct VertexNode   //定义顶点存储结点
{ VertexType vertex;       //数据元素
struct EdgeNode *link;   //第一个邻接点
};          

typedef struct Graph   //定义邻接表图结构
{ int VexNum;        //图的顶点个数
VertexNode Nodetable[Max_VertexNum];   //一维数组-邻接表    
}  Graphlnk;      //定义邻接表存储的图类型
//**********************************************************************************
// 基于邻接表存储的 无向、非加权图的各种操作的实现
//** 创建图
void create_graph(Graphlnk &g)
{	VertexType v1, v2;
    int i, j;
    struct  EdgeNode *p, *q;
    cin >> g.VexNum;  //读入图的顶点个数
    while (g.VexNum < 0)
        cin >> g.VexNum;
    for (i = 0; i < g.VexNum; i++)
    {	cin >> g.Nodetable[i].vertex;    //输入顶点元素
        g.Nodetable[i].link = NULL;      //邻接表初始化
    }
    cin >> v1 >> v2;     //输入边的两个顶点
    while (v1 != '*'&&v2 != '*')
    {   for (i = 0; i < g.VexNum; i++)
            if (g.Nodetable[i].vertex == v1) break;
        for (j = 0; j < g.VexNum; j++)
            if (g.Nodetable[j].vertex == v2) break;
        if (i >= g.VexNum || j >= g.VexNum)  cin >> v1 >> v2;    //边顶点不正确,重新读
        else      //链入邻接点
        {	p = (struct  EdgeNode *)malloc(sizeof(struct  EdgeNode));
            p->adjvex = j;
            p->next = g.Nodetable[i].link;
            g.Nodetable[i].link = p;
            q = (struct  EdgeNode *)malloc(sizeof(struct  EdgeNode));
            q->adjvex = i;
            q->next = g.Nodetable[j].link;
            g.Nodetable[j].link = q;
            cin >> v1 >> v2;
        }
    }
}

void print_graph(Graphlnk  g)
{	int i;
    struct  EdgeNode *p;
    cout << "Adjacency List is:" << endl;
    for (i = 0; i < g.VexNum; i++)
    {	cout << g.Nodetable[i].vertex << ":";
        p = g.Nodetable[i].link;
        while (p != NULL)
        {	cout << "-->" << g.Nodetable[p->adjvex].vertex;
            p = p->next;
        }
        cout << endl;
    }
}
//**********************************************************************
     补充 插入边、删除边的函数
//**********************************************************************
int main()
{	Graphlnk g;
    int ic;
    VertexType vi, vj;
    int k;
    while (1)
    {    //请输入要执行的操作:";
        cin >> ic;
        while (ic < 0 || ic>4)
            cin >> ic;
        if (ic == 1)  create_graph(g);    //创建图
        if (ic == 2)  print_graph(g);       //输出图结构
        if (ic == 3)     //插入边
        { cin >> vi >> vj;
            k = Insert_Edge(g, vi, vj);
            if (k == -1) cout << "Error:Vertex does not exist!" << endl;
            if(k==0) cout << "Error:Edge repetition!" << endl;
            if(k==1) cout << "Edge insertion succeeded!" << endl;
        }
        if (ic == 4)     //删除边
        { cin >> vi >> vj;
            k = Delete_Edge(g, vi, vj);
            if (k == -1) cout << "Error:Vertex does not exist!." << endl;
            if (k == 0) cout << "Error:Edge does not exist!" << endl;
            if (k == 1) cout << "Edge deletion succeeded!" << endl;
        }
        if (ic == 0)  break;
    }
    return 0;
}

三、作答如下↓

int prjIns1(Graphlnk  &g,VertexType vi,VertexType vj,int i,int j,struct EdgeNode *ptr1,struct EdgeNode *ptr2,struct EdgeNode *p,struct EdgeNode *q){
    if(ptr1==NULL){
        p = (struct  EdgeNode *)malloc(sizeof(struct  EdgeNode));
        p->adjvex = j;
        p->next = g.Nodetable[i].link;
        g.Nodetable[i].link = p;
        return 1;
    }
    if(ptr1!=NULL){
        if(ptr1->adjvex==j)
            return 0;
        else{
            while(ptr1->next!=NULL){
                ptr1=ptr1->next;
                if(ptr1->adjvex==j)
                    return 0;
            }
            p = (struct  EdgeNode *)malloc(sizeof(struct  EdgeNode));
            p->adjvex = j;
            p->next = ptr1->next;
            ptr1->next = p;
            return 1;
        }
    }
}

int prjIns2(Graphlnk  &g,VertexType vi,VertexType vj,int i,int j,struct EdgeNode *ptr1,struct EdgeNode *ptr2,struct EdgeNode *p,struct EdgeNode *q){
    if(ptr2==NULL){
        q = (struct  EdgeNode *)malloc(sizeof(struct  EdgeNode));
        q->adjvex = i;
        q->next = g.Nodetable[j].link;
        g.Nodetable[j].link = q;
        return 1;
    }
    if(ptr2!=NULL){
        if(ptr2->adjvex==i)
            return 0;
        else{
            while(ptr2->next!=NULL){
                ptr2=ptr2->next;
                if(ptr2->adjvex==i)
                    return 0;
            }
            q = (struct  EdgeNode *)malloc(sizeof(struct  EdgeNode));
            q->adjvex = i;
            p->next = ptr2->next;
            ptr2->next = p;
            return 1;
        }
    }
}

int Insert_Edge(Graphlnk  &g,VertexType vi,VertexType vj){
    int i,j;
    struct  EdgeNode *p, *q;

    for (i = 0; i < g.VexNum; i++){
        if (g.Nodetable[i].vertex == vi)break;
        if(i==g.VexNum-1)
            return -1;
    }
    for (j = 0; j < g.VexNum; j++){
        if (g.Nodetable[j].vertex == vj)break;
        if(j==g.VexNum-1)
            return -1;
    }


    struct EdgeNode *ptr1=g.Nodetable[i].link;
    struct EdgeNode *ptr2=g.Nodetable[j].link;


    int ins1,ins2;
    ins1=prjIns1(g,vi,vj,i,j,ptr1,ptr2,p,q);
    ins2=prjIns2(g,vi,vj,i,j,ptr1,ptr2,p,q);
    if(ins1==1&&ins2==1)
        return 1;
    else
        return 0;
}


int prjDel1(Graphlnk  &g,VertexType vi,VertexType vj,int i,int j,struct EdgeNode *ptr1,struct EdgeNode *ptr2){
    if(ptr1==NULL){
        return 0;
    }
    if(ptr1!=NULL){
        if(ptr1->adjvex==j&&ptr1->next!=NULL){
            g.Nodetable[i].link=ptr1->next;
            return 1;
        }
        if(ptr1->adjvex==j&&ptr1->next==NULL){
            g.Nodetable[i].link=NULL;
            return 1;
        }
        if(ptr1->adjvex!=j&&ptr1->next!=NULL){
            while (ptr1->next->adjvex!=j&&ptr1->next!=NULL){

                ptr1=ptr1->next;

            }
            if(ptr1->next==NULL)
                return 0;
            if(ptr1->next->adjvex==j){
                ptr1->next=ptr1->next->next;
                return 1;
            }
        }
        if(ptr1->adjvex!=j&&ptr1->next==NULL){
            return 0;
        }
    }
}

int prjDel2(Graphlnk  &g,VertexType vi,VertexType vj,int i,int j,struct EdgeNode *ptr1,struct EdgeNode *ptr2){
    if(ptr2==NULL){
        return 0;
    }
    if(ptr2!=NULL){
        if(ptr2->adjvex==i&&ptr2->next!=NULL){
            g.Nodetable[j].link=ptr2->next;
            return 1;
        }
        if(ptr2->adjvex==i&&ptr2->next==NULL){
            g.Nodetable[j].link=NULL;
            return 1;
        }
        if(ptr2->adjvex!=i&&ptr2->next!=NULL){
            while (ptr2->next->adjvex!=i&&ptr2->next!=NULL){

                ptr2=ptr2->next;

            }
            if(ptr2->next==NULL)
                return 0;
            if(ptr2->next->adjvex==i){
                ptr2->next=ptr2->next->next;
                return 1;
            }
        }
        if(ptr2->adjvex!=i&&ptr2->next==NULL){
            return 0;
        }
    }
}

int Delete_Edge (Graphlnk  &g,VertexType vi,VertexType vj){
    int i,j;
    struct  EdgeNode *p, *q;
    for (i = 0; i < g.VexNum; i++){
        if (g.Nodetable[i].vertex == vi)break;
        if(i==g.VexNum-1)
            return -1;
    }
    for (j = 0; j < g.VexNum; j++){
        if (g.Nodetable[j].vertex == vj)break;
    }

    struct EdgeNode *ptr1=g.Nodetable[i].link;
    struct EdgeNode *ptr2=g.Nodetable[j].link;

    int del1,del2;
    del1= prjDel1(g,vi,vj,i,j,ptr1,ptr2);
    del2= prjDel2(g,vi,vj,i,j,ptr1,ptr2);
    if(del1==1&&del2==1)
        return 1;
    if(del1==0)
        return 0;
}

四、反思

1.发现问题

一开始可以略微实现功能,但稍微复杂的输入就好多bug

2.解决实现

(1)在程序设计每一环节开始之前就想好每一步可能有的分支,然后依次实现,最后化简,先繁后间,可以防止没想到的情况发生;

(2)在实现不同分支时,我发现如果是if()if()if()这种语句的话,要考虑前if()对后if()的影响,比如经历了前if()可能会使得后if()意料之外实现,同时修改两个指针数据发生种问题尤其突出,主要是因为不是每个if()里都有return

(3)只要解决每个if里都有return就可以解决(2)的问题,在这道题中我建了小函数实现这种功能。

你可能感兴趣的:(算法習作,数据结构,链表,算法)