数据结构——图

图,主要内容:深度优先遍历,广度优先遍历,最小生成树。文中代码均已在VS2015上测试,空指针均为nullptr(C++11)。参考来源:慕课网

分类:有向图。无向图

顶点,弧,弧头。弧尾,权值,出度,入度,顶点,边,邻接点,连通图,完全图【边数=n(n-1)/2 】,生成树【边数=n-1】

核心:图的遍历,最小生成树

存储结构

图的存储结构:邻接矩阵,邻接表,十字链表,邻接多重表

邻接矩阵--数组存储

struct Node
{
    顶点索引;
    顶点数据;
};

struct Map
{
    顶点数组;
    邻接矩阵;
};

邻接表--链式存储

struct Node
{
    顶点索引;
    该顶点弧链表的头结点;
    顶点数据;
}

struct Arc
{
    指向的顶点索引;
    指向下一条弧的指针;
    弧信息;
}

struct Map
{
    顶点数组;
}

十字链表--链式存储

struct Node
{
    顶点索引;
    顶点数据;
    第一条入弧结点指针;
    第一条出弧结点指针;
}

struct Arc
{
    弧尾顶点索引;
    弧头顶点索引;
    指向下一条弧头相同的弧的指针;
    指向下一条弧尾相同的弧的指针;
    弧信息;
}

struct Map
{
    顶点数组;
}

邻接多重表--链式存储(无向图)

struct Node
{
    顶点索引;
    顶点数据;
    第一条边结点指针;
}

struct Arc
{
    顶点A索引;
    顶点B索引;
    连接A的下一条边的指针;
    连接A的下一条边的指针;
    边信息;
}

struct Map
{
    顶点数组;
}

图的遍历

深度优先搜索(前序遍历,根左右),广度优先搜索(层级搜索)

        A
       /  \
      B    D
     / \   / \
    C  F  G - H
     \ /
      E
深度优先遍历:A B C E F D G H
广度优先遍历:A B D C F G H E

邻接矩阵遍历代码:
【Node.h】

#ifndef NODE_H
#define NODE_H

class Node
{
public:
    Node(char data = 0);
    char m_cData;
    bool m_bIsVisited;
};

#endif // !NODE_H

【Node.cpp】

#include "Node.h"

Node::Node(char data)
{
    m_cData = data;
    m_bIsVisited = false;
}

【CMap.h】

#ifndef CMAP_H
#define CMAP_H
#include <vector>
#include "Node.h"
#include <iostream>
using namespace std;
class CMap
{
public:
    CMap(int capacity);
    ~CMap();
    bool addNode(Node *pNode);//向图中加入顶点
    void resetNode();//重置顶点
    bool setValueToMatrixForDirectedGraph(int row, int col, int val = 1);//为有向图设置邻接矩阵
    bool setValueToMatrixForUndirectedGraph(int row, int col, int val = 1);//为无向图设置邻接矩阵
    void printMatrix();//打印邻接矩阵
    void depthFirstTraverse(int nodeIndex);//深度优先遍历
    void breadthFirstTraverse(int nodeIndex);//广度优先遍历
private:
    bool getValueFromMatrix(int row, int col, int &val);//从矩阵中获取权值
    void breadthFirstTraverseImpl(vector<int>preVec);//广度优先遍历实现函数
private:
    int m_iCapacity;//图中最多可以容纳的顶点数
    int m_iNodeCount;//已经添加的顶点个数
    Node *m_pNodeArray;//用来存放顶点数组
    int *m_pMatrix;//用来存放邻接矩阵
};
#endif // !CMAP_H

【CMap.cpp】

#include "CMap.h"

CMap::CMap(int capacity)
{
    m_iCapacity = capacity;
    m_iNodeCount = 0;
    m_pNodeArray = new Node[m_iCapacity];
    m_pMatrix = new int[m_iCapacity *m_iCapacity];
    memset(m_pMatrix, 0, m_iCapacity*m_iCapacity * sizeof(int));
    /*for (int i = 0; i < m_iCapacity *m_iCapacity; i++)
    {
        m_pMatrix[i] = 0;
    }*/
}

