欢迎光临散文网 会员登陆 & 注册

数据结构与算法基础(青岛大学-王卓)

2023-07-31 21:01 作者:doodoook  | 我要投稿

/**

 * @brief 邻接多重表

 * 解决无向图,每条边都要存储两遍的问题

 */

#include "doo_graph.hpp"

#include <memory>

#include <vector>

#include <algorithm>

#include <iostream>

namespace doo::graph

{

    /// @brief 边的定义

    /// @tparam Info

    template <typename Info>

    struct _edge

    {

        Info info;

        int headvex_idx;

        int tailvex_idx;

        std::shared_ptr<_edge<Info>> head_node;

        std::shared_ptr<_edge<Info>> tail_node;


        _edge() : info(Info()), headvex_idx(-1), tailvex_idx(-1),

                  head_node(nullptr), tail_node(nullptr) {}


        _edge(int hidx, int tidx, const Info &inf)

            : info(inf), headvex_idx(hidx), tailvex_idx(tidx),

              head_node(nullptr), tail_node(nullptr) {}

        /// @brief 获取节点的相邻顶点的索引值

        /// @param idx

        /// @return

        int get_adjacenyIndex(int idx) const

        {

            return (idx == headvex_idx) ? tailvex_idx : headvex_idx;

        }

        /// @brief 获取顶点的边链表的下一个边

        /// @param idx

        /// @return

        std::shared_ptr<_edge<Info>> &get_next(int idx)

        {

            return (idx == headvex_idx) ? head_node : tail_node;

        }

    };


    template <typename Info>

    std::ostream &operator<<(std::ostream &os, const _edge<Info> &edg)

    {

        return os << "{[" << edg.headvex_idx << ":" << edg.tailvex_idx << "]"

                  << edg.info << "}";

    }

    /// @brief 边的定义

    /// @tparam Info

    template <typename Info>

    using edge = std::shared_ptr<_edge<Info>>;

    /// @brief 生成一个条边

    /// @tparam T

    /// @param hidx

    /// @param tidx

    /// @param inf

    /// @return

    template <typename T>

    edge<T> make_edge(int hidx, int tidx, const T &inf)

    {

        return std::make_shared<_edge<T>>(hidx, tidx, inf);

    }


    template <typename Info, typename ObjFun>

    void adj_mulTab_travelNode(edge<Info> node, int vexIdx, ObjFun proc)

    {

        while (node)

        {

            proc(node);

            node = node->get_next(vexIdx);

        }

    }

    /// @brief 顶点边链表添加一条边

    /// @tparam Info

    /// @param lst

    /// @param vexidx

    /// @param newNode

    template <typename Info>

    void adj_mulTab_push_back(edge<Info> &lst,

                              int vexidx,

                              const edge<Info> &newNode)

    {

        if (lst == nullptr)

        {

            lst = newNode;

        }

        else

        {

            edge<Info> tmp = lst;

            edge<Info> tt = nullptr;

            while (tmp)

            {

                tt = (*tmp).get_next(vexidx);

                if (tt)

                    tmp = tt;

                else

                    break;

            }

            tmp->get_next(vexidx) = newNode;

        }

    }


    /// @brief 打印边节点信息

    /// @tparam T

    /// @tparam Info

    template <typename T, typename Info>

    class adj_mulTab_print

    {

    public:

        adj_mulTab_print(std::ostream &os) : m_os(os) {}

        void operator()(const edge<Info> &edge) const

        {

            m_os << *edge << " "

                 << "->";

        }


    private:

        std::ostream &m_os;

    };

    /// @brief 获得顶点的邻接顶点的索引的函数对象(记录在vector引用中)

    /// @tparam T

    /// @tparam Info

    template <typename T, typename Info>

    class adj_mulTab_getAdjacenyIdx

    {

    public:

        adj_mulTab_getAdjacenyIdx(std::vector<int> &vet, int vexIdx)

            : m_vet(vet), m_vexidx(vexIdx) {}

        void operator()(const edge<Info> &edge) const

        {

            m_vet.push_back(edge->get_adjacenyIndex(m_vexidx));

        }


    private:

        std::vector<int> &m_vet;

        int m_vexidx;

    };


    /// @brief 链接多重表 (用来表示无向图)

    /// @tparam T

    /// @tparam Info

    template <typename T, typename Info>

    class adjacenty_mulTab : virtual public IGraph_search<T>

    {

    public:

        adjacenty_mulTab() : m_array() {}

        explicit adjacenty_mulTab(const std::initializer_list<T> &lst)

            : adjacenty_mulTab()

        {

            for (auto val : lst)

                m_array.push_back(_item(val));

        }

