1.1 深さ優先トラバーサル
深さ優先トラバーサル (深さ優先検索)。深さ優先検索または略して DFS とも呼ばれます。その主なアイデアは、たとえば、鍵を見つけることです。例: 車のキーを 1 つ紛失しましたが、それが家のどこかにあることは確かなので、部屋から探し始める必要がありますが、部屋の特定の場所で探すべきですか、それとも部屋全体 探した後、次の部屋はどこにありますか?深さ優先探索とは、車のキーが見つかるまで、他の部屋を検索する前に、部屋内のすべての場所を検索することを意味します。
今すぐタスクを完了する必要があるとします。自分が次の迷路の中にいるということを知る必要があります。頂点 A から始めて、グラフ内のすべての頂点を通過し、それらにマークを付ける必要があります。単に見て歩いているわけではないことに注意してください。このような平面グラフを現実と同じように歩き、迷路内のタスクを完了します。
明らかに、この種のグラフを横断するための戦略が必要です。そうでないと、この広大な道路で簡単に迷子になり、タスクを完了するには運に頼るしかありません。この記事を読んで深さ優先トラバースについてある程度理解していれば、このタスクを完了するのは難しくありません。
まずA地点からスタートし、通過の印を付けた後、目の前にBとFに続く道が2本あります。頂点が重複しない場合の原則を自分で決めます。 、常に右側のウォークに進むので、B 頂点に到達しました。パス全体のプロセスは次の図を参照してください。この時点で、C、I、G につながる 3 つの分岐があり、右手で C 頂点に到達します。F頂点まで行って、次の頂点を見つけたのでA頂点に戻り、F頂点で最後から2番目の右手の通路をG頂点まで進み、3つ遭遇しましたさらに道があったが、B、D を見つけた 私たちはすでに通過したので、H 頂点に到達しました H に到達したとき、2 つの交差点に遭遇し、両方とも通過しましたが、グラフの横断が完了していないことは明らかでしたで、H から G、F、E、D 頂点まで後退しました。D 頂点に到達すると、まだそこを歩いていないことがわかり、I まで歩いてこのタスクは完了です。
実際、上記の説明から、深さ優先走査は再帰的なプロセスであることがわかりますが、注意深く見ると、ツリーの前順序走査に似ていることがわかります。これは、グラフ内の特定の頂点 V から開始し、その頂点を訪問し、最初に V の未訪問の隣接点から、V とのパスを持つグラフ内のすべての頂点が訪問されるまで、グラフを深く横断します。
隣接行列の深さトラバーサルのコードは次のとおりです。
int visited[10];
//邻接矩阵的深度优先递归算法
void DFS(struct photo* G, int i) //访问标志的数组
{
int j;
visited[i] = 1;
cout << G->vex[i]<<" "; //打印结点的内容
for (j = 0; j < G->numnodes; j++)
{
if (G->arc[i][j] == 1 && visited[j] == 0) //对未被访问的结点进行递归
DFS(G, j);
}
}
//邻接矩阵的深度遍历操作
void DFStraverse(struct photo* G)
{
int i;
for (i = 0; i < G->numnodes; i++)
visited[i] = 0; //初始化标志数组都为被访问
for (i = 0; i < G->numnodes; i++)
if (visited[i] == 0)
DFS(G, i); //对未被党文的顶点调用DFS
}
データの保存方法を含む、実行可能なコード全体は次のとおりです。
struct photo
{
char vex[10];
int arc[10][10]={0};
int numnodes, numdges;
};
void creategraph(struct photo*G)
{
cout << "请输入顶点数和边数:" << endl;
cin >> G->numnodes >> G->numdges;
for (int i = 0; i < G->numnodes; i++)
cin >> G->vex[i];
for (int i = 0; i < G->numnodes; i++)
for (int j = 0; j < G->numnodes; j++)
G->arc[i][j] = 0;
for (int k = 0; k < G->numdges; k++)
{
int i, j;
cout << "请输入有边点数:(i,j)" << endl;
cin >> i>>j;
G->arc[i][j] = 1;
G->arc[j][i] = G->arc[i][j];
}
}
void print(struct photo* G)
{
for (int i = 0; i < G->numnodes; i++)
{
for (int j = 0; j < G->numnodes; j++)
{
cout <<setw(2)<< G->arc[i][j] << " ";
}
cout << endl;
}
}
int visited[10];
void DFS(struct photo* G, int i)
{
int j;
visited[i] = 1;
cout << G->vex[i]<<" ";
for (j = 0; j < G->numnodes; j++)
{
if (G->arc[i][j] == 1 && visited[j] == 0)
DFS(G, j);
}
}
void DFStraverse(struct photo* G)
{
int i;
for (i = 0; i < G->numnodes; i++)
visited[i] = 0;
for (i = 0; i < G->numnodes; i++)
if (visited[i] == 0)
DFS(G, i);
}
int main()
{
struct photo* y;
y = (struct photo*)malloc(sizeof(struct photo));
creategraph(y);
print(y);
DFStraverse(y);
return 0;
}
一般的な実行結果は次のとおりです。上記の推論によれば、主にこのアイデアを観察して習得するために、次の図に入力したデータが推測できます。
隣接リストのコード DFStraverse 関数のコードはほぼ同じですが、再帰関数では記憶構造が配列からリンク リストに変更されているため異なります。
隣接リストの詳細なトラバーサルのコードは次のとおりです。
int visited[10];
void DFS(nodes* G, int i)
{
struct dege* e;
visited[i] = 1;
cout << G->adj[i].data<<" ";
e = G->adj[i].first;
while (e)
{
if (visited[e->adv] == 0)
DFS(G, e->adv);
e = e->next;
}
}
void DFStraverse(nodes* G)
{
for (int i = 0; i < G->numnodes; i++)
visited[i] = 0;
for (int i = 0; i < G->numnodes; i++)
if (visited[i] == 0)
DFS(G, i);
}
完全な隣接リストと深さ優先トラバーサルを作成するコードは次のとおりです。
struct dege
{
int adv;
struct dege* next;
};
typedef struct vex
{
char data;
struct dege* first;
}adjlist[100];
struct nodes
{
adjlist adj;
int numnodes, numedges;
};
void create(struct nodes* G)
{
struct dege* e;
cout << "请输入顶点数目和边的数目:" << endl;
cin >> G->numnodes >> G->numedges;
for (int i = 0; i < G->numnodes; i++)
{
cin >> G->adj[i].data;
G->adj[i].first = NULL;
}
for (int k = 0; k < G->numedges; k++)
{
cout << "请输入有边的结点i,j:" << endl;
int i, j;
cin >> i >> j;
e = (struct dege*)malloc(sizeof(struct dege));
e->adv = j;
e->next = G->adj[i].first;
G->adj[i].first = e;
e = (struct dege*)malloc(sizeof(struct dege));
e->adv = i;
e->next = G->adj[j].first;
G->adj[j].first = e;
}
}
int visited[10];
void DFS(nodes* G, int i)
{
struct dege* e;
visited[i] = 1;
cout << G->adj[i].data<<" ";
e = G->adj[i].first;
while (e)
{
if (visited[e->adv] == 0)
DFS(G, e->adv);
e = e->next;
}
}
void DFStraverse(nodes* G)
{
for (int i = 0; i < G->numnodes; i++)
visited[i] = 0;
for (int i = 0; i < G->numnodes; i++)
if (visited[i] == 0)
DFS(G, i);
}
int main()
{
struct nodes* S;
S = (struct nodes*)malloc(sizeof(struct nodes));
create(S);
DFStraverse(S);
return 0;
}
最終的な実行結果は次のとおりです。
最近、私は少し混乱しています。主な理由は、中間試験の復習によって私自身の復習計画が混乱したためです。
私はこの言葉がとても好きです。「ティーンエイジャーは高いところに登りたいのではなく、安全で健康でありたいと思っています。」