图-邻接表

一篇整理的笔记,较为全面。用邻接表表示图,实现图的深度遍历、广度优先遍历。

图-邻接表的优缺点:

  • 邻接表适用于简单图(稀疏图)。
  • 邻接表保存的都是必要的关系信息。
  • 链表的结构,导致不适宜频繁查询遍历。

 

//
//  main.cpp
//  图-邻接表
//
//  Created by scnulpc on 2018/10/23.
//  Copyright © 2018年 scnulpc. All rights reserved.
//

#include <iostream>
#include <queue>
#define Defaultvertices 30
using namespace std;
template <class T,class E>
struct Edge             //边结点的定义
{
    int dest;           //边的另一顶点位置
    E weight;           //边上权值
    Edge<T,E>* link;
    Edge(int num,E cost):dest(num),weight(cost),link(NULL){}
    bool operator !=(Edge<T,E> &R)const     //判断边不等
    {
        return (dest!=R.dest)?true:false;
    }
};
template <class T,class E>
struct Vertex           //顶点的定义
{
    T data;             //顶点的名字
    Edge<T,E> * adjacent;//边链表的头指针
    Vertex(T name):data(name),adjacent(NULL){}
};
template <class T,class E>
class Graph
{
private:
    int numVertices;
    int numEdge;
    int maxVertices;
    Vertex<T, E> *NodeTable;
public:
    int getVertexPosition(T vertex)                 //给出顶点vertex在图中的位置
    {
        for (int i=0; i<numVertices; i++)
        {
            if (NodeTable[i].data==vertex) return i;
        }
        return -1;
    }
public:
    Graph(int sz=Defaultvertices);                  //构造函数
    ~Graph();                                       //析构函数
    T getValue(int i);                              //获取第i个顶点中的值
    E getWeight(int v1,int v2);                     //获取边(v1,v2)的权值
    int numberOfVetices(){return numVertices;}      //获取顶点数量
    Vertex<T, E>* getVertex(int i);                 //获取顶点
    bool insertVertex(const T & vertex);            //插入顶点
    bool removeVertex(int v);                       //删除顶点
    bool insertEdge(int v1,int v2,E weight);        //插入边(v1,v2)
    bool removeEdge(int v1,int v2);                 //删除边(v1,v2)
    int getFirstNeighbor(int v);                    //获取v的第一个邻接点
    int getNextNeighbor(int v,int w);               //获取顶点v在w下的下一个邻接点
    
};
template <class T,class E>
Graph<T, E>::Graph(int sz)
{
    maxVertices=sz;
    numVertices=0;
    numEdge=0;
    NodeTable = new Vertex<T, E>[sz];
}
template <class T,class E>
Graph<T, E>::~Graph()
{
    for (int i=0; i<numVertices; i++)               //删除各边链表中的结点
    {
        Edge<T, E> *p = NodeTable[i].adjacent;
        while (p!=NULL) {                           //不断删除第一个边结点
            NodeTable[i].adjacent = p->link;
            delete p;
            p=NodeTable[i].adjacent;
        }
    }
    delete [] NodeTable;
}
template <class T,class E>
T Graph<T,E>::getValue(int i)
{
    return (i>-1&&i<numVertices)?NodeTable[i].data:0;
}
template <class T,class E>
E Graph<T,E>::getWeight(int v1, int v2)
{
    if (v1>-1&&v1<numVertices&&v2>-1&&v2<numVertices)
    {
        Edge<T, E>* p = NodeTable[v1].adjacent;
        while (p!=NULL) {
            if (p->dest==v2) return p->weight;
        }
    }
    return 0;
}
template <class T,class E>
Vertex<T, E>* Graph<T,E>::getVertex(int i)
{
    if (i>-1&&i<numVertices)return NodeTable[i];
    else return NULL;
}
template <class T,class E>
bool Graph<T,E>::insertVertex(const T &vertex)
{
    if (numVertices==maxVertices) return false;     //满
    if (getVertexPosition(vertex)!=-1) return false;//已存在
    NodeTable[numVertices++]=new Vertex<T, E>(vertex);
    return true;
}
template <class T,class E>
bool Graph<T,E>::removeVertex(int v)
{
    if (v<0||v>=numVertices||numVertices==1) return false;//表空或顶点号超出范围
    Edge<T, E> *p,*s,*t;
    int k;
    while (NodeTable[v].adjacent!=NULL)     //删除第v个边链表中的所有结点
    {
        p=NodeTable[v].adjacent;
        k=p->dest;                          //找到邻接结点k
        t=NULL;
        s=NodeTable[k].adjacent;
        while (s!=NULL) {                   //找对称存放的边结点
            if (s->dest==v) break;
            t=s;
            s=s->link;
        }
        if (t==NULL) {                      //删除对称存放的边结点
            NodeTable[k].adjacent = s->link;
            //numEdge--;
            delete s;
        }
        else
        {
            t->link = s->link;
            //numEdge--;
            delete s;
        }
        NodeTable[v].adjacent = p->link;
        delete p;
        numEdge--;
    }
    numVertices--;
    NodeTable[v]=NodeTable[numVertices];    //替换
    p=NodeTable[numVertices].adjacent;
    while (p!=NULL) {
        t = NodeTable[p->dest].adjacent;
        while (t!=NULL)
            if (t->dest==numVertices) {t->dest=v;break;}
            else t=t->link;
        p=p->link;
    }
    return true;
}