CMap::~CMap()
{
    delete[]m_pNodeArray;
    delete[]m_pMatrix;
}

bool CMap::addNode(Node * pNode)
{
    if (pNode == nullptr)
    {
        return false;
    }
    m_pNodeArray[m_iNodeCount].m_cData = pNode->m_cData;
    m_iNodeCount++;
    return true;
}

void CMap::resetNode()
{
    for (int i = 0;i < m_iNodeCount;i++)
    {
        m_pNodeArray[i].m_bIsVisited = false;
    }
}

bool CMap::setValueToMatrixForDirectedGraph(int row, int col, int val)
{
    if (row<0||row>=m_iCapacity)
    {
        return false;
    }
    if (col<0 || col >= m_iCapacity)
    {
        return false;
    }
    m_pMatrix[row *m_iCapacity + col] = val;
    return true;
}

bool CMap::setValueToMatrixForUndirectedGraph(int row, int col, int val)
{
    if (row<0 || row >= m_iCapacity)
    {
        return false;
    }
    if (col<0 || col >= m_iCapacity)
    {
        return false;
    }
    m_pMatrix[row *m_iCapacity + col] = val;
    m_pMatrix[col *m_iCapacity + row] = val;
    return true;
}

void CMap::printMatrix()
{
    for (int i = 0; i < m_iCapacity; i++)
    {
        for (int k = 0; k < m_iCapacity; k++)
        {
            cout << m_pMatrix[i*m_iCapacity + k] << " ";
        }
        cout << endl;
    }
}

void CMap::depthFirstTraverse(int nodeIndex)
{
    int value = 0;
    cout << m_pNodeArray[nodeIndex].m_cData << " ";
    m_pNodeArray[nodeIndex].m_bIsVisited = true;
    for (int i = 0;i < m_iCapacity;i++)
    {
        getValueFromMatrix(nodeIndex, i, value);
        if (value == 1)
        {
            if (m_pNodeArray[i].m_bIsVisited)
            {
                continue;
            }
            else
            {
                depthFirstTraverse(i);
            }
        }
        else
        {
            continue;
        }
    }
}

void CMap::breadthFirstTraverse(int nodeIndex)
{
    cout << m_pNodeArray[nodeIndex].m_cData << " ";
    m_pNodeArray[nodeIndex].m_bIsVisited = true;
    vector<int>curVec;
    curVec.push_back(nodeIndex);
    breadthFirstTraverseImpl(curVec);
}

bool CMap::getValueFromMatrix(int row, int col, int & val)
{
    if (row<0 || row >= m_iCapacity)
    {
        return false;
    }
    if (col<0 || col >= m_iCapacity)
    {
        return false;
    }
    val = m_pMatrix[row *m_iCapacity + col];
    return true;
}

void CMap::breadthFirstTraverseImpl(vector<int> preVec)
{
    int value = 0;
    vector<int> curVec;
    for (int j = 0; j < (int)preVec.size(); j++)
    {
        for (int i = 0; i < m_iCapacity; i++)
        {
            getValueFromMatrix(preVec[j], i, value);
            if (value!=0)
            {
                if (m_pNodeArray[i].m_bIsVisited)
                {
                    continue;
                }
                else
                {
                    cout << m_pNodeArray[i].m_cData << " ";
                    m_pNodeArray[i].m_bIsVisited = true;
                    curVec.push_back(i);
                }
            }
        }
    }
    if (curVec.size()==0)
    {
        return;
    }
    else
    {
        breadthFirstTraverseImpl(curVec);
    }
}

【main.cpp】

