无向图基本操作

refer to

http://algs4.cs.princeton.edu/41undirected/


#include <iostream>

#include <vector>
#include <stack>
#include <queue>
#include <string.h>

using std::vector;
using std::stack;
using std::queue;
using std::cout;
using std::endl;

class Graph
{
public:
        Graph(int vCnt, int eCnt, int arr[][2])
        {
                numVertice = vCnt;
                numEdge = eCnt;
                adj = new vector<int>[vCnt];
                for (int i = 0; i < vCnt; ++i)
                        adj[i].clear();
                for (int t = 0; t < eCnt; ++t)
                {
                        adj[arr[t][0]].push_back(arr[t][1]);
                        adj[arr[t][1]].push_back(arr[t][0]);
                }
        }

        ~Graph()
        {
                delete []adj;
                adj = NULL;
        }

        vector<int> getAdj(int v)
        {
                return adj[v];
        }
        int getVerticeNum()
        {
                return numVertice;
        }

        int getEdgeNum()
        {
                return numEdge;
        }

        void show()
        {
                for (int i = 0; i < numVertice; ++i)
                {
                        cout << i << ": ";
                        int size = adj[i].size();
                        for (int j = 0; j < size; ++j)
                                cout << adj[i][j] << "  ";
                        cout << endl;
                }
        }

private:
        int numVertice;
        int numEdge;
        vector<int> *adj;

};

class DepthFirstSearch
{
public:
        DepthFirstSearch(Graph *g, int s, bool recursive)
        {
                count = 0;
                marked = new bool[g->getVerticeNum()];
                memset(marked, false, sizeof(bool)*(g->getVerticeNum()));
                if (recursive)
                        recursivedfs(g, s);
                else
                        dfs(g, s);
        }

        ~DepthFirstSearch()
        {
                delete []marked;
                marked = NULL;
        }

        int getCnt()
        {
                return count;
        }

private:
        void recursivedfs(Graph *g, int s)
        {
                ++count;
                marked[s] = true;
                int size = g->getAdj(s).size();
                for (int i = 0; i < size; ++i)
                        if (!marked[g->getAdj(s)[i]])
                                recursivedfs(g, g->getAdj(s)[i]);
        }

        void dfs(Graph *g, int s)
        {
                ++count;
                marked[s] = true;
                stack<int> st;
                st.push(s);
                while (!st.empty())
                {
                        int cur = st.top();
                        int i, size = g->getAdj(cur).size();
                        for (i = 0; i < size; ++i)
                                if (!marked[g->getAdj(cur)[i]])
                                {
                                        ++count;
                                        marked[g->getAdj(cur)[i]] = true;
                                        st.push(g->getAdj(cur)[i]);
                                        break;
                                }
                        if (i >= size)
                                st.pop();
                }
        }

private:
        int count;
        bool *marked;
};

class BreadthFirstSearch
{
public:
        BreadthFirstSearch(Graph *g, int s)
        {
                count = 0;
                marked = new bool[g->getVerticeNum()];
                memset(marked, false, sizeof(bool)*(g->getVerticeNum()));
                bfs(g, s);
        }

        ~BreadthFirstSearch()
        {
                delete []marked;
                marked = NULL;
        }

        int getCnt()
        {
                return count;
        }

private:
        void bfs(Graph *g, int s)
        {
                ++count;
                marked[s] = true;
                queue<int> qu;
                qu.push(s);
                while (!qu.empty())
                {
                        int cur = qu.front();
                        int i, size = g->getAdj(cur).size();
                        for (i = 0; i < size; ++i)
                                if (!marked[g->getAdj(cur)[i]])
                                {
                                        ++count;
                                        marked[g->getAdj(cur)[i]] = true;
                                        qu.push(g->getAdj(cur)[i]);
                                }
                        qu.pop();
                }
        }

private:
        int count;
        bool *marked;
};

