图的操作

图的操作

实验目的

  1. 掌握图的基本概念,描述方法;遍历方法。
  2. 掌握图的最短路径算法。
    实验内容:
    1.图的存储结构使用邻接矩阵。
    2.创建图操作类,支持BFS遍历、DFS遍历、求单源最短路径、判断是否存在回路等四个功能,这些功能封装成图操作类的成员函数。
    3. 输入图的节点数n(不超过10个)、边数m,节点分别用0到n-1表示。
    4. 采用“起始节点,终止节点,权值”输入图的m条边,创建图。
    5. 输出从节点0开始的BFS遍历、DFS遍历节点遍历顺序。
    6. 输出从节点0到其余节点最短路径的长度,如果没有路经,输出0。
    基本思路:
    1.使用了链式队列,图的实现代码
    2.在graph类中设置了BFS,DFS,Dijkstra,hascircle,4个基础操作函数,并利用helpBFS,helpDFS,minVertex,helpfindcircle,4个辅助操作函数
    3.在BFS和DFS中循环调用相应help函数对未遍历的节点遍历
    4.在hascircle函数中循环调用helpfindcircle对未遍历的节点dfs遍历,在逐个的遍历过程中,若发现除父节点外已经遍历过的结点,则判断有环
#include <iostream>
using namespace std;
template <typename E>
class Link {
private:
    static Link<E>* freelist; // Reference to freelist head
public: E element; // Value for this node
    Link *next;
    Link(const E& elemval, Link* nextval =NULL) {
        element = elemval; next = nextval; }

    Link(Link* nextval =NULL) { next = nextval; }
    void* operator new(size_t) {
        if (freelist == NULL)
            return ::new Link;
        Link<E>* temp = freelist;
        freelist = freelist->next;
        return temp;
    }
    void operator delete(void* ptr) {
        ((Link<E>*)ptr)->next = freelist;
        freelist = (Link<E>*)ptr; }
    };
template <typename E>
Link<E>* Link<E>::freelist = NULL;
template <typename E>
class Queue {
private: Link<E>* front; // Pointer to front queue node
    Link<E>* rear; // Pointer to rear queue node
    int size; // Number of elements in queue
public:
    Queue(int sz =10)
    { front = rear = new Link<E>();
        size = 0; }
~Queue() { clear();
            delete front; }
void clear() {
    while(front->next != NULL) {
        rear = front;
        delete rear; }
    rear = front;
    size = 0; }
void enqueue(const E& it) {
    rear->next = new Link<E>(it, NULL);
    rear = rear->next;
    size++; }
E dequeue() {
    //Assert(size != 0, "Queue is empty");
    E it = front->next->element;
    Link<E>* ltemp = front->next;
    front->next = ltemp->next;
    if (rear == ltemp)
        rear = front; // Dequeue last element
    delete ltemp; // Delete link
    size --;
    return it; // Return element value
}
const E& frontValue() const { // Get front element
    //Assert(size != 0, "Queue is empty");
    return front->next->element; }
virtual int length() const {
        return size; }
};