template <class T,class E>
bool Graph<T,E>::insertEdge(int v1, int v2, E weight)
{
    if (v1>=0&&v1<numVertices&&v2>=0&&v2<numVertices) {
        Edge<T, E>* p;
        p=NodeTable[v1].adjacent;
        while (p!=NULL) {
            if (p->dest==v2) return false;      //边已存在,不插
            p=p->link;
        }
        p=NodeTable[v1].adjacent;
        Edge<T, E> *target1 = new Edge<T, E>(v2,weight);
        target1->link=p;                        //插入边(v1,v2,weight)
        NodeTable[v1].adjacent=target1;
        p=NodeTable[v2].adjacent;
        Edge<T, E> *target2 = new Edge<T, E>(v1,weight);
        target2->link=p;                        //插入边(v2,v1,weight)
        NodeTable[v2].adjacent=target2;
        
        numEdge++;
        return true;
    }
    return false;
}
template <class T,class E>
bool Graph<T,E>::removeEdge(int v1, int v2)
{
    if (v1>=0&&v1<numVertices&&v2>=0&&v2<numVertices)
    {
        Edge<T, E> *pre=NULL,*p=NULL;
        p=NodeTable[v1].adjacent;
        while (p!=NULL) {                   //删除边(v1,v2)
            if (p->dest==v2) {
                if (pre==NULL) {
                    NodeTable[v1].adjacent=p->link;
                    delete p;
                }
                else
                {
                    pre->link=p->link;
                    delete p;
                }
                break;
            }
            else   {pre = p; p=p->link;}
        }
        p=NodeTable[v2].adjacent;
        while (p!=NULL) {                   //删除边(v2,v1)
            if (p->dest==v1) {
                if (pre==NULL) {
                    NodeTable[v2].adjacent=p->link;
                    delete p;
                }
                else
                {
                    pre->link=p->link;
                    delete p;
                }
                break;
            }
            else   { pre = p; p=p->link;}
        }
        numEdge--;                          //边数减一
        return true;
    }
    else return false;
}
template <class T,class E>
int  Graph<T,E>::getFirstNeighbor(int v)
{
    if (v>-1&&v<numVertices) {
        Edge<T, E> *p = NodeTable[v].adjacent;
        if (p!=NULL) return p->dest;
        else return -1;
    }
    return -1;
}
template <class T,class E>
int  Graph<T,E>::getNextNeighbor(int v, int w)
{
    if (v>-1&&v<numVertices&&w>-1&&w<numVertices) {
        Edge<T, E>* p = NodeTable[v].adjacent;
        while (p!=NULL) {
            if (p->dest==w)break;
            p=p->link;
        }
        if (p!=NULL&&p->dest==w)return p->dest;
        else return -1;
    }
    else return -1;
}
//图的深度遍历
template <class T,class E>
void DFS(Graph<T,E> *G,T vertex)
{
    int n = G->numberOfVetices();
    bool * visited = new bool[n];
    for (int i=0; i<n; i++)visited[i]=false;
    int index = G->getVertexPosition(vertex);
    DFS(G, index, visited);
    delete []visited;
}
template <class T,class E>
void DFS(Graph<T,E> *G,int i,bool visted[])     //深度遍历,核心操作
{
    cout<<G->getValue(i)<<" ";
    visted[i]=true;
    Edge<T, E>* p = G->getVertex(i).adjacent;
    while (p!=NULL) {
        DFS(G, p->dest, visted);
        p=p->link;
    }
}

//图的广度遍历
template <class T,class E>
void  BFS(Graph<T,E> *G,const T vertex)
{
    int index = G->getVertexPosition(vertex);
    int n = G->numberOfVetices();
    if (index<0||index>=n) return;
    bool * visited = new bool(n);
    for (int i=0; i<n; i++) visited[i]=false;
    queue<int> q;
    q.push(index);
    while (!q.empty()) {
        int v = q.front();q.pop();
        cout<<G->getValue(v)<<" ";
        visited[v]=true;
        int w = G->getFirstNeighbor(v);
        while (w!=-1) {
            if (visited[w]==false) {q.push(w);visited[w]=true;}
            w = G->getNextNeighbor(v, w);
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值