图的实现 邻接矩阵+无向图

#include <iostream>
#include <string.h>
#include <vector>
#include <stdlib.h>
using namespace std;

class Node
{
public:
    Node(char data = 0);//构造函数 初始化 
    char m_Data; //值 
    bool m_blsVisited; //标识是否被访问过       
};

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;   
};

class CMap
{
public:
    CMap(int iCapacity);
    ~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); //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; //存最小生成树中的边 
};

Node::Node(char data) 
{
    m_Data = data;
    m_blsVisited = false;
}

CMap::CMap(int iCapacity)
{
    m_iCapacity = iCapacity;
    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));

    m_pEdge = new Edge[iCapacity - 1]; 
}

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

bool CMap::AddNode(Node* pNode)
{   
    m_pNodeArray[m_iNodeCount].m_Data = pNode->m_Data;
    m_iNodeCount++;
    return true;
}

void CMap::ResetNode()
{
    for(int i = 0; i < m_iNodeCount; i++)
    {
        m_pNodeArray[i].m_blsVisited = false;
    }
}
//有向图邻接矩阵 
bool CMap::SetValueToMatrixForDirectedGraph(int row, int col, int val)
{
    m_pMatrix[row*m_iCapacity + col] = val;
    return true; 
}

bool CMap::SetValueToMatrixForUndirectedGraph(int row, int col, int val)
{
    m_pMatrix[row*m_iCapacity + col] = val;
    m_pMatrix[col*m_iCapacity + row ]= val;
    return true;
}

bool CMap::GetValueFromMatrix(int row, int col, int &val)
{
    val = m_pMatrix[row*m_iCapacity + col];
    return true;
}

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


void CMap::DepthFirstTraverse(int NodeIndex)
{
    int value = 0;
    cout << m_pNodeArray[NodeIndex].m_Data << " "; 
    m_pNodeArray[NodeIndex].m_blsVisited = true;

    for(int i =0; i < m_iCapacity; i++)
    {
        GetValueFromMatrix(NodeIndex, i, value);
        if(value == 1)
        {
            if(m_pNodeArray[i].m_blsVisited)
            {
                continue;
            }
            else
            {
                DepthFirstTraverse(i);
            }
        }
        else
        {
            continue;
        }
    }
}


void CMap::BreadthFirstTraverse(int NodeIndex)
{
    cout << m_pNodeArray[NodeIndex].m_Data << " ";
    m_pNodeArray[NodeIndex].m_blsVisited = true;

    vector<int> curVec;
    curVec.push_back(NodeIndex);

    BreadthFirstTraverseImpl(curVec);
}

void CMap::BreadthFirstTraverseImpl(vector<int> preVec) 
{
    int value = 0;
    vector<int> curVec; //保存当前这一层所有节点

    //preVec 上一层所有节点 
    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_blsVisited)
                {
                    continue; 
                }
                else
                {
                    cout << m_pNodeArray[i].m_Data << " ";
                    m_pNodeArray[i].m_blsVisited = true;

                    curVec.push_back(i);
                }
            }
        }   
    }
    if(curVec.size() == 0)
    {
        return ;
    }
    else
    {
        BreadthFirstTraverseImpl(curVec);
    }
}

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

    m_bSelected = false;
}

