以下内容主要参考了严蔚敏版的数据结构教材
以下算法求有向图的每一个强连通分量中的节点并把一个强连通分量中的所有节点放在一个集合中。算法包含两次深度优先搜索过程:
//图的十字链表表示
//弧节点
class GraphArcNode
{
private:
int weight;
int tailIndex;
int headIndex;
GraphArcNode* nextTailArcNode;
GraphArcNode* nextHeadArcNode;
public:
GraphArcNode(int d = 0, int tail = 0, int head = 0, GraphArcNode* nextTailArc=nullptr, GraphArcNode* nextHeadArc = nullptr)
{
weight=d;
tailIndex=tail;
headIndex=head;
nextTailArcNode= nextTailArc;
nextHeadArcNode= nextHeadArc;
}
int getTailIndex()
{
return tailIndex;
}
int getHeadIndex()
{
return headIndex;
}
GraphArcNode* getNextTailArcNode()
{
return nextTailArcNode;
}
GraphArcNode* getNextHeadArcNode()
{
return nextHeadArcNode;
}
};
//图节点
class GraphNode
{
private:
int data;
GraphArcNode* firstTailArcNode;
GraphArcNode* firstHeadArcNode;
public:
GraphNode(int d = 0, GraphArcNode* firstTail=nullptr, GraphArcNode* firstHead=nullptr)
{
data = d;
firstTailArcNode= firstTail;
firstHeadArcNode = firstHead;
}
void settail(GraphArcNode* value)
{
firstTailArcNode=value;
}
void sethead(GraphArcNode* value)
{
firstHeadArcNode=value;
}
GraphArcNode* gettail()
{
return firstTailArcNode;
}
GraphArcNode* gethead()
{
return firstHeadArcNode;
}
};
//图的数据结构
class OLGraph
{
private:
vector<GraphNode> graphNodeSet;
int nodeNum;
int arcNum;
public:
OLGraph(int num1,int num2)
{
nodeNum = num1;
arcNum=num2;
}
void createGraph()
{
int inputData=0;
int tail = 0;
int head = 0;
GraphArcNode* arc = nullptr;
cout << "Please input " << nodeNum << " nodes data!!" << endl;
for (int i = 0; i < nodeNum; i++)
{
cout << "The data " << i << " :";
cin >> inputData;
graphNodeSet.push_back(GraphNode(inputData,nullptr, nullptr));
}
cout << "Complete the data element input!! " << endl;
cout << "Please input " << arcNum << " arcs information!!" << endl;
for (int i = 0; i < arcNum; i++)
{
cout << "The arc " << i << " :"<<endl;
cout << "The arc tail:";
cin >> tail;
cout << "The arc head:";
cin >> head;
arc=new GraphArcNode(0,tail,head, graphNodeSet[tail].gettail(),graphNodeSet[head].gethead());
graphNodeSet[tail].settail(arc);
graphNodeSet[head].sethead(arc);
cout << "////////////////////////////////////" << endl;
cout << "The graph now is:" << endl;
for (int i = 0; i < nodeNum; i++)
{
cout << "i=" << i << endl;
GraphArcNode* tail = graphNodeSet[i].gettail();
GraphArcNode* head = graphNodeSet[i].gethead();
while (tail != nullptr)
{
cout << "tail->getTailIndex()=" << tail->getTailIndex();
cout << " tail->getHeadIndex=" << tail->getHeadIndex() << endl;
tail = tail->getNextTailArcNode();
}
}
cout << "////////////////////////////////////" << endl<< endl;
}
cout << "Complete the arcs information input!! " << endl;
}
int getGraphNodeNum()
{
return nodeNum;
}
GraphArcNode* getGraphNodeTail(int nodeIndex)
{
return graphNodeSet[nodeIndex].gettail();
}
GraphArcNode* getGraphNodeHead(int nodeIndex)
{
return graphNodeSet[nodeIndex].gethead();
}
};
int findNextReverseAdjNodeIndex(OLGraph g, int currentNodeIndex, vector<bool>& visited)
{
if (currentNodeIndex >= 0)
{
GraphArcNode* currentArcNode = g.getGraphNodeHead(currentNodeIndex);
while ((currentArcNode != nullptr) && (visited[currentArcNode->getTailIndex()]))
{
currentArcNode = currentArcNode->getNextHeadArcNode();
}
if (currentArcNode != nullptr)
{
return currentArcNode->getTailIndex();
}
else
{
return -1;
}
}
return -1;
}
void DFSSecond(OLGraph g, int nodeIndex, vector<bool>& visited)
{
visited[nodeIndex] = true;
for (int nextNodeIndex = findNextReverseAdjNodeIndex(g, nodeIndex, visited); nextNodeIndex >= 0; nextNodeIndex = findNextReverseAdjNodeIndex(g, nodeIndex, visited))
{
DFSSecond(g, nextNodeIndex, visited);
}
return;
}
void DFSTraverseSecond(OLGraph g, vector<int> finishedNode)
{
set<int> alreadyAdded;
vector<bool> visited(g.getGraphNodeNum(), false);
vector<vector<int>> connectedComponentArray;
vector<int> temp;
for (int i = g.getGraphNodeNum() - 1; i >= 0; i--)
{
temp = {};
if (!visited[finishedNode[i]])
{
DFSSecond(g, finishedNode[i], visited);
}
for (int j = 0; j < g.getGraphNodeNum(); j++)
{
if ((visited[j])&&(alreadyAdded.find(j)== alreadyAdded.end()))
{
temp.push_back(j);
alreadyAdded.insert(j);
}
}
if (temp.size() != 0)
{
connectedComponentArray.push_back(temp);
}
}
for (int i = 0; i < connectedComponentArray.size(); i++)
{
for (int j = 0; j < connectedComponentArray[i].size(); j++)
{
cout << connectedComponentArray[i][j] << " ";
}
cout << endl;
}
return;
}
int findNextAdjNodeIndex(OLGraph g, int currentNodeIndex, vector<bool>& visited)
{
if (currentNodeIndex >= 0)
{
GraphArcNode* currentArcNode = g.getGraphNodeTail(currentNodeIndex);
while ((currentArcNode != nullptr) && (visited[currentArcNode->getHeadIndex()]))
{
currentArcNode = currentArcNode->getNextTailArcNode();
}
if (currentArcNode != nullptr)
{
return currentArcNode->getHeadIndex();
}
else
{
return -1;
}
}
return -1;
}
void DFSFirst(OLGraph g, int nodeIndex, vector<bool>& visited, vector<int> &finishedNode, int &finishedNodeNum)
{
visited[nodeIndex] = true;
for (int nextNodeIndex = findNextAdjNodeIndex(g, nodeIndex, visited); nextNodeIndex >= 0; nextNodeIndex = findNextAdjNodeIndex(g, nodeIndex, visited))
{
DFSFirst(g, nextNodeIndex, visited, finishedNode, finishedNodeNum);
}
finishedNode[finishedNodeNum++] = nodeIndex;
return;
}
void DFSTraverseFirst(OLGraph g)
{
int finishedNodeNum = 0;
vector<int> finishedNode(g.getGraphNodeNum(),0);
vector<bool> visited(g.getGraphNodeNum(), false);
for (int i = 0; i < g.getGraphNodeNum(); i++)
{
if (!visited[i])
{
DFSFirst(g, i, visited, finishedNode, finishedNodeNum);
}
}
cout << "finishedNodeNum=" << finishedNodeNum << endl;
for (int i = 0; i < finishedNode.size(); i++)
{
cout << finishedNode[i] << endl;
}
DFSTraverseSecond(g, finishedNode);
return;
}
void printGraph(OLGraph g)
{
for (int i = 0; i < g.getGraphNodeNum(); i++)
{
cout << "i=" << i << endl;
GraphArcNode* tail =g.getGraphNodeTail(i);
GraphArcNode* head = g.getGraphNodeHead(i);
while (tail!=nullptr)
{
cout << "tail->getTailIndex()=" << tail->getTailIndex();
cout << "tail->getHeadIndex="<<tail->getHeadIndex() << endl;
tail = tail->getNextTailArcNode();
}
}
}
//测试程序
int main()
{
OLGraph g(4,7);
g.createGraph();
DFSTraverseFirst(g);
}