数据结构---图(邻接表)

// Graph_Adjacency List.cpp : Defines the entry point for the console application.
/*-----CODE FOR FUN---------------
-------CREATED BY Dream_Whui------
-------2015-2-12--------------------*/

#include "stdafx.h"
#include <iostream>
#include <queue>
using namespace std;

#define      MAX_VERTEX_NUM    20

#define   TRUE             1
#define   FALSE            0
#define   OK               1
#define   ERROR            0
#define   OVERFLOW          -2
#define   INFEASIBLE      -1

typedef        char*    VertexType;
typedef        int        InfoType;

typedef enum
{
    DG,DN,UDG,UDN//有向图,有向网,无向图,无向网
}GraphKind;

typedef struct ArcNode
{    
    int                adjvex;        //该弧所指向的顶点的位置
    struct ArcNode    *nextarc;    //指向下一条弧的指针
    InfoType        *info;        //该弧相关信息的指针
}ArcNode;

typedef struct VNode
{
    VertexType        data;        //顶点信息
    ArcNode            *firstarc;    //指向第一条依附该顶点的弧的指针
}VNode, AdjList[MAX_VERTEX_NUM];

typedef struct
{
    AdjList    vertices;
    int        vexnum,arcnum;        //顶点数,弧数
    int        kind;                //图的种类标记
}ALGraph;

bool visited[MAX_VERTEX_NUM];

int CreateDG(ALGraph &G);//构造有向图
int CreateDN(ALGraph &G);//构造有向网
int CreateUDG(ALGraph &G);//构造无向图
int CreateUDN(ALGraph &G);//构造无向网

int CreateGraph(ALGraph &G)//采用邻接表表示法,构造图G
{
    int n;
    cout<<"创建有向图(0),有向网(1),无向图(2),无向网(3)"<<endl;
    cin>>n;
    switch(n)
    {
    case DG:
        G.kind = DG;
        return CreateDG(G);//有向图
    case DN:
        G.kind = DN;
        return CreateDN(G);//有向网
    case UDG:
        G.kind = UDG;
        return CreateUDG(G);//无向图
    case UDN:
        G.kind = UDN;
        return CreateUDN(G);//无向网
    default:
        return ERROR;
    }
}

int LocateVex(ALGraph G, VertexType v)    //顶点v在图中的位置
{
    int i;
    for(i=0; i<G.vexnum; i++)
    {
        if(strcmp(G.vertices[i].data,v)==0)
            return i;
    }
    return -1;
}

void CreateSub(ALGraph &G, int i, int j, int* w)//创建图(网)的辅助函数,构建第i个顶点到第j个顶点,权值w
{
    ArcNode *e, *p, *pre;
    e = (ArcNode*)malloc(sizeof(ArcNode));
    p = (ArcNode*)malloc(sizeof(ArcNode));
    pre = (ArcNode*)malloc(sizeof(ArcNode));
    e->adjvex = j;                        //
    e->nextarc = NULL;
    e->info = w;
    if(!G.vertices[i].firstarc)            //在头结点后插入
            G.vertices[i].firstarc = e;
        else                            
        {
            p = G.vertices[i].firstarc;
            if(p->adjvex < j)            //在第一个结点前插入(第一个结点指头结点后面的那个结点)
            {
                e->nextarc = p;
                G.vertices[i].firstarc = e;
            }
            else                        //在第以个结点后插入
            {
                pre = p;
                p = p->nextarc;
                while(p)
                {
                    if(p->adjvex < j)
                    {
                        e->nextarc = p;
                        pre->nextarc = e;
                        break;
                    }
                    pre = p;
                    p = p->nextarc;
                }
                if(!p)                    //在尾结点后插入
                    pre->nextarc = e;
            }
        }
}

