図処理アルゴリズム-Kosaraju's-アルゴリズム
12206 ワード
1.アルゴリズムの授業で図面のある宿題について書きました.
c++で大きな配列を開くとsegment faultが出やすくなり,その後スタックで開くようになった.図の隣接表はチェーンテーブルで表されている.
2.図の格納については、隣接チェーンテーブルで格納する(vector配列よりチェーンテーブルでアクセス速度がずっと速い).
2.1辺表
2.2頂点テーブル
2.3図辺を初期化する際にヘッドプラグを用いた
3.深さ優先検索
3.1再帰的実現
疑似コードは次のとおりです.
入力:図Gと頂点i
1.頂点iをアクセス済みとしてマークします.
2.エッジ(i,j)、すなわち頂点iの隣接点jを遍歴する.
3.ifある頂点jがアクセスされていない場合、頂点jにアクセスする.
DFS(G,j)
c++コードは以下の通りです.
3.2非再帰的な実装
疑似コードは次のとおりです.
入力:図G、頂点iへ.
1.スタックを初期化し、頂点iをスタックに入れ、iをアクセス済みとしてマークします.
2.while(スタックが空でない)
x=スタックトップ要素
3.エッジ(x,j)を巡回する:
if:ある頂点jがアクセスされていない:
jをアクセス済みとマークする
jをスタックに入れる
break
else:
x出桟
c++コード:
完全なコード:https://github.com/Shinered/Kosaraju/blob/master/dfs3.cpp
転載先:https://www.cnblogs.com/Shinered/p/8999688.html
c++で大きな配列を開くとsegment faultが出やすくなり,その後スタックで開くようになった.図の隣接表はチェーンテーブルで表されている.
long int numVertexes = 875714;
long int numEdges;
VertexNode* adjList = new VertexNode[875714];
2.図の格納については、隣接チェーンテーブルで格納する(vector配列よりチェーンテーブルでアクセス速度がずっと速い).
2.1辺表
/******** ***********/
class EdgeNode
{
public:
long int adjvex; //
EdgeNode *next; //
EdgeNode(long int adj, EdgeNode *n = NULL): adjvex(adj), next(n){}
};
2.2頂点テーブル
/********* **********/
class VertexNode
{
public:
long int data; //
EdgeNode *firstEdge; //
// VertexNode(long int d, EdgeNode *fir = NULL) : data(d), firstedge(fir) {}
};
2.3図辺を初期化する際にヘッドプラグを用いた
/************* *************************/
void addEdge(long int a, long int b)
{
EdgeNode *enode = new EdgeNode(b,NULL);
enode->next = (adjList+a)->firstEdge;
(adjList+a)->firstEdge = enode;
}
3.深さ優先検索
3.1再帰的実現
疑似コードは次のとおりです.
入力:図Gと頂点i
1.頂点iをアクセス済みとしてマークします.
2.エッジ(i,j)、すなわち頂点iの隣接点jを遍歴する.
3.ifある頂点jがアクセスされていない場合、頂点jにアクセスする.
DFS(G,j)
c++コードは以下の通りです.
/*--------------------- dfs-------------------*/
void DFS(Graph graph, long int i)
{
marked[i] = true;
list<long int>::iterator iter;
for(iter = graph._storage[i].begin(); iter != graph._storage[i].end(); iter++)
{
long int temp = *iter;
if(!marked[temp])
{
DFS(graph, temp);
}
}
time++;
ff[time-1] = i;
}
/*--------------- dfs---------------*/
void DFS2(Graph graph, long int i)
{
marked[i] = true;
leader[i] = s;
list<long int>::iterator iter;
for(iter = graph._storage[i].begin(); iter != graph._storage[i].end(); iter++)
{
long int temp = *iter;
if(!marked[temp])
{
DFS2(graph, temp);
}
}
}
3.2非再帰的な実装
疑似コードは次のとおりです.
入力:図G、頂点iへ.
1.スタックを初期化し、頂点iをスタックに入れ、iをアクセス済みとしてマークします.
2.while(スタックが空でない)
x=スタックトップ要素
3.エッジ(x,j)を巡回する:
if:ある頂点jがアクセスされていない:
jをアクセス済みとマークする
jをスタックに入れる
break
else:
x出桟
c++コード:
/*================ dfs================*/
void dfsLoop1(Graph graph)
{
markedInit();
time = 0;
for(long int i = length-1; i >= 0; i--)
{
if(!marked[i])
{
DFS1(graph, i);
}
}
}
void DFS1(Graph graph, long int i)
{
stack< VertexNode* > stack;
stack.push(graph.adjList+i);
marked[i] = true;
while(!stack.empty())
{
VertexNode *temp = new VertexNode;
temp = stack.top();
EdgeNode *p = new EdgeNode(0, NULL);
p = temp->firstEdge;
int flag = 0;
while(p)
{
if(!marked[p->adjvex])
{
marked[p->adjvex] = true;
stack.push(graph.adjList + (p->adjvex));
flag = 1;
break;
}
p = p->next;
}
if(!flag)
{
ff[time] = temp->data;
time++;
stack.pop();
}
}
}
/*================ dfs================*/
void dfsLoop2(Graph graph)
{
markedInit();
time = 0;
for(long int i = length-1; i >=0 ; i--)
{
if(!marked[ff[i]])
{
s = ff[i];
DFS2(graph, ff[i]);
}
}
}
void DFS2(Graph graph, long int i)
{
stack < VertexNode* > stack;
stack.push(graph.adjList+i);
leader[i] = s;
marked[i] = true;
while(!stack.empty())
{
VertexNode *temp = new VertexNode;
temp = stack.top();
marked[temp->data] = true;
EdgeNode *p = new EdgeNode(0,NULL);
p = temp->firstEdge;
int flag = 0;
while(p)
{
if(!marked[p->adjvex])
{
marked[p->adjvex] = true;
stack.push(graph.adjList + p->adjvex);
flag = 1;
break;
}
p = p->next;
}
if(!flag)
{
leader[temp->data] = s;
stack.pop();
}
}
}
完全なコード:https://github.com/Shinered/Kosaraju/blob/master/dfs3.cpp
転載先:https://www.cnblogs.com/Shinered/p/8999688.html