深度优先实现 一

image.png

深度优先算法

  • 原料:class LinkStack<T>;
  • 步骤:

    1. 将起始顶点压入栈中
    2. 弹出栈顶顶点 v, 判断是否已经标记(比较:转2; 未标记:转3)
    3. 标记顶点, 并将顶点 v 的邻接顶点压入栈中
    4. 判断栈是否为空(非空:转2; 空:结束)

深度优先算法示例

image.png

image.png

编程实验:深度优先算法

文件:Graph.h

#ifndef GRAPH_H
#define GRAPH_H

#include "Object.h"
#include "SharedPointer.h"
#include "DynamicArray.h"
#include "LinkQueue.h"
#include "LinkStack.h"

namespace DTLib
{

template <typename E>
struct Edge : public Object
{
    int b;
    int e;
    E data;

    Edge(int i=-1, int j=-1)  : b(i), e(j)
    {
    }

    Edge(int i, int j, const E &value) : b(i), e(j), data(value)
    {
    }

    bool operator == (const Edge &obj)
    {
        return (b == obj.b) && (e == obj.e);
    }

    bool operator != (const Edge &obj)
    {
        return !(*this == obj);
    }
};

template <typename V, typename E>
class Graph : public Object
{
public:
    virtual V getVertex(int i) const = 0;
    virtual bool getVertex(int i, V &value) const = 0;
    virtual bool setVertex(int i, const V &value) = 0;
    virtual SharedPointer<Array<int>> getAdjacent(int i) const = 0;
    virtual E getEdge(int i, int j) const = 0;
    virtual bool getEdge(int i, int j, E &value) const = 0;
    virtual bool setEdge(int i, int j, const E &value) = 0;
    virtual bool removeEdge(int i, int j) = 0;
    virtual int vCount() const = 0;
    virtual int eCount() = 0;
    virtual int OD(int i) = 0;
    virtual int ID(int i) = 0;
    virtual int TD(int i)
    {
        return OD(i) + ID(i);
    }

    SharedPointer<Array<int>> BFS(int i)
    {
        DynamicArray<int> *ret = nullptr;

        if ((0 <= i) && (i < vCount()))
        {
            LinkQueue<int> q;
            LinkQueue<int> r;
            DynamicArray<bool> visited(vCount());

            for (int j=0; j<visited.length(); ++j)
            {
                visited[j] = false;
            }

            q.add(i);

            while (q.length() > 0)
            {
                int v = q.front();

                q.remove();

                if (!visited[v])
                {
                    SharedPointer<Array<int>> aj = getAdjacent(v);

                    for (int j=0; j<aj->length(); ++j)
                    {
                        q.add((*aj)[j]);
                    }

                    r.add(v);

                    visited[v] = true;
                }
            }

            ret = toArray(r);
        }
        else
        {
            THROW_EXCEPTION(InvalidParameterExcetion, "Parameter i is invalid ...");
        }

        return ret;
    }

    SharedPointer<Array<int>> DFS(int i)
    {
        DynamicArray<int> *ret = nullptr;

        if ((0 <= i) && (i < vCount()))
        {
            LinkStack<int> s;
            LinkQueue<int> r;
            DynamicArray<bool> visited(vCount());

            for (int j=0; j<visited.length(); ++j)
            {
                visited[j] = false;
            }

            s.push(i);

            while (s.size() > 0)
            {
                int v = s.top();

                s.pop();

                if (!visited[v])
                {
                    SharedPointer<Array<int>> aj = getAdjacent(v);

                    for (int j=aj->length()-1; j>=0; --j)
                    {
                        s.push((*aj)[j]);
                    }

                    r.add(v);

                    visited[v] = true;
                }
            }

            ret = toArray(r);
        }
        else
        {
            THROW_EXCEPTION(InvalidParameterExcetion, "Parameter i is invalid ...");
        }

        return ret;
    }

protected:
    template <typename T>
    DynamicArray<T>* toArray(LinkQueue<T> &queue)
    {
        DynamicArray<T> *ret = new DynamicArray<T>(queue.length());

        if (ret != nullptr)
        {
            for (int i=0; i<ret->length(); ++i, queue.remove())
            {
                ret->set(i, queue.front());
            }
        }
        else
        {
            THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create ret obj ...");
        }

        return ret;
    }
};

}

#endif // GRAPH_H

文件:main.cpp

#include <iostream>
#include "MatrixGraph.h"

using namespace std;
using namespace DTLib;