//普利姆生成树 
void CMap::primTree(int nodeIndex)
{
    int value = 0; //取边的权值
    int edgeCount = 0; 
    vector<int> NodeVec; //存储点的集合
    vector<Edge> EdgeVec; //备选边的集合 

    cout <<  m_pNodeArray[nodeIndex].m_Data << endl;
    m_pNodeArray[nodeIndex].m_blsVisited = true;

    NodeVec.push_back(nodeIndex);
    while(edgeCount < m_iCapacity - 1)
    {
        int temp = NodeVec.back(); //取出最尾部的元素

        //将与temp节点所连的所有的边都放入备选边集合 
        for(int i = 0; i < m_iCapacity; i++)
        {
            GetValueFromMatrix(temp, i, value);
            if(value != 0)
            {
                if(m_pNodeArray[i].m_blsVisited)
                {
                    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];

         //找到与当前最小边所连接的点 
         int nextNodeIndex= EdgeVec[edgeIndex].m_iNodeIndexB;
         NodeVec.push_back(nextNodeIndex);
         m_pNodeArray[nextNodeIndex].m_blsVisited = true;

         cout << m_pNodeArray[nextNodeIndex].m_Data << endl;
    }
}

int CMap::GetMinEdge(vector<Edge> EdgeVec)
{
    int minWeight = 0;
    int edgeIndex = 0;
    int i= 0; 
    //取出第一条未访问的边 
    for(; i < EdgeVec.size(); i++)
    {
        if(!EdgeVec[i].m_bSelected)
        {
            minWeight = EdgeVec[i].m_iWeightValue;
            edgeIndex = i;
            break;
        }

    }

    if(minWeight == 0)
    {
        return -1;
    }
    //剩余边中找最小边
    for(; i < EdgeVec.size(); i++)
    {
        if(!EdgeVec[i].m_bSelected)
        {
            if(minWeight > EdgeVec[i].m_iWeightValue)
            {
                minWeight = EdgeVec[i].m_iWeightValue;
                edgeIndex = i;
            }
        }
        else
        {
            continue ;
        }
    }
    return edgeIndex;
}

bool CMap::IsInSet(vector<int> nodeSet, int target)
{
    for(int i = 0; i < 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 < nodeSetB.size(); i++)
    {
        nodeSetA.push_back(nodeSetB[i]);
    }
}

void CMap::KruskalTree()
{
    int value = 0; 
    int edgeCount = 0;

    //定义一个点集合的数组
    vector< vector<int> > NodeSets;  
    //1.取出所有的边
    vector<Edge> EdgeVec;
    for(int i = 0; i < m_iCapacity; i++)
    {
        for(int j = i + 1; j < m_iCapacity; j++) //取出邻接矩阵上半个三角,不含主对角线上的数据 
        {
            GetValueFromMatrix(i, j, value);
            if(value != 0)
            {
                Edge edge(i, j, value);
                EdgeVec.push_back(edge);    
            } 
        }
    }   
    //2.  从所有边中取出组成最小生成树的边
         // 找到算法结束条件  边数 = 顶点数 - 1
    while(edgeCount < m_iCapacity - 1)
    {        
         // 从边集合中找到最小边
         int minEdgeIndex = GetMinEdge(EdgeVec);
         EdgeVec[minEdgeIndex].m_bSelected = true;

         //找到最小边连接的点
         int nodeAIndex = EdgeVec[minEdgeIndex].m_iNodeIndexA;
         int nodeBIndex = EdgeVec[minEdgeIndex].m_iNodeIndexB;

         bool nodeAIsInSet = false;
         bool nodeBIsInSet = false;

         int nodeAInSetLabel = -1;
         int nodeBInSetLabel = -1;

         //找出A点所在的集合
          for(int i = 0; i < NodeSets.size(); i++)
          {
              nodeAIsInSet = IsInSet(NodeSets[i], nodeAIndex);  
              if(nodeAIsInSet)
              {
                    nodeAInSetLabel = i;
              }
          } 
          //找出B点所在的集合
          for(int i = 0; i < NodeSets.size(); i++)
          {
              nodeBIsInSet = IsInSet(NodeSets[i], nodeAIndex);  
              if(nodeBIsInSet)
              {
                    nodeBInSetLabel = i;
              }
          }

         //根据点所在的集合做出不同的处理 
         if(nodeAInSetLabel == -1 && nodeBInSetLabel == -1)
         {
            vector<int> vec;
            vec.push_back(nodeAInSetLabel);
            vec.push_back(nodeBInSetLabel);
            NodeSets.push_back(vec);
         }
         else if(nodeAInSetLabel == -1 && nodeBInSetLabel != -1)
         {
            NodeSets[nodeBInSetLabel].push_back(nodeAInSetLabel);
         }
         else if(nodeAInSetLabel != -1 && nodeBInSetLabel == -1)
         {
            NodeSets[nodeAInSetLabel].push_back(nodeBInSetLabel);
         }
         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];

         cout << EdgeVec[minEdgeIndex].m_iNodeIndexA << "......" << EdgeVec[minEdgeIndex].m_iNodeIndexB << " ";
         cout << EdgeVec[minEdgeIndex].m_iWeightValue << endl;
    }
}


int main()
{
    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');
//  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);
#if 0   
    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(4, 5);
#endif
    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);

    pMap->PrintMatrix();
    cout << endl;
#if 0   
    pMap->ResetNode();
    pMap->DepthFirstTraverse(0);
    cout << endl;

    pMap->ResetNode();
    pMap->BreadthFirstTraverse(0);
    cout << endl;
#endif  

    pMap->KruskalTree();
    system("pause");
    return 0;
}










  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值