数据结构图的各种操作

#ifndef _GRAPHCLASS_H_
#define _GRAPHCLASS_H_

const int MaxSize = 100;
const int INF = 9999;

int visited[MaxSize];

template<class T>
struct ArcNode      //边结点类型
{
    int adjvex;     //该边的终点编号
    ArcNode<T> *nextarc;//指向下一条边的指针
    T weight;
};
//
template<class T>
struct VNode        //表头结点类型
{
    char data[MaxSize];
    ArcNode<T> *firstarc;
};
//
template<class T>
struct ALGraph                      //图的邻接表类型
{
    VNode<T> adjlist[MaxSize];      //邻接表数组
    int n,e;                        //图中顶点数n和边数e
};
//
template<class T>
class GraphClass
{
public:
    GraphClass();           //构造函数
    ~GraphClass();          //析构函数
    void CreateALGraph(T a[][MaxSize], int n, int e);//建立邻接链表
    void DFSA();                        //深度优先遍历非连通图无向图
    void BFSA();                        //广度优先遍历非连通图无向图
    bool Connect();                     //判断一个无向图是否连通
    bool HasPath(int u,int v);          //判断u与v之间是否是连通的
    void FindPath(int u,int v);         //输出u到 v的简单路径
    void FindAllPath(int u, int v);     //输出u到v的所有路径
    void FindAllLengthPath(int u, int v, int l);//输出u到v的所有路径长度为l的路径
    bool Cycle();                       //判断图中是否有回路
private:
    ALGraph<T> *G;
    void DestroyGraph();                //销毁图的邻接表
    void DFS1(int v);                   //深度优先遍历调用函数
    void BFS1(int v);                   //广度优先遍历调用函数
    void HasPath1(int u, int v, bool &has);//判断连通调用函数
    void FindPath1(int u, int v, int path[], int d);
    void FindAllPath1(int u, int v, int path[], int d);
    void FindAllLengthPath1(int u, int v, int path[], int d, int l);
    void Cycle1(int u, int v,int d,bool &has);
};
//
template<class T>
GraphClass<T>::GraphClass()
{
    G = NULL;
}
//
template<class T>
GraphClass<T>::~GraphClass()
{
    if(G != NULL)
    {
        DestroyGraph();
    }
}
//
template<class T>
void GraphClass<T>::DestroyGraph()
{
    int i;
    ArcNode<T> *p,*pre;
    for(i = 0;i < G->n;i++)             //遍历所有头结点
    {
        pre = G->adjlist[i].firstarc;
        if(pre != NULL)
        {
            p = pre->nextarc;
            while(p != NULL)
            {
                delete pre;
                pre = p;
                p = p->nextarc;
            }
            delete pre;
        }
    }
    delete G;                   //释放G所指的头结点数组的内存空间
}
//通过边数组a,顶点数n和边数e来建立图的邻接表
template<class T>
void GraphClass<T>::CreateALGraph(T a[][MaxSize], int n, int e)
{
    int i,j;
    ArcNode<T> *p;
    G = new ALGraph<T>;
    G->n = n;
    G->e = e;
    for(i = 0;i < G->n;i++)             //给邻接表中所有头结点的指针域置初值
    {
        G->adjlist[i].firstarc = NULL;
    }

    for(i = 0;i < G->n;i++)             //检查边数组中a中的每个元素
    {
        for(j = G->n - 1;j >= 0;j--)
        {
            if(a[i][j] != 0 && a[i][j] != INF)
            {
                p = new ArcNode<T>;
                p->adjvex = j;
                p->weight = a[i][j];
                p->nextarc = G->adjlist[i].firstarc;
                G->adjlist[i].firstarc = p;
            }
        }
    }

}
//
template<class T>
void GraphClass<T>::DFS1(int v)
{
    int w;
    ArcNode<T> *p;
    visited[v] = 1;             //置已访问标记
    std::cout<<v<<" ";
    p = G->adjlist[v].firstarc; //p指向v的第一个邻接点
    while(p != NULL)
    {
        w = p->adjvex;
        if(visited[w] == 0)     //若w顶点未被访问,递归访问它
        {
            DFS1(w);
        }
        p = p->nextarc;         //p置为下一个邻接点
    }
}
//
template<class T>
void GraphClass<T>::BFS1(int v)
{
    ArcNode<T> *p;
    int w;
    int qu[MaxSize];
    int rear = 0, front = 0;
    std::cout<<v<<" ";
    visited[v] = 1;         //已访问标志
    rear = (rear + 1) % MaxSize;
    qu[rear] = v;
    while(rear != front)
    {
        front = (front + 1) % MaxSize;
        w = qu[front];
        p = G->adjlist[w].firstarc;
        while(p != NULL)
        {
            if(visited[p->adjvex] == 0)
            {
                std::cout<<p->adjvex<<" ";
                visited[p->adjvex] = 1;
                rear = (rear + 1) % MaxSize;
                qu[rear] = p->adjvex;
            }
            p = p->nextarc;                 //找下一个临界顶点
        }
    }
}
//若无向图是非连通图,则只能访问到初始点所在连通分量中的所有顶点,其他连通分量中的顶点不可能访问到
//需要在每个连通分量中选择初始结点,分别进行遍历
template<class T>
void GraphClass<T>::DFSA()
{
    int i;
    ArcNode<T> *p;
    for(i = 0;i < G->n;i++)
    {
        visited[i] = 0;
    }
    for(i = 0;i < G->n;i++)
    {
        if(visited[i] == 0)
        {
            DFS1(i);
        }
    }
}
//
template<class T>
void GraphClass<T>::BFSA()
{
    int i;
    for(i = 0;i < G->n;i++)
    {
        visited[i] = 0;
    }
    for(i = 0;i < G->n;i++)
    {
        if(visited[i] == 0)
        {
            BFS1(i);
        }
    }
}
//判断连通性
template<class T>
bool GraphClass<T>::Connect()
{
    int i;
    bool flag = true;
    for(i = 0;i < G->n;i++)     //将visited数组元素均置为0
    {
        visited[i] = 0;
    }
    DFS1(0);                   //深度优先遍历
    for(i = 0;i < G->n;i++)
    {
        if(visited[i] == 0)     //若有没有被访问到的结点
        {
            flag = false;
            break;
        }
    }
    return flag;
}
//
template<class T>
bool GraphClass<T>::HasPath(int u,int v)
{
    int i;
    bool has = false;
    for(i = 0;i < G->n;i++)         //将访问数组元素置为0
    {
        visited[i] = 0;
    }
    HasPath1(u,v,has);              //深度优先遍历
    return has;
}
//
template<class T>
void GraphClass<T>::HasPath1(int u, int v, bool &has)
{
    ArcNode<T> *p;
    int w;
    visited[u] = 1;
    p = G->adjlist[u].firstarc;//p指向u的第一个相邻点
    while(p != NULL)
    {
        w = p->adjvex;          //相邻点的编号是w
        if(w == v)              //找到目标点后返回
        {
            has = true;
            return;
        }
        if(visited[w] == 0)
        {
            HasPath1(w,v,has);
        }
        p = p->nextarc;         //p指向下一个相邻点
    }
}
//
template<class T>
void GraphClass<T>::FindPath(int u, int v)
{
    int i, path[MaxSize], d = -1;
    for(i = 0;i < G->n;i++)
    {
        visited[i] = 0;
    }
    FindPath1(u,v,path,d);
}
//
template<class T>
void GraphClass<T>::FindPath1(int u, int v, int path[], int d)
{
    ArcNode<T> *p;
    int w, i;
    visited[u] = 1;
    d++;
    path[d] = u;
    if(u == v)
    {
        for(i = 0;i < d;i++)
        {
            std::cout<<path[i]<<"   ";
        }
        std::cout<<std::endl;
        return;
    }
    p = G->adjlist[u].firstarc;
    while(p != NULL)
    {
        w = p->adjvex;
        if(visited[w] == 0)
        {
            FindPath1(w,v,path,d);
        }
        p = p->nextarc;
    }
}
//
template<class T>
void GraphClass<T>::FindAllPath(int u, int v)
{
    int path[MaxSize],d = -1,i;
    for(i = 0;i < G->n;i++)     //未访问标记
    {
        visited[i] = 0;
    }
    FindAllPath1(u,v,path,d);
}
//
template<class T>
void GraphClass<T>::FindAllPath1(int u, int v, int path[], int d)
{
    ArcNode<T> *p;
    int w,i;
    visited[u] = 1;
    d++;
    path[d] = u;                    //将顶点u加入到路径中去
    if(u == v)                      //如果找到路径
    {
        for(i = 0;i < d;i++)
        {
            std::cout<<path[i]<<"   ";
        }
        std::cout<<std::endl;
    }
    p = G->adjlist[u].firstarc;
    while(p != NULL)
    {
        w = p->adjvex;              //相邻结点的编号
        if(visited[w] == 0)
        {
            FindAllPath1(w,v,path,d);//递归调用
        }
        p = p->nextarc;
    }
    visited[u] = 0;                 //回溯,重置为0,和找单一路径的唯一区别
}
//
template<class T>
void GraphClass<T>::FindAllLengthPath(int u, int v, int l)
{
    int path[MaxSize],i,d = -1;
    for(i = 0;i < G->n;i++)
    {
        visited[i] = 0;
    }
    FindAllLengthPath1(u,v,path,d,l);
}
//
template<class T>
void GraphClass<T>::FindAllLengthPath(int u, int v, int path[], int d, int l)
{
    ArcNode<T> *p;
    int w,i;
    visited[u] = 1;     //加入到路径中
    d++;
    path[d] = u;
    if((u == v) && (d == l))//找到一条路径长度为l的输出路径
    {
        for(i = 0;i < d;i++)
        {
            std::cout<<path[i]<<"   ";
        }
        std::cout<<std::endl;
    }
    p = G->adjlist[u].firstarc;
    while(p != NULL)
    {
        w = p->adjvex;
        if(visited[w] == 0)
        {
            FindAllLengthPath1(w,v,path,d,l);
        }
        p = p->nextarc;
    }
    visited[u] = 0;
}
//
template<class T>
bool GraphClass<T>::Cycle()
{
    int i,j;
    bool has = false;
    int d = -1;
    for(i = 0;i < G->n;i++)
    {
        visited[i] = 0;
        Cycle1(i,i,d,has);
        if(has)
        {
            return true;
        }
    }
    return false;
}
//
template<class T>
void GraphClass<T>::Cycle1(int u, int v, int d,bool &has)
{
    ArcNode<T> *p;
    int w;
    d++;
    visited[u] = 1;
    if((u == v)&&(d > 0))
    {
        has = true;
        return;
    }
    p = G->adjlist[u];
    while(p != NULL)
    {
        w = p->adjvex;
        if(visited[w] == 0)
        {
            Cycle1(w,v,d,has);
        }
        p = p->nextarc;
    }
    visited[u] = 0;
}
#endif // _GRAPHCLASS_H_

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值