int main()
{
    MatrixGraph<9, char, int> g;
    const char* VD = "ABEDCGFHI";

    for(int i=0; i<9; i++)
    {
        g.setVertex(0, VD[i]);
    }

    g.setEdge(0, 1, 0);
    g.setEdge(1, 0, 0);

    g.setEdge(0, 3, 0);
    g.setEdge(3, 0, 0);

    g.setEdge(0, 4, 0);
    g.setEdge(4, 0, 0);

    g.setEdge(1, 2, 0);
    g.setEdge(2, 1, 0);

    g.setEdge(1, 4, 0);
    g.setEdge(4, 1, 0);

    g.setEdge(2, 5, 0);
    g.setEdge(5, 2, 0);

    g.setEdge(3, 6, 0);
    g.setEdge(6, 3, 0);

    g.setEdge(4, 6, 0);
    g.setEdge(6, 4, 0);

    g.setEdge(6, 7, 0);
    g.setEdge(7, 6, 0);

    g.setEdge(7, 8, 0);
    g.setEdge(8, 7, 0);

    SharedPointer<Array<int>> sa = g.DFS(0);

    for (int i=0; i<sa->length(); ++i)
    {
        cout << (*sa)[i] << " ";
    }

    cout << endl;

    return 0;
};

输出:

0 1 2 5 4 6 3 7 8

深度优先实现 二

问题: 如何使用二叉树先序遍历的思想遍历图?

递归深度优先

G = v0 + G'

