在学习数据结构的时候自己纯手打的实现代码,放到平台上来方便自己日后回顾,也可以给其他想学习的朋友一点小小的参考。
(代码思路来源于慕课网的c++数据结构课程)
- 结点Node.h
#pragma once
#include<stdlib.h>
#include<string>
#include<iostream>
using namespace std;
class Node
{
public:
Node(char data = 0);
char m_cData;
bool m_bIsVisited;
};
Node::Node(char data)
{
m_cData = data;
m_bIsVisited = false;
}
- 边edge.h
#pragma once
#include<stdlib.h>
#include<string>
#include<iostream>
using namespace std;
//边
class Edge
{
public:
int m_iNodeIndexA;
int m_iNodeIndexB;
int m_iWeightValue;
bool m_bSelected;
Edge(int NodeIndexA = 0, int NodeIndexB = 0, int WeightValue = 0);
};
Edge::Edge(int NodeIndexA, int NodeIndexB, int WeightValue)
{
m_iNodeIndexA = NodeIndexA;
m_iNodeIndexB = NodeIndexB;
m_iWeightValue = WeightValue;
m_bSelected = false;
}
- 图cMap.h
#pragma once
#include<stdlib.h>
#include<string>
#include<iostream>
#include "Node.h"
#include "Edge.h"
#include <vector>
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 depthFirstTaverse(int nodeIndex); //深度优先遍历
void breadthFirstTaverse(int nodeIndex); //广度优先遍历
void primTree(int nodeIndex); //普利姆算法(普利姆生成树)
void kruskalTree(); //克鲁斯卡尔算法(克鲁斯卡尔生成树)
private:
bool getValueFromMatrix(int row, int col, int& val); //从矩阵中获取权值
void breadthFirstTaverseImpl(vector<int>preVec); //广度优先遍历实现函数
int getMinEDge(vector<Edge> edgeVec); //取最小边
bool isInSet(vector<int> nodeSet, int target); //判断点是否在集合内
void mergeNodeSet(vector<int> &nodeSetA, vector<int> nodeSetB); //将集合B合并到集合A
private:
int m_iCapacity; //图中容纳的顶点数
int m_iNodeCount; //图中已经添加了的顶点数
Node* m_pNodeArray; //存放顶点数组
int* m_pMatrix; //存放邻接数组
Edge* m_pEdge; //最小边的指针
};
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));
m_pEdge = new Edge[m_iCapacity - 1];
}
cMap::~cMap()
{
delete []m_pMatrix;
delete []m_pNodeArray;
delete[]m_pEdge;
}
bool cMap::AddNode(Node* pNode)
{
if (pNode == NULL)
{
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 || 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 || 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 r = 0; r < m_iCapacity; r++)
{
for (int c = 0; c < m_iCapacity; c++)
{
cout << m_pMatrix[r * m_iCapacity + c] << " ";
}
cout << endl;
}
}
bool cMap::getValueFromMatrix(int row, int col, int& val)
{
if (row < 0 || row >= m_iCapacity || col < 0 || col >= m_iCapacity)
{
return false;
}
val = m_pMatrix[row * m_iCapacity + col];
return true;
}
void cMap::depthFirstTaverse(int nodeIndex)
{
cout << m_pNodeArray[nodeIndex].m_cData << " ";
m_pNodeArray[nodeIndex].m_bIsVisited = true;
int value = 0;
for (int i = 0; i < m_iCapacity; i++)
{
getValueFromMatrix(nodeIndex, i, value);
if (value != 0)
{
if (m_pNodeArray[i].m_bIsVisited)
{
continue;
}
else
{
depthFirstTaverse(i);
}
}
else
{
continue;
}
}
}
void cMap::breadthFirstTaverse(int nodeIndex)
{
cout << m_pNodeArray[nodeIndex].m_cData << " ";
m_pNodeArray[nodeIndex].m_bIsVisited = true;
vector<int> curVec;
curVec.push_back(nodeIndex);
breadthFirstTaverseImpl(curVec);
}
void cMap::breadthFirstTaverseImpl(vector<int>preVec)
{
int value = 0;
vector<int> curVec;
for (int i = 0; i < (int)preVec.size(); i++)
{
for (int j = 0; j < m_iCapacity; j++)
{
getValueFromMatrix(preVec[i], j, value);
if (value != 0)
{
if (m_pNodeArray[j].m_bIsVisited)
{
continue;
}
else
{
cout << m_pNodeArray[j].m_cData << " ";
m_pNodeArray[j].m_bIsVisited = true;
curVec.push_back(j);
}
}
}
}
if (curVec.size() != 0)
{
breadthFirstTaverseImpl(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;
nodeVec.push_back(nodeIndex);
m_pNodeArray[nodeIndex].m_bIsVisited = true;
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);
if (edgeIndex == -1)
{
edgeVec[nodeIndex].m_bSelected = true;
}
else
{
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_bIsVisited = true;
cout << m_pNodeArray[nextNodeIndex].m_cData << 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 (0 == minWeight)
{
return -1;
}
for (; i < 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;
}
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 (0 != value)
{
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 nodeAIsInSet = false;
bool nodeBIsInSet = false;
int nodeAIsInSetLabel = -1;
int nodeBIsInSetLabel = -1;
for (int i = 0; i < (int)nodeSets.size(); i++)
{
nodeAIsInSet = isInSet(nodeSets[i], nodeAIndex);
if (nodeAIsInSet)
{
nodeAIsInSetLabel = i;
}
}
for (int i = 0; i < (int)nodeSets.size(); i++)
{
nodeBIsInSet = isInSet(nodeSets[i], nodeBIndex);
if (nodeBIsInSet)
{
nodeBIsInSetLabel = i;
}
}
//5.根据点所在的集合不同做出不同处理
if (nodeAIsInSetLabel == -1 && nodeBIsInSetLabel == -1)
{
vector<int>vec;
vec.push_back(nodeAIsInSetLabel);
vec.push_back(nodeBIsInSetLabel);
nodeSets.push_back(vec);
}
else if (nodeAIsInSetLabel == -1 && nodeBIsInSetLabel != -1)
{
nodeSets[nodeBIsInSetLabel].push_back(nodeAIsInSetLabel);
}
else if (nodeBIsInSetLabel == -1 && nodeAIsInSetLabel != -1)
{
nodeSets[nodeAIsInSetLabel].push_back(nodeBIsInSetLabel);
}
else if (nodeAIsInSetLabel != 1 && nodeBIsInSetLabel != -1 && nodeAIsInSetLabel != nodeBIsInSetLabel)
{
mergeNodeSet(nodeSets[nodeAIsInSetLabel], nodeSets[nodeBIsInSetLabel]);
for (int k = nodeBIsInSetLabel; k < (int)nodeSets.size() - 1; k++)
{
nodeSets[k] = nodeSets[k + 1];
}
}
else if (nodeAIsInSetLabel != 1 && nodeBIsInSetLabel != -1 && nodeAIsInSetLabel == nodeBIsInSetLabel)
{
continue;
}
m_pEdge[edgeCount] = edgeVec[minEdgeIndex];
edgeCount++;
cout << edgeVec[minEdgeIndex].m_iNodeIndexA << "---" << edgeVec[minEdgeIndex].m_iNodeIndexB << " ";
cout << edgeVec[minEdgeIndex].m_iWeightValue << endl;
}
}
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]);
}
}
- 主函数demo.cpp
#include<stdlib.h>
#include<iostream>
#include<string>
#include "cMap.h"
#include "Node.h"
using namespace std;
int main()
{
Node* n1 = new Node('A');
Node* n2 = new Node('B');
Node* n3 = new Node('C');
Node* n4 = new Node('D');
Node* n5 = new Node('E');
Node* n6 = new Node('F');
cMap* map = new cMap(6);
map->AddNode(n1);
map->AddNode(n2);
map->AddNode(n3);
map->AddNode(n4);
map->AddNode(n5);
map->AddNode(n6);
map->setValueToMatrixForUnDirectedGraph(0, 1, 6);
map->setValueToMatrixForUnDirectedGraph(0, 4, 5);
map->setValueToMatrixForUnDirectedGraph(0, 5, 1);
map->setValueToMatrixForUnDirectedGraph(1, 2, 3);
map->setValueToMatrixForUnDirectedGraph(1, 5, 2);
map->setValueToMatrixForUnDirectedGraph(2, 5, 8);
map->setValueToMatrixForUnDirectedGraph(2, 3, 7);
map->setValueToMatrixForUnDirectedGraph(3, 5, 4);
/*map->depthFirstTaverse(0);
map->resetNode();
map->breadthFirstTaverse(0);
cout << endl;*/
map->printMatrix();
cout << endl;
//map->primTree(0);
map->kruskalTree();
return 0;
}