C++ dijkstra 最短路径算法、top排序、DFS、BFS 示例 C++11

好一段时间前写的了。。。正好现在在复习数据结构,重构了一下代码

首先先是 图、点Vertex和边AdjACent的定义

class JpGraph
    {
    public:

        class Vertex;
        class AdjAcent
        {
        public:
            int cost;
            Vertex* ptr;

            explicit AdjAcent(int newCost = 0,Vertex* newPtr = nullptr):cost(newCost),ptr(newPtr){}
        };


        class Vertex
        {
        public:
            int index;
            int inDegree;
            vectordegree;


            Vertex(int data, int in_degree)
                : index(data),
                  inDegree(in_degree)                 
            {
            }
        };


        JpGraph(){}

        void lowestCost(const Vertex& v);

        void buildGraph(vector vertexs);
        void BFS(int index);
        void DFS(int index);
        void topSort();
    private:
        vectorvertexs;
    };
下面是最短路径的实现,也就是dijkstra算法的实现
inline void JpGraph::lowestCost(const Vertex& v) //形参既是从哪个点开始算
    {
        vectorbool, int>> status;
        for (int i = 0; i < vertexs.size(); ++i)
        {
            status.push_back(pair<bool, int>(false, INT32_MAX));
        }
        //建立与相应点集对应的集合。
        status[v.index].second = 0;
        auto findMin = [&]() //lambda表达式,反正我就这个函数用就没单独写个私有函数
                             //目的是找到当前权重最小的点的下标
        {
            int min = INT32_MAX;
            int minIndx = 0;
            for (int i = 0; i < status.size(); ++i)
                if (status[i].second < min && status[i].first == false)
                {
                    min = status[i].second;
                    minIndx = i;
                }
            return minIndx;
        };
        auto isAllTrue = [&]() //检查所有的点是不是都已标记为true
        {
            for (const auto& i : status)
            {
                if (i.first == false)
                    return false;
            }
            return true;
        };
        //以前写的实现,这次重构发现完全没必要全部遍历。。dijkstra算法的思想可不就是贪心么。。不知道以前咋想的
        //for (;;)
        //{
        //  status[findMin()].first = true; //每次都将未知的点集中的最小值设为已知
        //  for (int i = 0; i < status.size(); ++i)
        //  {
        //      if (status[i].first == true)
        //      {
        //          for (const auto& adj : vertexs[i].degree)
        //          {
        //              auto desV = (*(adj.ptr)).index;
        //              if (status[i].second + adj.cost < status[desV].second) //对与已知点相连接的点的cost进行更新
        //                  status[desV].second = status[i].second + adj.cost;
        //          }
        //      }
        //  }
        //  if (isAllTrue()) //如果所有点都已知,则退出循环
        //      break;
        //}
        while(!isAllTrue())
        {
            auto minIndex = findMin();
            status[minIndex].first = true; //每次都将未知的点集中的最小值设为已知

                    for (const auto& adj : vertexs[minIndex].degree)
                    {
                        auto desV = (*(adj.ptr)).index;
                        if (status[minIndex].second + adj.cost < status[desV].second) //对与已知点相连接的点的cost进行更新
                            status[desV].second = status[minIndex].second + adj.cost;
                    }


        }

        for (int i = 0; i < status.size(); ++i)
        {
            cout << "vertexIndex :" << i << "   cost: " << status[i].second << endl;
        }
    }

以下为测试代码

    inline void testDijkstra()
    {
        std::cout << "testDijkstra :" << std::endl;
        vector<int>vec;
        //sort(vec.begin(), vec.end(), less());
        typedef JpGraph::Vertex  vertex;
        typedef JpGraph::AdjAcent adj;
        vertex v0(0, 0);
        vertex v1(1, 1);
        vertex v2(2, 1);
        vertex v3(3, 2);
        vertex v4(4, 2);
        vertex v5(5, 3);
        vertex v6(6, 2);
        v0.degree = vector{ adj(1,&v3),adj{ 2,&v1 } };
        v1.degree = vector{ adj{ 3,&v3 },adj{ 2,&v4 } };
        v2.degree = vector{ adj{ 5,&v5 },adj{ 4,&v0 } };
        v3.degree = vector{ adj{ 8,&v5 },adj{ 2,&v2 },adj{ 2,&v4 },adj{ 4,&v6 } };
        v4.degree = vector{ adj{ 6,&v6 }, };
        v5.degree = vector();
        v6.degree = vector{ adj{ 1,&v5 } };
        JpGraph graph;
        graph.buildGraph(vector{v0, v1, v2, v3, v4, v5, v6});
        graph.lowestCost(v0);


    }