#include "CMap.h"
int main(void)
{
    CMap *pMap = new CMap(8);
    Node *pNodeA = new Node('A');
    Node *pNodeB = new Node('B');
    Node *pNodeC = new Node('C');
    Node *pNodeD = new Node('D');
    Node *pNodeE = new Node('E');
    Node *pNodeF = new Node('F');
    Node *pNodeG = new Node('G');
    Node *pNodeH = new Node('H');
    pMap->addNode(pNodeA);
    pMap->addNode(pNodeB);
    pMap->addNode(pNodeC);
    pMap->addNode(pNodeD);
    pMap->addNode(pNodeE);
    pMap->addNode(pNodeF);
    pMap->addNode(pNodeG);
    pMap->addNode(pNodeH);
    pMap->setValueToMatrixForUndirectedGraph(0, 1);
    pMap->setValueToMatrixForUndirectedGraph(0, 3);
    pMap->setValueToMatrixForUndirectedGraph(1, 2);
    pMap->setValueToMatrixForUndirectedGraph(1, 5);
    pMap->setValueToMatrixForUndirectedGraph(3, 6);
    pMap->setValueToMatrixForUndirectedGraph(3, 7);
    pMap->setValueToMatrixForUndirectedGraph(6, 7);
    pMap->setValueToMatrixForUndirectedGraph(2, 4);
    pMap->setValueToMatrixForUndirectedGraph(2, 5);
    pMap->printMatrix();
    cout << endl;
    pMap->depthFirstTraverse(0);
    cout << endl;
    pMap->resetNode();
    pMap->breadthFirstTraverse(0);
    cout << endl;
    return 0;
}

最小生成树

普里姆(Prim)算法;克鲁斯卡尔(Kruskal)算法

普里姆算法

基本思想

普里姆算法的基本思想:普里姆算法是一种构造最小生成树的算法,它是按逐个将顶点连通的方式来构造最小生成树的。

从连通网络N = { V, E }中的某一顶点u0出发,选择与它关联的具有最小权值的边(u0, v),将其顶点加入到生成树的顶点集合U中。以后每一步从一个顶点在U中,而另一个顶点不在U中的各条边中选择权值最小的边(u, v),把该边加入到生成树的边集TE中,把它的顶点加入到集合U中。如此重复执行,直到网络中的所有顶点都加入到生成树顶点集合U中为止。

假设G=(V,E)是一个具有n个顶点的带权无向连通图,T(U,TE)是G的最小生成树,其中U是T的顶点集,TE是T的边集,则构造G的最小生成树T的步骤如下:

(1)初始状态,TE为空,U={v0},v0∈V;

(2)在所有u∈U,v∈V-U的边(u,v)∈E中找一条代价最小的边(u′,v′)并入TE,同时将v′并入U;

重复执行步骤(2)n-1次,直到U=V为止。

在普里姆算法中,为了便于在集合U和(V-U)之间选取权值最小的边,需要设置两个辅助数组closest和lowcost,分别用于存放顶点的序号和边的权值。

对于每一个顶点v∈V-U,closest[v]为U中距离v最近的一个邻接点,即边(v,closest[v])是在所有与顶点v相邻、且其另一顶点j∈U的边中具有最小权值的边,其最小权值为lowcost[v],即lowcost[v]=cost[v][closest[v]],采用邻接表作为存储结构:
设置一个辅助数组closedge[]:

lowcost域存放生成树顶点集合内顶点到生成树外各顶点的各边上的当前最小权值;

adjvex域记录生成树顶点集合外各顶点距离集合内哪个顶点最近(即权值最小)。

克鲁斯卡尔算法

基本思想

克鲁斯卡尔算法是在剩下的所有未选取的边中,找最小边,如果和已选取的边构成回路,则放弃,选取次小边。

克鲁斯卡尔算法的时间复杂度为O(eloge)(e为网中边的数目),因此它相对于普里姆算法而言,适合于求边稀疏的网的最小生成树。

