这里写图片描述

Graph.h

#pragma once
#include<iostream>
#include<string>
#include<queue>
#include<stack>
using namespace std;
#define MAXN 100   //最大顶点数
#define PERRROR perror("Allocate dynamic memory");

typedef struct Edge   //边
{
    int adjvexID;   //邻接点id
    int weight;
    Edge* next;
}*EdgePtr;

typedef struct Node  //顶点
{
    string name;  //顶点名称
    int id;
    EdgePtr firstedg;  //边表头指针
}*NodePtr;

struct UnWeightedTable   //路径
{
    bool Known;
    int dist;
    int path;
};

class Graph
{
private:
    Node Vertex[MAXN];     //顶点集合
    bool visited[MAXN];      //遍历用
    int Indegree[MAXN];     //记录每个顶点的入度
    int NameToID(string str);
    void InitIndegree();
    void DFS(int i);
    void PrintPath(int vertex, UnWeightedTable* table);

public:
    int numVertexs;   //点数
    int numEdges;     //边数
    void DFSTraverse();  //DFS遍历
    void BFSTraverse();  //BFS遍历
    void TopSort();    //拓扑排序
    void UnWeightedPath(string source, string dest);//无权最短路径
    void WeightedPath(string source, string dest); //带权最短路径
    Graph();
    ~Graph();

    void MakeGraph();
    void PrintGraph();
};

Graph::Graph()
{
    numVertexs = numEdges = 0;
}

Graph::~Graph()
{
    EdgePtr temp;
    for (int i = 0; i < numVertexs; i++)
    {
        while (Vertex[i].firstedg)
        {
            temp = Vertex[i].firstedg;
            Vertex[i].firstedg = Vertex[i].firstedg->next;
            free(temp);
        }
    }
}

int Graph::NameToID(string str)
{
    int i = 0;
    for (i = 0; i < numVertexs; i++)
    {
        if (!Vertex[i].name.compare(str))
            break;
    }
    if (i < numVertexs)
        return i;
    else
        cout << "Wrong Vertex name: " << str << endl;
    return -1;
}

//构建图
void Graph::MakeGraph()
{
    int v, e, w;
    string s, t;
    cout << "输入顶点数和边数:\n";
    cin >> v >> e;
    numVertexs = v;
    numEdges = e;

    cout << "输入顶点名称:\n";
    for (int i = 0; i < v; i++)
    {
        cin >> Vertex[i].name;
        Vertex[i].id = i;
        Vertex[i].firstedg = NULL;
    }

    cout << "输入边的信息:\n";
    for (int i = 0; i < e; i++)
    {
        cin >> s >> t >> w;

        //申请一个新的边
        EdgePtr edge = (EdgePtr)malloc(sizeof(Edge));
        if (edge == NULL)
            PERRROR;

        edge->adjvexID = NameToID(t);
        edge->weight = w;
        edge->next = Vertex[NameToID(s)].firstedg;
        Vertex[NameToID(s)].firstedg = edge;

        无向图同时添加2条边
        申请一个新的边
        //EdgePtr edge1 = (EdgePtr)malloc(sizeof(Edge));
        //if (edge1 == NULL)
        //  PERRROR;

        //edge1->adjvexID = NameToID(s);
        //edge1->weight = w;
        //edge1->next = Vertex[NameToID(t)].firstedg;
        //Vertex[NameToID(s)].firstedg = edge1;
    }
}

//输出图
void Graph::PrintGraph()
{
    EdgePtr p;
    cout << "顶点数: " << numVertexs << "   边数: " << numEdges << endl;
    for (int i = 0; i < numVertexs; i++)
    {
        cout << Vertex[i].name << ": ";
        p = Vertex[i].firstedg;
        while (p)
        {
            cout << Vertex[p->adjvexID].name << "(" << p->weight << ") ";
            p = p->next;
        }
        cout << endl;
    }
}

//深度优先遍历
void Graph::DFS(int i)
{
    visited[i] = true;
    cout << Vertex[i].name << " ";

    EdgePtr p = Vertex[i].firstedg;
    while (p)
    {
        if (!visited[p->adjvexID])
            DFS(p->adjvexID);
        p = p->next;
    }
}

void Graph::DFSTraverse()
{
    cout << "DFS: ";
    memset(visited, false, numVertexs*sizeof(bool));
    for (int i = 0; i < numVertexs; i++)
    {
        if (!visited[i])
            DFS(i);
    }
    cout << endl;
}

//广度优先遍历
void Graph::BFSTraverse()
{
    cout << "BFS: ";
    EdgePtr p;
    queue<Node> q;
    memset(visited, false, numVertexs*sizeof(bool));
    for (int i = 0; i < numVertexs; i++)
    {
        if (!visited[i])
        {
            visited[i] = true;
            cout << Vertex[i].name << " ";
            q.push(Vertex[i]);
            while (!q.empty())
            {
                p = q.front().firstedg;
                q.pop();
                while (p)
                {
                    if (!visited[p->adjvexID])
                    {
                        visited[p->adjvexID] = true;
                        cout << Vertex[p->adjvexID].name << " ";
                        q.push(Vertex[p->adjvexID]);
                    }
                    p = p->next;
                }
            }
        }
    }
    cout << endl;
}