以下为top排序,top排序的思想我也不说了,网上一搜都有,以下仅实现

    inline void JpGraph::topSort()
    {
        dequeq;
        for(const Vertex& vertex : vertexs)
        {
            if (vertex.inDegree == 0)//将所有入度为0的点加入
                q.push_back(vertex);
        }
        while(q.size()!=0)//依次将与入度为0的点相连的点加入,并将入度0的点pop掉,此处既是一个DFS
        {
            auto i = q.front(); q.pop_front();
            cout<" "; //通过简单的cout代表访问点
            for(auto& adj : i.degree) 
            {
                auto ptr = adj.ptr;
                --(ptr->inDegree);
                if (ptr->inDegree == 0)
                    q.push_back(*ptr);
            }


        }

    }

以下为测试代码

        inline void testTopSort()
    {
        vector<int>vec;
        //sort(vec.begin(), vec.end(), less());
        typedef JpGraph::Vertex  vertex;
        typedef JpGraph::AdjAcent adj;
        vertex v0(0, 0);
        vertex v1(1, 1);
        vertex v2(2, 1);
        vertex v3(3, 2);
        vertex v4(4, 2);
        vertex v5(5, 3);
        vertex v6(6, 2);
        v0.degree = vector{ adj(1,&v3),adj{ 2,&v1 } };
        v1.degree = vector{ adj{ 3,&v3 },adj{ 2,&v4 } };
        v2.degree = vector{ adj{ 5,&v5 },adj{4,&v0} };
        v3.degree = vector{ adj{ 8,&v5 },adj{ 2,&v2 },adj{2,&v4},adj{ 4,&v6 } };
        v4.degree = vector{ adj{ 6,&v6 },};
        v5.degree = vector();
        v6.degree = vector{ adj{ 1,&v5 } };
        JpGraph graph;
        graph.buildGraph(vector{v0, v1, v2, v3, v4, v5, v6});
        graph.topSort();
    }

DFS和BFS我也不说废话,直接上代码,DFS和BFS的思想网上随便找

inline void JpGraph::BFS(int index)
    {
        map<int, bool>hasVisited;
        deque<int>checkLine;
        for (int i = 0; i < vertexs.size(); ++i)
            hasVisited[i] = false;

        checkLine.push_back(index);
        while(!checkLine.empty())
        {
            int toTravel = checkLine.front();
            checkLine.pop_front();
            if (!hasVisited[toTravel])
            {
                hasVisited[toTravel] = true;
                cout << vertexs[toTravel].index + 1 << " ";

                for(const auto& i : vertexs[toTravel].degree)
                {
                    auto toPAt = *(i.ptr);
                    if(!hasVisited[toPAt.index])
                    {
                        checkLine.push_back(toPAt.index);

                    }
                }
            }
            else;


        }


    }


    inline void JpGraph::DFS(int index)
    {
        map<int, bool>hasVisited;
        for (int i = 0; i < vertexs.size(); ++i)
        {
            hasVisited[i] = false;
        }
        stack<int>stk;
        stk.push(index);
        while (!stk.empty())
        {
            int toTravel = stk.top();
            stk.pop();
            if (hasVisited[toTravel] == false) 
            {
                hasVisited[toTravel] = true;
                cout << vertexs[toTravel].index + 1 << " ";

                for (const auto& i : vertexs[toTravel].degree)
                {
                    auto toPAt = *(i.ptr);
                    if (!hasVisited[toPAt.index])
                    {
                        stk.push(toPAt.index);

                    }

                }

            }
            else;

        }
    }

测试代码

inline void testDFSAndBFS()
    {

        vector<int>vec;
        //sort(vec.begin(), vec.end(), less());
        typedef JpGraph:: Vertex  vertex;
        typedef JpGraph:: AdjAcent adj;
        vertex v0(0, 0);
        vertex v1(1, 1);
        vertex v2(2, 1);
        vertex v3(3, 2);
        vertex v4(4, 2);
        vertex v5(5, 3);
        vertex v6(6, 2);
        v0.degree = vector{ adj(1,&v3),adj{ 2,&v1 } };
        v1.degree = vector{ adj{ 3,&v3 },adj{ 2,&v4 } };
        v2.degree = vector{ adj{ 5,&v5 },adj{ 4,&v0 } };
        v3.degree = vector{ adj{ 8,&v5 },adj{ 2,&v2 },adj{ 2,&v4 },adj{ 4,&v6 } };
        v4.degree = vector{ adj{ 6,&v6 }, };
        v5.degree = vector();
        v6.degree = vector{ adj{ 1,&v5 } };
        JpGraph graph;
        graph.buildGraph(vector{v0, v1, v2, v3, v4, v5, v6});
        std::cout << "testDFS :" << std::endl;
        graph.DFS(0);
        cout << "test BFS" << endl;
        graph.BFS(0);
    }

你可能感兴趣的:(数据结构,c++探究)