实例

【Node.h】

#ifndef NODE_H
#define NODE_H

class Node
{
public:
    Node(char data = 0);
    char m_cData;
    bool m_bIsVisited;
};

#endif // !NODE_H

【Node.cpp】

#include "Node.h"

Node::Node(char data)
{
    m_cData = data;
    m_bIsVisited = false;
}

【Edge.h】

#ifndef EDGE_H
#define EDGE_H
class Edge
{
public:
    Edge(int nodeIndexA = 0, int nodeIndexB = 0, int weightValue = 0);
    int m_iNodeIndexA;
    int m_iNodeIndexB;
    int m_iWeightValue;
    bool m_bSelected;
};
#endif // !EDGE_H

【Edge.cpp】

#include "Edge.h"

Edge::Edge(int nodeIndexA, int nodeIndexB, int weightValue)
{
    m_iNodeIndexA = nodeIndexA;
    m_iNodeIndexB = nodeIndexB;
    m_iWeightValue = weightValue;
    m_bSelected = false;
}

【CMap.h】

#ifndef CMAP_H
#define CMAP_H
#include <vector>
#include "Node.h"
#include "Edge.h"
#include <iostream>
using namespace std;
class CMap
{
public:
    CMap(int capacity);
    ~CMap();
    bool addNode(Node *pNode);//向图中加入顶点
    void resetNode();//重置顶点
    bool setValueToMatrixForDirectedGraph(int row, int col, int val = 1);//为有向图设置邻接矩阵
    bool setValueToMatrixForUndirectedGraph(int row, int col, int val = 1);//为无向图设置邻接矩阵
    void printMatrix();//打印邻接矩阵
    void depthFirstTraverse(int nodeIndex);//深度优先遍历
    void breadthFirstTraverse(int nodeIndex);//广度优先遍历

    void primTree(int nodeIndex);//普里姆生成树
    void kruskalTree();
private:
    bool getValueFromMatrix(int row, int col, int &val);//从矩阵中获取权值
    void breadthFirstTraverseImpl(vector<int>preVec);//广度优先遍历实现函数
    int getMinEdge(vector<Edge>edgeVec);
    bool isInSet(vector<int>nodeSet, int target);
    void mergeNodeSet(vector<int>&nodeSetA, vector<int>nodeSetB);
private:
    int m_iCapacity;//图中最多可以容纳的顶点数
    int m_iNodeCount;//已经添加的顶点个数
    Node *m_pNodeArray;//用来存放顶点数组
    int *m_pMatrix;//用来存放邻接矩阵
    Edge *m_pEdge;
};
#endif // !CMAP_H

【CMap.cpp】

#include "CMap.h"

CMap::CMap(int capacity)
{
    m_iCapacity = capacity;
    m_iNodeCount = 0;
    m_pNodeArray = new Node[m_iCapacity];
    m_pMatrix = new int[m_iCapacity *m_iCapacity];
    memset(m_pMatrix, 0, m_iCapacity*m_iCapacity * sizeof(int));
    /*for (int i = 0; i < m_iCapacity *m_iCapacity; i++)
    {
        m_pMatrix[i] = 0;
    }*/
    m_pEdge = new Edge[m_iCapacity - 1];
}

CMap::~CMap()
{
    delete[]m_pNodeArray;
    delete[]m_pMatrix;
}

bool CMap::addNode(Node * pNode)
{
    if (pNode == nullptr)
    {
        return false;
    }
    m_pNodeArray[m_iNodeCount].m_cData = pNode->m_cData;
    m_iNodeCount++;
    return true;
}

void CMap::resetNode()
{
    for (int i = 0;i < m_iNodeCount;i++)
    {
        m_pNodeArray[i].m_bIsVisited = false;
    }
}