class Graph{
private:
    int numVertex, numEdge; // Store number of vertices, edges
    int **matrix;
    int *mark;
    void helpDFS(int v) {
        PreVisit(v);
        setMark(v, 1);
        for (int w=first(v); w<numVertex; w = next(v,w))
            if (getMark(w) == 0)
                helpDFS(w);
    }
    void helpBFS(int start, Queue<int>* Q) {
        int v, w;
        Q->enqueue(start);
        setMark(start, 1);
        while (Q->length() != 0) {
            v = Q->dequeue();
            PreVisit(v);
            for (w=first(v); w<numVertex; w = next(v,w))
                if (getMark(w) == 0) {
                    setMark(w, 1);
                    Q->enqueue(w); }
        }

    }
    int helpfindcircle(int v,int baba)
    {  setMark(v,1);
        for (int w=first(v); w<n(); w = next(v,w))
       {     if(getMark(w)==1&&w!=baba)
                return 1;
             else if(getMark(w)==0)
                if(helpfindcircle(w,v))
                     return 1;
        }
        return 0;
    }
public:
    Graph(int numVert){
        Init(numVert); }
    ~Graph() {
        delete [] mark;
        for (int i=0; i<numVertex; i++)
            delete [] matrix[i];
        delete [] matrix; }
void Init(int n) {
    int i;
    numVertex = n;
    numEdge = 0;
    mark = new int[n]; // Initialize mark array
    for (i=0; i<numVertex; i++)
        mark[i] = 0;
    matrix = (int**) new int*[numVertex]; // Make matrix
    for (i=0; i<numVertex; i++)
        matrix[i] = new int[numVertex];
    for (i=0; i< numVertex; i++) // Initialize to 0 weights
        for (int j=0; j<numVertex; j++)
            matrix[i][j] = 0;
    }
    int n() {
        return numVertex; }
    int e() {
        return numEdge; }
    int first(int v) {
        for (int i=0; i<numVertex; i++)
             if (matrix[v][i] != 0)
                 return i;
        return numVertex; // Return n if none
       }
// Return v’s next neighbor after w
    int next(int v, int w) {
        for(int i=w+1; i<numVertex; i++)
            if (matrix[v][i] != 0) return i;
        return numVertex; // Return n if none
    }
    void setEdge(int v1, int v2, int wt) {
     //   Assert(wt>0, "Illegal weight value");
        if (matrix[v1][v2] == 0)
            numEdge++;
        matrix[v1][v2] = wt; }
    void delEdge(int v1, int v2) {
        if (matrix[v1][v2] != 0)
            numEdge--;
        matrix[v1][v2] = 0; }
    bool isEdge(int i, int j) // Is (i, j) an edge?
    { return matrix[i][j] != 0; }
    int weight(int v1, int v2) {
        return matrix[v1][v2]; }
    int getMark(int v) {
        return mark[v]; }
    void setMark(int v, int val) {
        mark[v] = val; }
    void PreVisit(int v){
            cout<<v<<' ';
    }
    void DFS(){
        int i;
        for(i=0;i<numVertex;i++)
            setMark(i,0);
        for(int i=0;i<numVertex;i++)
                if(getMark(i)==0)
                    helpDFS(i);
        cout<<endl;

    }
    void BFS(){
        Queue<int> q;
        int i;
        for(i=0;i<numVertex;i++)
            setMark(i,0);
        for(i=0;i<numVertex;i++)
            if(getMark(i)==0)
                helpBFS(i,&q);
        cout<<endl;

    }
    int minVertex(int* D) {
        int i, v =-1;
        for (i=0; i<numVertex; i++)
            if (getMark(i) == 0) {
                v = i;
                break; }
        for (i++; i<numVertex; i++)
            if ((getMark(i) == 0) && (D[i] < D[v]))
                v = i;
        return v;
    }
    void Dijkstra(int* D, int s) {
       int i, v, w;
       D[s]=0;
       for(i=0;i<n();i++)
           setMark(i,0);
        for (i=0; i<numVertex; i++) {
            v = minVertex(D);
            if (D[v] == 100)
                return; // Unreachable vertices
            setMark(v, 1);
            for (w=first(v);w<n(); w = next(v,w))
                if (D[w] > (D[v] + weight(v, w)))
                    D[w] = D[v] + weight(v, w);
        }
    }
    bool hascircle(int v)
    {
        int i;
        for(i=0;i<numVertex;i++)
            setMark(i,0);
        for(i=0;i<n();i++)
                if(getMark(i)==0)
                {   if(helpfindcircle(i,-1)==1)
                        return true;
                }
        return false;
    }

};

int main()
{
int m,n,i,v1,v2,w;
cin>>n>>m;
Graph G(n);
int D[n];
for(i=0;i<n;i++)
    D[i]=100;
for(i=0;i<m;i++)
{cin>>v1>>v2>>w;
    G.setEdge(v1,v2,w);
    G.setEdge(v2,v1,w);
}
//BFS遍历
G.BFS();

//DFS遍历
G.DFS();

//找最短路径
G.Dijkstra(D,0);
for(i=1;i<G.n();i++)
    if(D[i]==100)
        cout<<0<<' '<<i<<' '<<"0"<<endl;
    else
        cout<<0<<' '<<i<<' '<<D[i]<<endl;
//有无环

if(G.hascircle(0)==true)
    cout<<"YES"<<endl;
else
    cout<<"NO"<<endl;

return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值