图的节点

//
// Created by Administrator on 2021/8/10.
//

#ifndef C__TEST02_NODE_HPP
#define C__TEST02_NODE_HPP
#include "iostream"
#include <vector>
using namespace std;

class Edge;
class Node {
public:
    int value;
    int in; //入度
    int out; //出度
    vector<Node*> nexts; //出度连接的节点
    vector<Edge*> nextEdges; //出度连接节点的边长
    explicit Node(int value);
};

Node::Node(int value):value(value) {
    in = 0;
    out = 0;
}

class Edge {
public:
    int weight;
    Node *from;
    Node *to;
    Edge(int weight, Node *from, Node *to);
};

Edge::Edge(int weight, Node *from, Node *to) :
        weight(weight), from(from), to(to)
{}

#endif //C__TEST02_NODE_HPP

图及相关算法

//
// Created by Administrator on 2021/8/10.
//

#ifndef C__TEST02_GRAPH_HPP
#define C__TEST02_GRAPH_HPP

#include "Node.hpp"
#include "MyHeap.hpp"
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include <stack>
#include <list>
using namespace std;

class Graph {
public:
    unordered_set<Edge*> edges;
    unordered_map<int, Node*> nodes;
    explicit Graph(vector<vector<int>> &matrix){
        creatGraph(matrix);
    }
    void creatGraph(vector<vector<int>> &matrix);

    void BFS(Node* head);
    void DFS(Node* head);

    Node* getMinDistanceAndUnuseSelecedNode(
            unordered_map<Node*, int> &distanceMap,
            unordered_set<Node*> &touchSet);
    unordered_map<Node*, int> dijkstral(Node* head);
    unordered_map<Node*, int> dijkstral(Node* head, int heapSize);
};

void Graph::creatGraph(vector<vector<int>> &matrix){
    for(vector<int> it:matrix){
        //获得from和to节点,以及权值
        int from = it[0];
        int to = it[1];
        int weight = it[2];

        //如果from节点或者to节点没创建,则创建并记录两个节点
        if(nodes.find(from) == nodes.end()){
            nodes[from] = new Node(from);
        }
        if(nodes.find(to) == nodes.end()){
            nodes[to] = new Node(to);
        }

        //获得from和to节点
        Node* fromNode = nodes[from];
        Node* toNode = nodes[to];
        Edge* weightEdge = new Edge(weight, fromNode, toNode);
        fromNode->out++;
        toNode->in++;
        fromNode->nextEdges.push_back(weightEdge);
        fromNode->nexts.push_back(toNode);

        edges.insert(weightEdge);
    }
}

//宽度优先搜索
void Graph::BFS(Node *head){
    unordered_set<Node*> hashSet;
    queue<Node*> q;
    q.push(head);
    hashSet.insert(head);
    while(!q.empty()){
        Node *cur = q.front();
        cout<<cur->value<<endl;
        q.pop();
        for(Node* next:cur->nexts){
            if(hashSet.find(next) == hashSet.end()){
                q.push(next);
                hashSet.insert(next);
            }
        }
    }

}
//广度优先搜索
void Graph::DFS(Node *head) {
    stack<Node*> s;
    unordered_set<Node*> hashSet;
    s.push(head);
    hashSet.insert(head);
    cout<<head->value<<endl;
    while(!s.empty()){
        Node* cur = s.top();
        s.pop();
        for(Node* next:cur->nexts){
            if(hashSet.find(next) == hashSet.end()){
                s.push(cur);
                s.push(next);
                cout<<next->value<<endl;
                hashSet.insert(next);
                break;
            }
        }
    }
}

Node* Graph::getMinDistanceAndUnuseSelecedNode(
        unordered_map<Node*, int> &distanceMap,
        unordered_set<Node*> &touchSet){

    int minDistance = INT_MAX;
    Node* minNode = nullptr;
    for(auto & it : distanceMap){
        Node* distanceNode = it.first;
        int distance = it.second;
        if(touchSet.find(distanceNode) == touchSet.end() && distance < minDistance){
            minDistance = distance;
            minNode = distanceNode;
        }
    }

    return minNode;
}
unordered_map<Node*, int> Graph::dijkstral(Node* head){

    unordered_map<Node*, int> distanceMap;
    unordered_set<Node*> touchSet;

    distanceMap[head] = 0;
    Node* minNode = getMinDistanceAndUnuseSelecedNode(
            distanceMap, touchSet);

    while(minNode != nullptr){
        //获取当前距离最小的节点的距离
        int distance = distanceMap[minNode];
        //遍历当前节点的所有边
        for(auto edge:minNode->nextEdges){
            //取得该边的达到节点
            Node* toNode = edge->to;
            //如果到达节点没有记录,则记录minNode的距离加边的距离
            if(distanceMap.find(toNode) == distanceMap.end()){
                distanceMap[toNode] = edge->weight + distance;
            }
            //如果记录了,比较记录值和上面边距离+minNode距离
            distanceMap[toNode] = min(distanceMap[toNode],
                                      edge->weight + distance);
        }
        //此时选择的最小节点已经处理完毕了,可以放在touchSet里
        touchSet.insert(minNode);
        //继续更新获取下一个最小节点,当所有节点都touch了返回空节点
        minNode = getMinDistanceAndUnuseSelecedNode(distanceMap, touchSet);
    }
   return distanceMap;
}

unordered_map<Node*, int> Graph::dijkstral(Node* head, int heapSize){
    MyHeap *nodeHeap = new MyHeap(heapSize);
    unordered_map<Node*, int> result;
    nodeHeap->updateOrIngore(head, 0);

    while(!nodeHeap->isEmpty()){
        NodeRecord* record = nodeHeap->pop();
        Node* cur = record->node;
        int distance = record->distance;
        for(Edge* edge : cur->nextEdges){
            nodeHeap->updateOrIngore(edge->to,
                                     distance + edge->weight);
        }
        result[cur] = distance;
    }
    return result;
}

list<Node*> sortedTopology(Graph* graph) {
    unordered_map<Node*, int> inMap;
    queue<Node*> zeroInQueue;
    for (auto &it : graph->nodes) {
        auto node = it.second;
        inMap[node] =  node->in;
        if (node->in == 0) {
            zeroInQueue.push(node);
        }
    }
    list<Node*> result;
    while (!zeroInQueue.empty()) {
        Node* cur = zeroInQueue.front();
        zeroInQueue.pop();
        result.push_back(cur);
        for (Node* next : cur->nexts) {
            inMap[next] = inMap[next] - 1;
            if (inMap[next] == 0) {
                zeroInQueue.push(next);
            }
        }
    }
    return result;
}
#endif //C__TEST02_GRAPH_HPP

posted @   蘑菇王国大聪明  阅读(49)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示