int CreateDG(ALGraph &G)//构造有向图
{
    cout<<"输入顶点数,边数:"<<endl;
    cin>>G.vexnum>>G.arcnum;
    int i,j,k,w;
    for(i=0; i<G.vexnum; i++)//构造顶点向量
    {
        cout<<"输入第"<<i+1<<"个顶点的名称:";
        G.vertices[i].data = (VertexType)malloc( sizeof(char) );
        cin>>G.vertices[i].data;
        G.vertices[i].firstarc = NULL;
    }
    char *v1, *v2;
    v1 = (char*)malloc(sizeof(char));
    v2 = (char*)malloc(sizeof(char));
    for(k=0; k<G.arcnum; k++)
    {
        cout<<"输入相连的边(v1,v2):";
        cin>>v1>>v2;
        i = LocateVex(G,v1);//弧尾
        j = LocateVex(G,v2);//弧头
        w = 1;
        CreateSub(G,i,j,&w);
    }
    G.kind = DG;
    return OK;
}

int CreateUDG(ALGraph &G)//构造无向图
{
    cout<<"输入顶点数,边数:"<<endl;
    cin>>G.vexnum>>G.arcnum;
    int i,j,k,w;
    for(i=0; i<G.vexnum; i++)//构造顶点向量
    {
        cout<<"输入第"<<i+1<<"个顶点的名称:";
        G.vertices[i].data = (VertexType)malloc( sizeof(char) );
        cin>>G.vertices[i].data;
        G.vertices[i].firstarc = NULL;
    }
    char *v1, *v2;
    v1 = (char*)malloc(sizeof(char));
    v2 = (char*)malloc(sizeof(char));
    for(k=0; k<G.arcnum; k++)
    {
        cout<<"输入相连的边(v1,v2):";
        cin>>v1>>v2;
        i = LocateVex(G,v1);//边的起点
        j = LocateVex(G,v2);//边的终点
        CreateSub(G,i,j,&w);
        CreateSub(G,j,i,&w);
    }
    G.kind = UDG;
    return OK;
}

int CreateDN(ALGraph &G)//构造有向网
{
    cout<<"输入顶点数,边数:"<<endl;
    cin>>G.vexnum>>G.arcnum;
    int i,j,k,w;
    for(i=0; i<G.vexnum; i++)//构造顶点向量
    {
        cout<<"输入第"<<i+1<<"个顶点的名称:";
        G.vertices[i].data = (VertexType)malloc( sizeof(char) );
        cin>>G.vertices[i].data;
        G.vertices[i].firstarc = NULL;
    }
    char *v1, *v2;
    v1 = (char*)malloc(sizeof(char));
    v2 = (char*)malloc(sizeof(char));
    for(k=0; k<G.arcnum; k++)
    {
        cout<<"输入相连的边及权值(v1,v2,w):";
        cin>>v1>>v2>>w;
        i = LocateVex(G,v1);//弧尾
        j = LocateVex(G,v2);//弧头
        CreateSub(G,i,j,&w);
    }
    G.kind = DN;
    return OK;
}

int CreateUDN(ALGraph &G)//构造无向网
{
    cout<<"输入顶点数,边数:"<<endl;
    cin>>G.vexnum>>G.arcnum;
    int i,j,k,w;
    for(i=0; i<G.vexnum; i++)//构造顶点向量
    {
        cout<<"输入第"<<i+1<<"个顶点的名称:";
        G.vertices[i].data = (VertexType)malloc( sizeof(char) );
        cin>>G.vertices[i].data;
        G.vertices[i].firstarc = NULL;
    }
    char *v1, *v2;
    v1 = (char*)malloc(sizeof(char));
    v2 = (char*)malloc(sizeof(char));
    for(k=0; k<G.arcnum; k++)
    {
        cout<<"输入相连的边及权值(v1,v2,w):";
        cin>>v1>>v2>>w;
        i = LocateVex(G,v1);//边的起点
        j = LocateVex(G,v2);//边的终点
        CreateSub(G,i,j,&w);
        CreateSub(G,j,i,&w);
    }
    G.kind = UDN;
    return OK;
}