bool CMap::setValueToMatrixForDirectedGraph(int row, int col, int val)
{
    if (row<0||row>=m_iCapacity)
    {
        return false;
    }
    if (col<0 || col >= m_iCapacity)
    {
        return false;
    }
    m_pMatrix[row *m_iCapacity + col] = val;
    return true;
}

bool CMap::setValueToMatrixForUndirectedGraph(int row, int col, int val)
{
    if (row<0 || row >= m_iCapacity)
    {
        return false;
    }
    if (col<0 || col >= m_iCapacity)
    {
        return false;
    }
    m_pMatrix[row *m_iCapacity + col] = val;
    m_pMatrix[col *m_iCapacity + row] = val;
    return true;
}

void CMap::printMatrix()
{
    for (int i = 0; i < m_iCapacity; i++)
    {
        for (int k = 0; k < m_iCapacity; k++)
        {
            cout << m_pMatrix[i*m_iCapacity + k] << " ";
        }
        cout << endl;
    }
}

void CMap::depthFirstTraverse(int nodeIndex)
{
    int value = 0;
    cout << m_pNodeArray[nodeIndex].m_cData << " ";
    m_pNodeArray[nodeIndex].m_bIsVisited = true;
    for (int i = 0;i < m_iCapacity;i++)
    {
        getValueFromMatrix(nodeIndex, i, value);
        if (value == 1)
        {
            if (m_pNodeArray[i].m_bIsVisited)
            {
                continue;
            }
            else
            {
                depthFirstTraverse(i);
            }
        }
        else
        {
            continue;
        }
    }
}

void CMap::breadthFirstTraverse(int nodeIndex)
{
    cout << m_pNodeArray[nodeIndex].m_cData << " ";
    m_pNodeArray[nodeIndex].m_bIsVisited = true;
    vector<int>curVec;
    curVec.push_back(nodeIndex);
    breadthFirstTraverseImpl(curVec);
}

void CMap::primTree(int nodeIndex)
{
    int value = 0;
    int edgeCount = 0;
    vector<int>nodeVec;
    vector<Edge>edgeVec;
    cout << m_pNodeArray[nodeIndex].m_cData << endl;
    m_pNodeArray[nodeIndex].m_bIsVisited = true;
    nodeVec.push_back(nodeIndex);
    while (edgeCount < m_iCapacity - 1)
    {
        int temp = nodeVec.back();
        for (int i = 0; i < m_iCapacity; i++)
        {
            getValueFromMatrix(temp, i, value);
            if (value != 0)
            {
                if (m_pNodeArray[i].m_bIsVisited)
                {
                    continue;
                }
                else
                {
                    Edge edge(temp, i, value);
                    edgeVec.push_back(edge);
                }
            }
        }
        int edgeIndex = getMinEdge(edgeVec);
        edgeVec[edgeIndex].m_bSelected = true;
        cout << edgeVec[edgeIndex].m_iNodeIndexA << "---" << edgeVec[edgeIndex].m_iNodeIndexB << " ";
        cout << edgeVec[edgeIndex].m_iWeightValue << endl;
        m_pEdge[edgeCount] = edgeVec[edgeIndex];
        edgeCount++;
        int nextNodeIndex = edgeVec[edgeIndex].m_iNodeIndexB;
        nodeVec.push_back(nextNodeIndex);
        m_pNodeArray[nextNodeIndex];
        m_pNodeArray[nextNodeIndex].m_bIsVisited = true;
        cout << m_pNodeArray[nextNodeIndex].m_cData << endl;
    }
}

