概要
ソースコードをダウンロード:
深さ優先検索 (深さ優先検索、深さ優先検索、DFS とも呼ばれます)、幅優先検索 (幅優先検索、幅優先検索、BFS とも呼ばれます) は非常に基本的なアルゴリズムであり、誰もがよく知っています。 。
まずは視覚化効果を見てみましょう。
1. DFSとBFSの基本概念
抜粋: Mingyin ツリーの幅優先探索アルゴリズムと深さ優先探索アルゴリズム_Mingyin のブログ - CSDN ブログ_深さ優先探索アルゴリズムと幅優先探索アルゴリズム1 ツリーの幅優先探索アルゴリズム 幅優先探索アルゴリズム (幅優先探索)、幅優先探索、または風景優先とも呼ばれます。検索。ルート ノードから開始し、ツリーの幅に沿ってツリーのノードを横断します。すべてのノードにアクセスすると、アルゴリズムは中止されます。上に示したバイナリ ツリーに示されているように、A が最初にアクセスされ、次に B、C、次に D、E、F、G の順にアクセスされます。では、このアクセスの順序を確保するにはどうすればよいでしょうか? キュー データ構造の助けを借りて、キューは先入れ先出し順序であるため、最初にhttps://blog.csdn.net/lmingyin5/article/details/47282925
幅優先トラバーサルアルゴリズムは、幅優先トラバーサルまたは水平優先トラバーサルとも呼ばれ、ルート ノードから開始し、ツリーの幅に沿ってツリーのノードをトラバースします。すべてのノードにアクセスすると、アルゴリズムは中止されます。
深さ優先トラバーサル アルゴリズムは、トラバーサル アルゴリズムの一種です。深さに沿ってツリーのノードをトラバースすることです。
ノード v のすべてのエッジが探索されると、検索はノード v が見つかったエッジの開始ノードに戻ります。このプロセスは、ソース ノードから到達可能なすべてのノードが検出されるまで続行されます。
まだ検出されていないノードがある場合は、それらの 1 つをソース ノードとして選択し、上記のプロセスを繰り返し、すべてのノードが訪問されるまでプロセス全体が繰り返されます。
抜粋: Xiaofengxue IT https://blog.csdn.net/EngineerofAI/article/details/120590420幅優先検索アルゴリズムは、バイナリ ツリーのレベル順の走査に似ており、階層的な検索プロセスです。 forward は頂点のバッチにアクセスする可能性があり、バックオフがないため、再帰的アルゴリズムではありません。最初に開始頂点 v を訪問し、次に v から開始して、v の各未訪問の隣接頂点 w1、w2、...、wi を訪問し、次に w1、w2、...、wi のすべての未訪問の隣接頂点を順番に訪問します。次に、これらの訪問した頂点から始めて、未訪問の隣接する頂点をすべて訪問し、グラフ内のすべての頂点が訪問されるまでこれを繰り返します。
幅優先検索とは異なり、深さ優先検索 (DFS) はツリーの事前順序走査に似ています。プロセス: 頂点 V0 から開始して道路に沿って最後まで進み、目的の解に到達できない場合は、前のノードに戻り、別の道路から開始してすべての頂点が到達するまで終点まで進みます。このような できるだけ深く進むという概念が深さ優先の概念です。
2. DFS と BFS の C# 実装
引用元: csdnBigBoy
コードが利用可能で、コメントが明確かつ包括的であるため、注意深く読むことができます。
3. DFS と BFS の視覚的な実装
学生はよく「良いプログラムとは何ですか?」と尋ねます。最も基本的なものは次のとおりです。
(1) 読みやすい: プログラムは読みやすく、コメントは合理的であり、形式は適切である必要があります。
(2) 見栄えの良い: プログラム ロジック、明確な思考、モジュールとセクションの合理的な分割、一貫した命名規則。
(3) 使いやすさ: 通常の操作、安定性が第一、パフォーマンスが二番目。
したがって、プログラムの実行結果がすぐにわかります。プログラムの視覚化は重要な形式です。
まずは効果を見てみましょう。
上記のコード (csdnBigBoy のコードから改変):
using System;
using System.Text;
using System.Linq;
using System.Data;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
namespace DFSBFS
{
public partial class Form1 : Form
{
TreeInfo TreeTotal = null;
List<NodeInfo> PathResult = null;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.Text = "深度优先搜索算法DFS,广度优先搜索算法BFS,可视化编程实例";
button1.Text = "深度优先搜索算法 DFS"; button1.Cursor = Cursors.Hand;
button2.Text = "广度优先搜索算法 BFS"; button2.Cursor = Cursors.Hand;
panel1.Dock = DockStyle.Top; panel2.Dock = DockStyle.Fill;
webBrowser1.Navigate("http://www.315soft.com");
}
private static TreeInfo TreeGrowth()
{
TreeInfo tree = new TreeInfo();
tree.Append(new NodeInfo(1, new int[] { 3, 2, 4 }));
tree.Append(new NodeInfo(2, new int[] { 1, 5, 8, 300 }));
tree.Append(new NodeInfo(3, new int[] { 1, 7, 9, 100 }));
tree.Append(new NodeInfo(4, new int[] { 1, 6, 10, 200 }));
tree.Append(new NodeInfo(5, new int[] { 2 }));
tree.Append(new NodeInfo(6, new int[] { 4 }));
tree.Append(new NodeInfo(7, new int[] { 3 }));
tree.Append(new NodeInfo(8, new int[] { 2 }));
tree.Append(new NodeInfo(9, new int[] { 3, 400 }));
tree.Append(new NodeInfo(10, new int[] { 4 }));
tree.Append(new NodeInfo(100, new int[] { 3 }));
tree.Append(new NodeInfo(200, new int[] { 4 }));
tree.Append(new NodeInfo(300, new int[] { 2 }));
tree.Append(new NodeInfo(400, new int[] { 9 }));
return tree;
}
/// <summary>
/// 深度优先搜索算法
/// Deep First Search Algorithm
/// </summary>
/// <param name="Tree"></param>
/// <param name="startNode"></param>
private static List<NodeInfo> DFS(TreeInfo Tree, NodeInfo startNode)
{
// 详细注解请浏览原文
// https://blog.csdn.net/CSDNBigBoy/article/details/80635220
List<NodeInfo> path = new List<NodeInfo>();
path.Add(startNode);
List<NodeInfo> b = new List<NodeInfo>();
b.Add(startNode);
startNode.Visited = true;
NodeInfo a = new NodeInfo();
while (b.Count != 0)
{
List<NodeInfo> b_nbs = Tree.FindNeighbors(b[b.Count - 1]);
a = b_nbs.FirstOrDefault(k => !k.Visited);
while (a != null)
{
b.Add(a);
path.Add(a);
a.Visited = true;
b_nbs = Tree.FindNeighbors(b[b.Count - 1]);
a = b_nbs.FirstOrDefault(k => !k.Visited);
}
if (a == null)
{
b.Remove(b[b.Count - 1]);
}
}
return path;
}
/// <summary>
/// 广度优先搜索算法
/// Breadth First Search Algorithm
/// </summary>
/// <param name="Tree"></param>
/// <param name="startNode"></param>
private static List<NodeInfo> BFS(TreeInfo Tree, NodeInfo startNode)
{
// 详细注解请浏览原文
// https://blog.csdn.net/CSDNBigBoy/article/details/80635220
List<NodeInfo> path = new List<NodeInfo>();
path.Add(startNode);
Queue qq = new Queue();
qq.Enqueue(startNode);
startNode.Visited = true;
NodeInfo a = new NodeInfo();
while (qq.Count != 0)
{
a = (NodeInfo)qq.Dequeue();
List<NodeInfo> a_nbs = Tree.FindNeighbors(a);
foreach (NodeInfo tmp in a_nbs.Where(k => !k.Visited).ToList())
{
qq.Enqueue(tmp);
path.Add(tmp);
tmp.Visited = true;
}
}
return path;
}
private string ShowPath()
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
sb.AppendLine("<html xmlns=\"http://www.w3.org/1999/xhtml\" >");
sb.AppendLine("<head>");
sb.AppendLine("<style>");
sb.AppendLine(".ball1 { width:30px;height:30px;font-size:12px;line-height:30px;border:solid 1px #999999;background-color:#F0F0F0;text-align:center;border-radius:15px; }");
sb.AppendLine(".ball2 { width:30px;height:30px;font-size:12px;line-height:30px;border:solid 1px #FF6701;background-color:#FA9A70;text-align:center;border-radius:15px; }");
sb.AppendLine(".node { float:left;width:20px;height:20px;font-size:12px;line-height:20px;border:solid 1px #FF6701;background-color:#FAFAF0;text-align:center;border-radius:10px; }");
sb.AppendLine(".arrow { float:left;width:20px;height:20px;font-size:12px;line-height:20px;border:solid 0px #FF6701;background-color:#FFFFFF;text-align:center; }");
sb.AppendLine("</style>");
sb.AppendLine("<script type=\"text/javascript\" src=\"" + Application.StartupPath.Replace(@"\", @"/") + "/jquery-3.6.0.min.js\"></script>");
sb.AppendLine("<script type=\"text/javascript\" src=\"" + Application.StartupPath.Replace(@"\", @"/") + "/dfsbfs.js\"></script>");
sb.AppendLine("</head>");
sb.AppendLine("<body>");
sb.AppendLine("<img src='https://img-blog.csdn.net/20180609184540410' width='400'><br>");
sb.AppendLine(ShowInTable());
sb.AppendLine("<br>");
int k = 0;
foreach (NodeInfo node in PathResult)
{
sb.AppendLine("<div class='node'>" + node.Id + "</div>");
sb.AppendLine("<div class='arrow'>→</div>");
if (k >= loop) break;
k++;
}
sb.AppendLine("<script language=\"javascript\">");
sb.AppendLine("$(document).ready(function() {");
sb.AppendLine("CanvasCreate();");
foreach(NodeInfo node in TreeTotal.Nodes)
{
for (int i = 0; i < node.Neighbors.Length; i++)
{
sb.AppendLine("Connect(\"" + node.Id + "\", \""+ node.Neighbors[i] + "\");");
}
}
sb.AppendLine("});");
sb.AppendLine("</script>");
sb.AppendLine("</body>");
sb.AppendLine("</html>");
return sb.ToString();
}
int loop = 0;
private void button1_Click(object sender, EventArgs e)
{
TreeTotal = TreeGrowth();
PathResult = DFS(TreeTotal, TreeTotal.First());
timer1.Interval = 1000;
timer1.Enabled = true;
loop = 0;
}
private void button2_Click(object sender, EventArgs e)
{
TreeTotal = TreeGrowth();
PathResult = BFS(TreeTotal, TreeTotal.First());
timer1.Interval = 1000;
timer1.Enabled = true;
loop = 0;
}
public string ShowInTable()
{
int[,] matrix = new int[4, 9]
{
{ 0,0,0,0,1,0,0,0,0 },
{ 0,3,0,0,2,0,0,4,0 },
{ 7,9,100,5,8,300,6,10,200 },
{ 0,400,0,0,0,0,0,0,0 },
};
for(int i = 0; i < TreeTotal.Nodes.Count; i++)
{
TreeTotal.Nodes[i].Visited = false;
}
for (int i = 0; i <= loop; i++)
{
PathResult[i].Visited = true;
}
StringBuilder sb = new StringBuilder();
sb.AppendLine("<style>td { padding:10px; }</style>");
sb.AppendLine("<table width='300' border='1' bordercolor='#EEEEEE' style='border-collapse:collapse;'>");
for (int y = 0; y < 4; y++)
{
sb.AppendLine("<tr>");
for (int x = 0; x < 9; x++)
{
int nk = matrix[y, x];
if (nk >= 100) nk = 10 + nk / 100;
if (nk == 0)
{
sb.Append("<td></td>");
}
else if (TreeTotal.Nodes[nk - 1].Visited == true)
{
sb.Append("<td><div class='ball2'>" + TreeTotal.Nodes[nk - 1].Id + "</div></td>");
}
else
{
sb.Append("<td><div class='ball1'>" + TreeTotal.Nodes[nk - 1].Id + "</div></td>");
}
}
sb.AppendLine("</tr>");
}
sb.AppendLine("</table>");
return sb.ToString();
}
private void timer1_Tick(object sender, EventArgs e)
{
if (loop < PathResult.Count)
{
webBrowser1.DocumentText = ShowPath();
loop++;
return;
}
loop = 0;
}
}
/// <summary>
/// 树
/// </summary>
public class TreeInfo
{
/// <summary>
/// 所有节点
/// </summary>
public List<NodeInfo> Nodes { get; set; } = new List<NodeInfo>();
/// <summary>
/// 新增节点
/// </summary>
/// <param name="node"></param>
public void Append(NodeInfo node)
{
Nodes.Add(node);
}
/// <summary>
/// 第一个节点
/// </summary>
/// <returns></returns>
public NodeInfo First()
{
return Nodes[0];
}
/// <summary>
/// 搜索指定节点的邻居(邻接节点)
/// </summary>
/// <param name="node"></param>
/// <returns></returns>
public List<NodeInfo> FindNeighbors(NodeInfo node)
{
List<NodeInfo> list = new List<NodeInfo>();
foreach (int nx in node.Neighbors)
{
list.Add(Nodes.FirstOrDefault(k => k.Id == nx));
}
return list;
}
}
/// <summary>
/// 节点信息
/// 来自:https://blog.csdn.net/CSDNBigBoy/article/details/80635220
/// </summary>
public class NodeInfo
{
/// <summary>
/// 节点的id
/// </summary>
public int Id { get; set; } = 0;
/// <summary>
/// 是否被遍历过的标记,默认false表示没有被遍历过
/// </summary>
public bool Visited { get; set; } = false;
/// <summary>
/// 用于存储该元素的临接元素的id
/// </summary>
public int[] Neighbors { get; set; } = null;
/// <summary>
/// 构造函数
/// </summary>
public NodeInfo() { }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="id"></param>
/// <param name="neighbors"></param>
public NodeInfo(int id, int[] neighbors)
{
Id = id;
Neighbors = neighbors;
}
}
}
アニメーションがあると効果が違います!
2 つの js ファイルが必要です。1 つは jQuery です。自分でダウンロードしてください。
ツリー構造を描画 (描画) するためのもう 1 つのソース コード、dfsbfs.js。
プロジェクト パッケージでは、それをダウンロードして解凍するだけです。
—————————————————————
315SOFT.COMおよびTRUFFER.CNによる電源