VertexType GetVex(ALGraph G, int v)//返回图中第V个顶点
{
    if(v<0 || v>G.vexnum)
        return NULL;
    return G.vertices[v-1].data;
}

int PutVex(ALGraph &G, VertexType v, VertexType value)//修改图中顶点v的名称为value
{
    int i;
    i = LocateVex(G,v);
    if(i<0)
        return ERROR;
    else
        strcpy(G.vertices[i].data,value);
    return OK;
}

ArcNode* FirstAdjVex(ALGraph G, VertexType v)//返回顶点V的第一个邻接点
{
    int i;
    i = LocateVex(G,v);
    if(i<0)
        return NULL;
    else
        return G.vertices[i].firstarc;
}

ArcNode* NextAdjVex(ALGraph G, VertexType v, VertexType w)//返回顶点V的(相对于w)下一个邻接点
{
    int i,j,k;
    i = LocateVex(G,v);
    j = LocateVex(G,w);
    if(i<0 || j<0)
        return NULL;
    ArcNode *p;
    p = G.vertices[i].firstarc;
    while(p)
    {
        if(p->adjvex == j)
            return p->nextarc;
        p = p->nextarc;
    }
}

void InsertVex(ALGraph &G, VertexType v)//插入顶点
{
    G.vertices[G.vexnum].data = (VertexType)malloc( sizeof(char) );
    strcpy(G.vertices[G.vexnum].data,v);
    G.vertices[G.vexnum].firstarc = NULL;
    G.vexnum++;
}

int DeleteVex(ALGraph &G, VertexType v)//删除顶点
{
    int i,k,j;
    k = LocateVex(G,v);
    if(G.kind < 2)//有向
        j = 1;
    else        //无向
        j = 0;
    if(v<0)
        return ERROR;
    ArcNode *p,*q;
    p = G.vertices[k].firstarc;//p指向顶点v的链表
    while(p)                    //删除顶点v的链表
    {
        q = p;
        G.vertices[k].firstarc = p->nextarc;
        p = p->nextarc;
        free(q);
        G.arcnum--;            //边数减1
    }
    for(i=0; i<G.vexnum; i++)//对邻接表其余顶点链表操作,删除有顶点v的指针
    {
        p = G.vertices[i].firstarc;
        if(p)            
        {
            if(p->adjvex == k)    //删除第一个结点(顶点v是第一个结点)
            {
                G.vertices[i].firstarc = p->nextarc;
                free(p);
                G.arcnum = G.arcnum - j;
            }
            else                //删除第一个后的结点(顶点v不是第一个结点)
            {    
                q = p;
                p = p->nextarc;
                while(p)
                {
                    if(p->adjvex == k)
                    {
                        q->nextarc = p->nextarc;
                        free(p);
                        G.arcnum = G.arcnum - j;//有向:边再减1;无向:不用再减1
                        break;
                    }
                    q = p;
                    p = p->nextarc;
                }
            }
        }
    }
    for(i=k; i<G.vexnum-1; i++)//邻接表第k个位置后都往前移
        G.vertices[i] = G.vertices[i+1];
    G.vexnum--;                    //顶点数减1
    for(i=0; i<G.vexnum; i++)    //由于邻接表位置的挪动,导致各顶点链表中的adjvex域都错位,应重新调整
    {
        p = G.vertices[i].firstarc;
        while(p)
        {
            if(p->adjvex > k)    //第k个位置后的链表都往前移了,因此p->adjvex > k的情况下,都减1
                p->adjvex = p->adjvex -1;
            p = p->nextarc;
        }
    }
}