void CMap::kruskalTree()
{
    int value = 0;
    int edgeCount = 0;
    //定义存放结点集合的数组
    vector<vector<int>>nodeSets;
    //第一步:取出所有边
    vector<Edge>edgeVec;
    for (int i=0;i<m_iCapacity;i++)
    {
        for (int k = i+1;k<m_iCapacity;k++)
        {
            getValueFromMatrix(i, k, value);
            if (value!=0)
            {
                Edge edge(i, k, value);
                edgeVec.push_back(edge);
            }
        }
    }
    //第二步:从所有边中取出组成最小生成树的边
    //1.找到算法结束条件
    while (edgeCount<m_iCapacity-1)
    {
        //2.从边集合中找到最小边
        int minEdgeIndex = getMinEdge(edgeVec);
        edgeVec[minEdgeIndex].m_bSelected = true;
        //3.找到最小边连接的点
        int nodeAIndex = edgeVec[minEdgeIndex].m_iNodeIndexA;
        int nodeBIndex = edgeVec[minEdgeIndex].m_iNodeIndexB;
        //4.找到点所在的点集合
        bool nodeAIsSet = false;
        bool nodeBIsSet = false;
        int nodeAInSetLabel = -1;
        int nodeBInSetLabel = -1;
        for (int i = 0;i<(int)nodeSets.size();i++)
        {
            nodeAIsSet = isInSet(nodeSets[i], nodeAIndex);
            if (nodeAIsSet)
            {
                nodeAInSetLabel = i;
            }
        }
        for (int i = 0;i < (int)nodeSets.size();i++)
        {
            nodeBIsSet = isInSet(nodeSets[i], nodeBIndex);
            if (nodeBIsSet)
            {
                nodeBInSetLabel = i;
            }
        }
        //5.根据点所在集合的不同做出不同处理
        if (nodeAInSetLabel==-1&&nodeBInSetLabel==-1)
        {
            vector<int>vec;
            vec.push_back(nodeAIndex);
            vec.push_back(nodeBIndex);
            nodeSets.push_back(vec);
        }
        else if (nodeAInSetLabel!=-1&&nodeBInSetLabel==-1)
        {
            nodeSets[nodeAInSetLabel].push_back(nodeBIndex);
        }
        else if (nodeAInSetLabel != -1 && nodeBInSetLabel != -1 && nodeAInSetLabel != nodeBInSetLabel)
        {
            mergeNodeSet(nodeSets[nodeAInSetLabel], nodeSets[nodeBInSetLabel]);
            for (int k = nodeBInSetLabel;k < (int)nodeSets.size() - 1;k++)
            {
                nodeSets[k] = nodeSets[k + 1];
            }
        }
        else if (nodeAInSetLabel!=-1&&nodeBInSetLabel!=-1&&nodeAInSetLabel==nodeBInSetLabel)
        {
            continue;
        }
        m_pEdge[edgeCount] = edgeVec[minEdgeIndex];
        edgeCount++;
        cout << edgeVec[minEdgeIndex].m_iNodeIndexA << "---" << edgeVec[minEdgeIndex].m_iNodeIndexB << " ";
        cout << edgeVec[minEdgeIndex].m_iWeightValue << endl;
    }

}

bool CMap::getValueFromMatrix(int row, int col, int & val)
{
    if (row<0 || row >= m_iCapacity)
    {
        return false;
    }
    if (col<0 || col >= m_iCapacity)
    {
        return false;
    }
    val = m_pMatrix[row *m_iCapacity + col];
    return true;
}

void CMap::breadthFirstTraverseImpl(vector<int> preVec)
{
    int value = 0;
    vector<int> curVec;
    for (int j = 0; j < (int)preVec.size(); j++)
    {
        for (int i = 0; i < m_iCapacity; i++)
        {
            getValueFromMatrix(preVec[j], i, value);
            if (value!=0)
            {
                if (m_pNodeArray[i].m_bIsVisited)
                {
                    continue;
                }
                else
                {
                    cout << m_pNodeArray[i].m_cData << " ";
                    m_pNodeArray[i].m_bIsVisited = true;
                    curVec.push_back(i);
                }
            }
        }
    }
    if (curVec.size()==0)
    {
        return;
    }
    else
    {
        breadthFirstTraverseImpl(curVec);
    }
}