DFG(G) = visited(v0) + DFS(G')
(G'不为空,且 v0 到 G' 有连接)

image.png

  • 定义功能: DFS(graph, vex)

    • 以顶点 vex 为起始顶点深度优先遍历 graph

image.png

编程实验:递归版深度优先算法

文件:main.cpp

#include <iostream>
#include "BTreeNode.h"
#include "ListGraph.h"
#include "MatrixGraph.h"

using namespace std;
using namespace DTLib;

template <typename V, typename E>
void DFP(Graph<V, E> &graph, int i, DynamicArray<bool> &visited)
{
    if (!visited[i])
    {
        cout << i << " ";

        visited[i] = true;

        SharedPointer<Array<int>> aj = graph.getAdjacent(i);

        for (int j=0; j<aj->length(); ++j)
        {
            DFP(graph, (*aj)[j], visited);
        }
    }
}

template <typename V, typename E>
void DFP(Graph<V, E> &graph, int i)
{
    if ((0 <= i) && (i < graph.vCount()))
    {
        DynamicArray<bool> visited(graph.vCount());

        for (int j=0; j<graph.vCount(); ++j)
        {
            visited[j] = false;
        }

        DFP(graph, i, visited);

        cout << endl;
    }
    else
    {
        THROW_EXCEPTION(InvalidParameterExcetion, "Parameter i is invalid ...");
    }
}

int main()
{
    MatrixGraph<9, char, int> g;
    const char* VD = "ABEDCGFHI";

    for(int i=0; i<9; i++)
    {
        g.setVertex(0, VD[i]);
    }

    g.setEdge(0, 1, 0);
    g.setEdge(1, 0, 0);

    g.setEdge(0, 3, 0);
    g.setEdge(3, 0, 0);

    g.setEdge(0, 4, 0);
    g.setEdge(4, 0, 0);

    g.setEdge(1, 2, 0);
    g.setEdge(2, 1, 0);

    g.setEdge(1, 4, 0);
    g.setEdge(4, 1, 0);

    g.setEdge(2, 5, 0);
    g.setEdge(5, 2, 0);

    g.setEdge(3, 6, 0);
    g.setEdge(6, 3, 0);

    g.setEdge(4, 6, 0);
    g.setEdge(6, 4, 0);

    g.setEdge(6, 7, 0);
    g.setEdge(7, 6, 0);

    g.setEdge(7, 8, 0);
    g.setEdge(8, 7, 0);

    SharedPointer< Array<int> > sa = g.DFS(0);

    for(int i=0; i<sa->length(); i++)
    {
        cout << (*sa)[i] << " ";
    }

    cout << endl;

    DFP(g, 0);

    return 0;
}

输出:

0 1 2 5 4 6 3 7 8
0 1 2 5 4 6 3 7 8

小结

  • 深度优先按照"先序遍历的方式"对顶点进行访问
  • 深度优先算法的核心是栈的使用
  • 深度优先和广度优先的唯一不同在于栈或队列的使用
  • 深度优先算法可以使用递归的方式实现

以上内容整理于狄泰软件学院系列课程,请大家保护原创!


[添加递归版深度优先算法]文件:Grap.h

#ifndef GRAPH_H
#define GRAPH_H

#include "Object.h"
#include "SharedPointer.h"
#include "DynamicArray.h"
#include "LinkQueue.h"
#include "LinkStack.h"

namespace DTLib
{

template <typename E>
struct Edge : public Object
{
    int b;
    int e;
    E data;

    Edge(int i=-1, int j=-1)  : b(i), e(j)
    {
    }

    Edge(int i, int j, const E &value) : b(i), e(j), data(value)
    {
    }

    bool operator == (const Edge &obj)
    {
        return (b == obj.b) && (e == obj.e);
    }

    bool operator != (const Edge &obj)
    {
        return !(*this == obj);
    }
};

template <typename V, typename E>
class Graph : public Object
{
public:
    virtual V getVertex(int i) const = 0;
    virtual bool getVertex(int i, V &value) const = 0;
    virtual bool setVertex(int i, const V &value) = 0;
    virtual SharedPointer<Array<int>> getAdjacent(int i) const = 0;
    virtual E getEdge(int i, int j) const = 0;
    virtual bool getEdge(int i, int j, E &value) const = 0;
    virtual bool setEdge(int i, int j, const E &value) = 0;
    virtual bool removeEdge(int i, int j) = 0;
    virtual int vCount() const = 0;
    virtual int eCount() = 0;
    virtual int OD(int i) = 0;
    virtual int ID(int i) = 0;
    virtual int TD(int i)
    {
        return OD(i) + ID(i);
    }

    SharedPointer<Array<int>> BFS(int i)
    {
        DynamicArray<int> *ret = nullptr;

        if ((0 <= i) && (i < vCount()))
        {
            LinkQueue<int> q;
            LinkQueue<int> r;
            DynamicArray<bool> visited(vCount());

            for (int j=0; j<visited.length(); ++j)
            {
                visited[j] = false;
            }

            q.add(i);

            while (q.length() > 0)
            {
                int v = q.front();

                q.remove();

                if (!visited[v])
                {
                    SharedPointer<Array<int>> aj = getAdjacent(v);

                    for (int j=0; j<aj->length(); ++j)
                    {
                        q.add((*aj)[j]);
                    }

                    r.add(v);

                    visited[v] = true;
                }
            }

            ret = toArray(r);
        }
        else
        {
            THROW_EXCEPTION(InvalidParameterExcetion, "Parameter i is invalid ...");
        }

        return ret;
    }

#ifdef DFS_R
    SharedPointer<Array<int>> DFS(int i)  // 递归版深度优先遍历
    {
        DynamicArray<int> *ret = nullptr;

        if ((0 <= i) && (i < vCount()))
        {
            LinkQueue<int> r;
            DynamicArray<bool> visited(vCount());

            for (int j=0; j<vCount(); ++j)
            {
                visited[j] = false;
            }

            DFP(i, visited, r);

            ret = toArray(r);
        }
        else
        {
            THROW_EXCEPTION(InvalidParameterExcetion, "Parameter i is invalid ...");
        }

        return ret;
    }
#else
    SharedPointer<Array<int>> DFS(int i)
    {
        DynamicArray<int> *ret = nullptr;

        if ((0 <= i) && (i < vCount()))
        {
            LinkStack<int> s;
            LinkQueue<int> r;
            DynamicArray<bool> visited(vCount());

            for (int j=0; j<visited.length(); ++j)
            {
                visited[j] = false;
            }

            s.push(i);

            while (s.size() > 0)
            {
                int v = s.top();

                s.pop();

                if (!visited[v])
                {
                    SharedPointer<Array<int>> aj = getAdjacent(v);

                    for (int j=aj->length()-1; j>=0; --j)
                    {
                        s.push((*aj)[j]);
                    }

                    r.add(v);

                    visited[v] = true;
                }
            }

            ret = toArray(r);
        }
        else
        {
            THROW_EXCEPTION(InvalidParameterExcetion, "Parameter i is invalid ...");
        }

        return ret;
    } 
#endif


protected:
    template <typename T>
    DynamicArray<T>* toArray(LinkQueue<T> &queue)
    {
        DynamicArray<T> *ret = new DynamicArray<T>(queue.length());

        if (ret != nullptr)
        {
            for (int i=0; i<ret->length(); ++i, queue.remove())
            {
                ret->set(i, queue.front());
            }
        }
        else
        {
            THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create ret obj ...");
        }

        return ret;
    }

#ifdef DFS_R
    void DFP(int i, DynamicArray<bool> &visited, LinkQueue<int>& queue)
    {
        if (!visited[i])
        {
            queue.add(i);

            visited[i] = true;

            SharedPointer<Array<int>> aj = getAdjacent(i);

            for (int j=0; j<aj->length(); ++j)
            {
                DFP((*aj)[j], visited, queue);
            }
        }
    }
#endif
};

}

#endif // GRAPH_H

以上内容整理于狄泰软件学院系列课程,请大家保护原创!


TianSong
734 声望138 粉丝

阿里山神木的种子在3000年前已经埋下,今天不过是看到当年注定的结果,为了未来的自己,今天就埋下一颗好种子吧