int InsertArc(ALGraph &G, VertexType v, VertexType w)//插入一条边或弧
{
    int i,j,weight;
    i = LocateVex(G,v);//尾
    j = LocateVex(G,w);//头
    if(i<0 || j<0)
        return ERROR;
    G.arcnum++;
    if(G.kind % 2 == 1)//网
    {
        cout<<"输入权值:";
        cin>>weight;
    }
    else            //图
        weight = 1;
    if(G.kind < 2)//有向
        CreateSub(G,i,j,&weight);
    else         //无向
    {
        CreateSub(G,i,j,&weight);
        CreateSub(G,j,i,&weight);
    }
    return OK;
}

void DeleteSub(ALGraph &G, int i, int j)//删除边或弧的辅助函数
{
    ArcNode *p, *pre;
    p = G.vertices[i].firstarc;
    if(p->adjvex == j)
    {    
        G.vertices[i].firstarc = p->nextarc;
        free(p);
    }
    else
    {
        pre = p;
        p = p->nextarc;
        while(p)
        {
            if(p->adjvex == j)
            {
                pre->nextarc = p->nextarc;
                free(p);
                break;
            }
            pre = p;
            p = p->nextarc;
        }
    }
}

int DeleteArc(ALGraph &G, VertexType v, VertexType w)//删除一条边
{
    int i,j,k;
    i = LocateVex(G,v);//尾
    j = LocateVex(G,w);//头
    if(i<0 || j<0)
        return ERROR;
    if(G.kind < 2)//有向
        DeleteSub(G,i,j);
    else        //无向
    {
        DeleteSub(G,i,j);
        DeleteSub(G,j,i);
    }
    G.arcnum--;
    return OK;
}

void Display(ALGraph G)
{
    int i;
    ArcNode *t;
    cout<<"边数:"<<G.arcnum<<endl;
    cout<<"顶点数:"<<G.vexnum<<endl;
    for(i=0; i<G.vexnum; i++)
    {
        cout<<i+1<<": "<<G.vertices[i].data;
        t = G.vertices[i].firstarc;
        while(t)
        {
            cout<<G.vertices[t->adjvex].data;
            t = t->nextarc;
        }
        cout<<endl;
    }
}

void Visit(VertexType e)
{
    cout<<e;
}

void DFS(ALGraph G, int i)
{
    visited[i] = TRUE;
    Visit(G.vertices[i].data);
    ArcNode *w;
    for(w=FirstAdjVex(G,G.vertices[i].data); w!=NULL; w=NextAdjVex(G,G.vertices[i].data,G.vertices[w->adjvex].data))
    {
        if(!visited[w->adjvex])
            DFS(G,w->adjvex);
    }
}


void DFSTraverse(ALGraph G, void(*Visit)(VertexType))//深度优先遍历
{
    int i;
    for(i=0; i<G.vexnum; i++)
        visited[i] = FALSE;
    for(i=0; i<G.vexnum; i++)
    {
        if(!visited[i])
            DFS(G,i);
    }
    cout<<endl;
}

void BFSTraverse(ALGraph G, void(*Visit)(VertexType))//广度优先搜索算法
{
    int i,u;
    ArcNode *w;
    for(i=0; i<G.vexnum; i++)
        visited[i] = FALSE;
    queue<int> Q;
    for(i=0; i<G.vexnum; i++)
    {
        if(!visited[i])
        {
            visited[i] = TRUE;
            Visit(G.vertices[i].data);
            Q.push(i);
            while(!Q.empty())
            {
                u = Q.front();
                Q.pop();
                for(w=FirstAdjVex(G,G.vertices[u].data); w!=NULL; w=NextAdjVex(G,G.vertices[u].data,G.vertices[w->adjvex].data))
                {
                    if(!visited[w->adjvex])
                    {
                        visited[w->adjvex] = TRUE;
                        Visit(G.vertices[w->adjvex].data);
                        Q.push(w->adjvex);
                    }
                }
            }
        }
    }
    cout<<endl;
}

int main(int argc, char* argv[])
{
    ALGraph G;
    CreateGraph(G);
    Display(G);
    DFSTraverse(G,Visit);
    BFSTraverse(G,Visit);
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值