class Cycle
{
public:
        Cycle(Graph *g)
        {
                int size = g->getVerticeNum();
                marked = new bool[size];
                memset(marked, false, size);
                if (hasSelfLoop(g))
                        return ;
                if (hasParallelEdges(g))
                        return ;
                edgeTo = new int[size];
                memset(edgeTo, -1, sizeof(int)*size);
                for (int v = 0; v < size; ++v)
                        if (!marked[v])
                                dfs(g, -1, v);
        }

        ~Cycle()
        {
                if (NULL != marked)
                {
                        delete []marked;
                        marked = NULL;
                }
                if (NULL != edgeTo)
                {
                        delete []edgeTo;
                        edgeTo = NULL;
                }
        }

        bool hasCycle()
        {
                return cycle.size() > 0 ? true : false;
        }

        void showCycle()
        {
                while (!cycle.empty())
                {
                        cout << cycle.top() << " <- ";
                        cycle.pop();
                }
        }

private:
        bool hasSelfLoop(Graph *g)
        {
                int size = g->getVerticeNum();
                for (int v = 0; v < size; ++v)
                {
                        int len = g->getAdj(v).size();
                        for (int i = 0; i < len; ++i)
                                if (v == g->getAdj(v)[i])
                                {
                                        cycle.push(v);
                                        cycle.push(v);
                                        return true;
                                }
                }

                return false;
        }

        bool hasParallelEdges(Graph *g)
        {
                int size = g->getVerticeNum();
                for (int v = 0; v < size; ++v)
                {
                        // check for parallel edges incident to v
                        int len = g->getAdj(v).size();
                        for (int i = 0; i < len; ++i)
                        {
                                if (marked[g->getAdj(v)[i]])
                                {
                                        cycle.push(v);
                                        cycle.push(g->getAdj(v)[i]);
                                        cycle.push(v);
                                        return true;
                                }
                                marked[g->getAdj(v)[i]] = true;
                        }

                        // reset so marked[v] = false for all v
                        for (int j = 0; j < len; ++j)
                                marked[g->getAdj(v)[j]] = false;
                }

                return false;
        }

        void dfs(Graph *g, int u, int v)
        {
                marked[v] = true;
                int size = g->getAdj(v).size();
                for (int i = 0; i < size; ++i)
                {
                        if (cycle.size() > 0)
                                return ;
                        if (!marked[g->getAdj(v)[i]])
                        {
                                edgeTo[g->getAdj(v)[i]] = v;
                                dfs(g, v, g->getAdj(v)[i]);
                        }
                        else if (g->getAdj(v)[i] != u)
                        {
                                for (int x = v; x != g->getAdj(v)[i]; x = edgeTo[x])
                                        cycle.push(x);
                                cycle.push(g->getAdj(v)[i]);
                                cycle.push(v);
                        }

                }
        }

private:
        bool *marked;
        int *edgeTo;
        stack<int> cycle;
};

int main()
{
        int vNum = 13;
        int eNum = 13;
        int arr[][2] = {
                        {0, 5}, {4, 3}, {0, 1}, {9, 12},
                        {6, 4}, {5, 4}, {0, 2}, {11, 12},
                        {9, 10}, {0, 6}, {7, 8}, {9, 11},
                        {5, 3}
                       };
        Graph graph(vNum, eNum, arr);
        graph.show();
        DepthFirstSearch dfs(&graph, 0, false);
        if (graph.getVerticeNum() != dfs.getCnt())
        {
                cout << "total num: " << graph.getVerticeNum() << endl;
                cout << "dfs from 0 can visit " << dfs.getCnt() << " vertices" << endl;
                cout << "disconnected" << endl;
        }
        else
                cout << "connected" << endl;

        BreadthFirstSearch bfs(&graph, 0);
        if (graph.getVerticeNum() != dfs.getCnt())
        {
                cout << "total num: " << graph.getVerticeNum() << endl;
                cout << "bfs from 0 can visit " << bfs.getCnt() << " vertices" << endl;
                cout << "disconnected" << endl;
        }
        else
                cout << "connected" << endl;

        Cycle finder(&graph);
        if (finder.hasCycle())
        {
                cout << "show cycle" << endl;
                finder.showCycle();
                cout << endl;
        }
        else
                cout << "graph is acycle" << endl;

        return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值