        void set_edge(const T &head, const T &tail, const Info &inf)

        {

            int hidx = get_index(head);

            int tidx = get_index(tail);

            if (hidx == -1 || tidx == -1)

                return;

            _set_edge(hidx, tidx, inf);

        }

        //------------IGraph_search接口--------------------------

        const T &get_value(int vexIdx) const override

        {

            return m_array[vexIdx].value;

        }


        std::vector<int> get_ajacenyNode(int vexIdx) const override

        {

            std::vector<int> tmpVet;

            adj_mulTab_travelNode(m_array[vexIdx].arcs, vexIdx,

                                  adj_mulTab_getAdjacenyIdx<T, Info>(tmpVet, vexIdx));

            return tmpVet;

        }


    private:

        struct _item

        {

            T value;

            edge<Info> arcs; // 边节点

            _item() : value(T()), arcs(nullptr) {}

            explicit _item(const T &val) : value(val), arcs(nullptr) {}

        };


    private:

        int get_index(const T &val) const

        {

            int idx = 0;

            for (auto im : m_array)

            {

                if (im.value == val)

                    return idx;

                ++idx;

            }

            return -1;

        }


        void _set_edge(int hidx, int tidx, const Info &inf)

        {

            edge<Info> newNode = make_edge(hidx, tidx, inf);

            adj_mulTab_push_back(m_array[hidx].arcs,

                                 hidx,

                                 newNode);

            adj_mulTab_push_back(m_array[tidx].arcs,

                                 tidx,

                                 newNode);

        }


    private:

        std::vector<_item> m_array;

        //---------------友元函数------------------------

        friend std::ostream &operator<<(std::ostream &os, const adjacenty_mulTab &multab)

        {

            int idx = 0;

            for (auto val : multab.m_array)

            {

                os << idx << "[" << val.value << "]-->";

                adj_mulTab_travelNode(val.arcs, idx, adj_mulTab_print<T, Info>(os));

                os << '\n';

                ++idx;

            }

            return os;

        }

    };


}


////接口定义

 /// @brief 图的搜索接口

    template <typename T>

    struct IGraph_search

    {

        virtual const T &get_value(int vexIdx) const = 0;

        virtual std::vector<int> get_ajacenyNode(int vexIdx) const = 0;

    };


///DFS算法

#pragma once

/**

 * @brief 图的深度优先遍历

 *

 */

#include "doo_AMGraph.hpp"

#include <bitset>

#include <iostream>

#include <queue>

namespace doo::graph

{

    /// @brief 深度优先遍历图

    /// @tparam T

    /// @tparam N

    /// @param graph

    /// @param vexIdx

    /// @param bset

    template <typename T, int N>

    void dfs(const IGraph_search<T> &graph, int vexIdx, std::bitset<N> &bset)

    {

        std::cout << graph.get_value(vexIdx) << " ";

        bset.set(vexIdx);

        std::vector<int> vet = graph.get_ajacenyNode(vexIdx);

        for (int i = 0; i < vet.size(); i++)

        {

            if (!bset.test(vet[i]))

                dfs<T, N>(graph, vet[i], bset);

        }

    }

    /// @brief 广度优先遍历图

    /// @tparam T

    /// @tparam N

    /// @param graph

    /// @param vexIdx

    /// @param bset

    template <typename T, int N>

    void bfs(const IGraph_search<T> &graph,

             int vexIdx,

             std::bitset<N> &bset)

    {

        std::queue<int> que;

        que.push(vexIdx);

        while (!que.empty())

        {

            int vidx = que.front();

            que.pop();

            if (!bset.test(vidx))

                std::cout << graph.get_value(vidx) << " ";

            bset.set(vidx);

            std::vector<int> vet = graph.get_ajacenyNode(vidx);

            for (int i = 0; i < vet.size(); i++)

                if (!bset.test(vet[i]))

                    que.push(vet[i]);

        }

    }

}


//-------------------------------用法---------------

 adjacenty_mulTab<char, int> multab({'A', 'B', 'C', 'D', 'E'});

    multab.set_edge('A', 'B', 0);

    multab.set_edge('A', 'D', 0);

    // multab.set_edge('A','C',0);

    multab.set_edge('B', 'C', 0);

    multab.set_edge('B', 'E', 0);

    multab.set_edge('C', 'E', 0);

    multab.set_edge('C', 'D', 0);

    cout << multab << endl;

///测试深度优先和广度优先

 bitset<5> bset;

    dfs<char, 5>(multab, 0, bset);

    CR;

    bset.reset();

    bfs<char, 5>(multab, 0, bset);

    CR;

数据结构与算法基础(青岛大学-王卓)的评论 (共 条)

分享到微博请遵守国家法律