int CMap::getMinEdge(vector<Edge> edgeVec)
{
    int minWeight = 0;
    int edgeIndex = 0;
    int i = 0;
    for (;i<(int)edgeVec.size();i++)
    {
        if (!edgeVec[i].m_bSelected)
        {
            minWeight = edgeVec[i].m_iWeightValue;
            edgeIndex = 1;
            break;
        }   
    }
    if (minWeight == 0)
    {
        return -1;
    }
    for (;i<(int)edgeVec.size();i++)
    {
        if (edgeVec[i].m_bSelected)
        {
            continue;
        }
        else
        {
            if (minWeight>edgeVec[i].m_iWeightValue)
            {
                minWeight = edgeVec[i].m_iWeightValue;
                edgeIndex = i;
            }
        }
    }
    return edgeIndex;
}

bool CMap::isInSet(vector<int> nodeSet, int target)
{
    for (int i = 0;i<(int)nodeSet.size();i++)
    {
        if (nodeSet[i] == target)
        {
            return true;
        }
    }
    return false;
}

void CMap::mergeNodeSet(vector<int>& nodeSetA, vector<int> nodeSetB)
{
    for (int i = 0; i < (int)nodeSetB.size(); i++)
    {
        nodeSetA.push_back(nodeSetB[i]);
    }
}

【main.cpp】

#include "CMap.h"
int main(void)
{
    CMap *pMap = new CMap(6);
    Node *pNodeA = new Node('A');
    Node *pNodeB = new Node('B');
    Node *pNodeC = new Node('C');
    Node *pNodeD = new Node('D');
    Node *pNodeE = new Node('E');
    Node *pNodeF = new Node('F');
    pMap->addNode(pNodeA);
    pMap->addNode(pNodeB);
    pMap->addNode(pNodeC);
    pMap->addNode(pNodeD);
    pMap->addNode(pNodeE);
    pMap->addNode(pNodeF);
    pMap->setValueToMatrixForUndirectedGraph(0, 1, 6);
    pMap->setValueToMatrixForUndirectedGraph(0, 4, 5);
    pMap->setValueToMatrixForUndirectedGraph(0, 5, 1);
    pMap->setValueToMatrixForUndirectedGraph(1, 2, 3);
    pMap->setValueToMatrixForUndirectedGraph(1, 5, 2);
    pMap->setValueToMatrixForUndirectedGraph(2, 5, 8);
    pMap->setValueToMatrixForUndirectedGraph(2, 3, 7);
    pMap->setValueToMatrixForUndirectedGraph(3, 5, 4);
    pMap->setValueToMatrixForUndirectedGraph(3, 4, 2);
    pMap->setValueToMatrixForUndirectedGraph(4, 5, 9);
    
    cout <<"普利姆算法" << endl;
    pMap->primTree(0);
    cout << "克鲁斯卡尔算法"<< endl;
    pMap->kruskalTree();
    return 0;
}

运行结果

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容

  • https://zh.visualgo.net/graphds 浅谈图形结构https://zh.visualgo...
    狼之独步阅读 4,122评论 0 0
  • 第一章 绪论 什么是数据结构? 数据结构的定义:数据结构是相互之间存在一种或多种特定关系的数据元素的集合。 第二章...
    SeanCheney阅读 5,743评论 0 19
  • 数据结构 - 图 目录: 基本概念无向图有向图 储存结构邻接矩阵邻接表十字链表(有向图)邻接多重表(无向图) 图的...
    Rayhaha阅读 1,032评论 3 20
  • 简书尽然不支持LaTex公式编辑!!!! 图 有向图与无向图的区别在于边集合E是否有相,另外表示的区别在于$e =...
    Kean_L_C阅读 737评论 0 1
  • 2015.05.02 2016年对我来说真的是满怀期待的一年,但也是目前为止最让我对自己失望的一年。并不是说以往自...
    lizhiyou阅读 384评论 1 1