void Graph::InitIndegree()
{
    EdgePtr p;
    memset(Indegree, 0, numVertexs*sizeof(int));   //暂且用来寻找那些入度为0的顶点
    for (int i = 0; i < numVertexs; i++)
    {
        p = Vertex[i].firstedg;
        while (p)
        {
            Indegree[p->adjvexID]++;
            p = p->next;
        }
    }
}

//拓扑排序
void Graph::TopSort()
{
    cout << "TopSort: ";
    int count = 0;
    EdgePtr p;
    queue<int> q;
    int temp;

    InitIndegree();
    //初始化入度为0的入队
    for (int i = 0; i < numVertexs; i++)
    {
        if (!Indegree[i])
        {
            q.push(i);
        }
    }

    while (!q.empty())
    {
        temp = q.front();
        q.pop();
        cout << Vertex[temp].name << " ";
        count++;

        p = Vertex[temp].firstedg;
        while (p)
        {
            Indegree[p->adjvexID]--;
            if (!Indegree[p->adjvexID])
                q.push(p->adjvexID);
            p = p->next;
        }
    }

    if (!count == numVertexs)
        cout << "Graph has a cycle";
    cout << endl;
}

//无权图求最短路径
void Graph::UnWeightedPath(string source, string dest)
{
    UnWeightedTable* table = (UnWeightedTable*)malloc(numVertexs*sizeof(UnWeightedTable));;
    for (int i = 0; i < numVertexs; i++)
    {
        table[i].dist = INT16_MAX;
        table[i].path = i;
    }

    queue<int> q;
    q.push(NameToID(source));
    table[NameToID(source)].dist = 0;

    int temp;
    EdgePtr p;

    while (!q.empty())
    {
        temp = q.front();
        q.pop();

        p = Vertex[temp].firstedg;
        while (p)
        {
            if (table[p->adjvexID].dist == INT16_MAX)
            {
                table[p->adjvexID].dist = table[temp].dist + 1;
                table[p->adjvexID].path = temp;
                q.push(p->adjvexID);
            }
            p = p->next;
        }
    }
    stack<string> paths;
    temp = NameToID(dest);
    while (temp != NameToID(source))
    {
        paths.push(Vertex[temp].name);
        temp = table[temp].path;
    }
    paths.push(Vertex[temp].name);

    cout << "Paths: ";
    while (!paths.empty())
    {
        cout << paths.top() << " ";
        paths.pop();
    }
    cout<<"Length: " <<table[NameToID(dest)].dist<< endl;
    free(table);
}

void Graph::PrintPath(int vertex, UnWeightedTable* table)
{
    if (table[vertex].path != -1)
    {
        PrintPath(table[vertex].path, table);
    }
    cout << Vertex[vertex].name << " ";
}

//有权图求最短路径
void Graph::WeightedPath(string source, string dest)
{
    UnWeightedTable* table = (UnWeightedTable*)malloc(numVertexs*sizeof(UnWeightedTable));;
    for (int i = 0; i < numVertexs; i++)
    {
        table[i].Known = false;
        table[i].dist = INT32_MAX;
        table[i].path = i;
    }
    table[NameToID(source)].dist = 0;
    table[NameToID(source)].path = -1;

    int i,smallest = INT32_MAX;
    int smallID = -1;
    EdgePtr p;

    for (;;)
    {
        smallest = INT32_MAX;
        smallID = -1;
        for (i = 0; i < numVertexs; i++)
        {
            if (!table[i].Known && table[i].dist < smallest)
            {
                smallest = table[i].dist;
                smallID = i;
            }
        }
        if (smallID == -1)
            break;

        table[smallID].Known = true;
        p = Vertex[smallID].firstedg;
        while (p)
        {
            if( ! table[p->adjvexID].Known )
                if (table[smallID].dist + p->weight < table[p->adjvexID].dist)
                {
                    table[p->adjvexID].dist = table[smallID].dist + p->weight;
                    table[p->adjvexID].path = smallID;
                }
            p = p->next;
        }
    }
    PrintPath(NameToID(dest), table);
    cout <<"Length: "<<table[NameToID(dest)].dist<< endl;
    free(table);
}

Graph.cpp

#include"Graph.h"
#include<iostream>
using namespace std;

/*
输入:
7 12
v1 v2 v3 v4 v5 v6 v7
v1 v2 2
v1 v3 4
v1 v4 1
v2 v4 3
v2 v5 10
v3 v6 5
v4 v3 2
v4 v5 2
v4 v6 8
v4 v7 4
v5 v7 6
v7 v6 1

*/

int main()
{
    Graph G;
    G.MakeGraph();
    G.DFSTraverse();
    G.BFSTraverse();
    G.TopSort();
    G.UnWeightedPath("v1", "v6");
    G.WeightedPath("v1", "v5");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值