Khi đi qua một cây / đồ thị, sự khác biệt giữa chiều rộng đầu tiên và độ sâu đầu tiên là gì? Bất kỳ ví dụ mã hóa hoặc mã giả sẽ là tuyệt vời.
Khi đi qua một cây / đồ thị, sự khác biệt giữa chiều rộng đầu tiên và độ sâu đầu tiên là gì? Bất kỳ ví dụ mã hóa hoặc mã giả sẽ là tuyệt vời.
Câu trả lời:
Hai thuật ngữ này phân biệt giữa hai cách khác nhau để đi trên cây.
Nó có lẽ là dễ nhất chỉ để thể hiện sự khác biệt. Hãy xem xét cây:
A
/ \
B C
/ / \
D E F
Một chiều sâu đầu tiên sẽ truy cập vào các nút theo thứ tự này
A, B, D, C, E, F
Chú ý rằng bạn đi tất cả các cách xuống một chân trước khi chuyển.
Một chiều rộng đầu tiên sẽ truy cập vào nút theo thứ tự này
A, B, C, D, E, F
Ở đây chúng tôi làm việc tất cả các cách trên mỗi cấp độ trước khi đi xuống.
(Lưu ý rằng có một sự mơ hồ trong các đơn hàng truyền tải và tôi đã gian lận để duy trì thứ tự "đọc" ở mỗi cấp độ của cây. Trong cả hai trường hợp tôi có thể đến B trước hoặc sau C, và tương tự tôi có thể nhận được E trước hoặc sau F. Điều này có thể có hoặc không quan trọng, tùy thuộc vào ứng dụng của bạn ...)
Cả hai loại truyền tải đều có thể đạt được với mã giả:
Store the root node in Container
While (there are nodes in Container)
N = Get the "next" node from Container
Store all the children of N in Container
Do some work on N
Sự khác biệt giữa hai thứ tự truyền tải nằm ở sự lựa chọn Container
.
Việc thực hiện đệ quy trông giống như
ProcessNode(Node)
Work on the payload Node
Foreach child of Node
ProcessNode(child)
/* Alternate time to work on the payload Node (see below) */
Đệ quy kết thúc khi bạn đến một nút không có con, vì vậy nó được đảm bảo kết thúc cho các đồ thị hữu hạn, theo chu kỳ.
Tại thời điểm này, tôi vẫn bị lừa một chút. Với một chút thông minh, bạn cũng có thể làm việc trên các nút theo thứ tự này:
D, B, E, F, C, A
đó là một biến thể của độ sâu - trước tiên, trong đó tôi không thực hiện công việc tại mỗi nút cho đến khi tôi đi ngược lên cây. Tuy nhiên tôi đã đến thăm các nút cao hơn trên đường xuống để tìm con của họ.
Truyền tải này khá tự nhiên trong triển khai đệ quy (sử dụng dòng "Thời gian thay thế" ở trên thay vì dòng "Công việc" đầu tiên) và không quá khó nếu bạn sử dụng ngăn xếp rõ ràng, nhưng tôi sẽ để nó như một bài tập.
A, B, D, C, E, F
- phiên bản đầu tiên được trình bày), infix ( D, B, A, E, C, F
- được sử dụng để sắp xếp: thêm dưới dạng cây AVL sau đó đọc infix) hoặc postfix ( D, B, E, F, C, A
thay thế được trình bày). Các tên được đưa ra bởi vị trí mà bạn xử lý root. Cần lưu ý rằng infix chỉ thực sự có ý nghĩa đối với cây nhị phân. @batbrat đó là những cái tên ... được đưa ra từ khi bạn hỏi, có lẽ bạn đã biết.
Bức ảnh này sẽ cho bạn ý tưởng về bối cảnh sử dụng các từ rộng và sâu .
Thuật toán tìm kiếm sâu đầu tiên hoạt động như thể nó muốn càng xa điểm xuất phát càng nhanh càng tốt.
Nó thường sử dụng Stack
để ghi nhớ nơi cần đi khi đến ngõ cụt.
Các quy tắc cần tuân theo: Đẩy đỉnh A đầu tiên vào Stack
Mã Java:
public void searchDepthFirst() {
// Begin at vertex 0 (A)
vertexList[0].wasVisited = true;
displayVertex(0);
stack.push(0);
while (!stack.isEmpty()) {
int adjacentVertex = getAdjacentUnvisitedVertex(stack.peek());
// If no such vertex
if (adjacentVertex == -1) {
stack.pop();
} else {
vertexList[adjacentVertex].wasVisited = true;
// Do something
stack.push(adjacentVertex);
}
}
// Stack is empty, so we're done, reset flags
for (int j = 0; j < nVerts; j++)
vertexList[j].wasVisited = false;
}
Ứng dụng : Các tìm kiếm đầu tiên thường được sử dụng trong các mô phỏng trò chơi (và các tình huống giống như trò chơi trong thế giới thực). Trong một trò chơi thông thường, bạn có thể chọn một trong nhiều hành động có thể. Mỗi lựa chọn dẫn đến những lựa chọn khác, mỗi lựa chọn dẫn đến những lựa chọn khác, và tiếp tục thành một biểu đồ khả năng hình cây ngày càng mở rộng.
Queue
.Mã Java:
public void searchBreadthFirst() {
vertexList[0].wasVisited = true;
displayVertex(0);
queue.insert(0);
int v2;
while (!queue.isEmpty()) {
int v1 = queue.remove();
// Until it has no unvisited neighbors, get one
while ((v2 = getAdjUnvisitedVertex(v1)) != -1) {
vertexList[v2].wasVisited = true;
// Do something
queue.insert(v2);
}
}
// Queue is empty, so we're done, reset flags
for (int j = 0; j < nVerts; j++)
vertexList[j].wasVisited = false;
}
Ứng dụng : Tìm kiếm theo chiều rộng đầu tiên trước tiên tìm thấy tất cả các đỉnh nằm cách điểm bắt đầu một cạnh, sau đó tất cả các đỉnh nằm cách hai cạnh, v.v. Điều này hữu ích nếu bạn đang cố gắng tìm đường đi ngắn nhất từ đỉnh bắt đầu đến một đỉnh đã cho.
Hy vọng rằng điều đó là đủ để hiểu các tìm kiếm Breadth-First và Depth-First. Để đọc thêm, tôi muốn giới thiệu chương Đồ thị từ một cuốn sách cấu trúc dữ liệu tuyệt vời của Robert Lafore.
Cho cây nhị phân này:
Breadth First Traversal:
Đi qua từng cấp độ từ trái sang phải.
"Tôi là G, con tôi là D và tôi, cháu của tôi là B, E, H và K, cháu của họ là A, C, F"
- Level 1: G
- Level 2: D, I
- Level 3: B, E, H, K
- Level 4: A, C, F
Order Searched: G, D, I, B, E, H, K, A, C, F
Depth First Traversal:
Traversal không được thực hiện ACROSS toàn bộ các cấp tại một thời điểm. Thay vào đó, di chuyển qua lặn vào DEPTH (từ gốc đến lá) của cây trước. Tuy nhiên, nó phức tạp hơn một chút so với chỉ đơn giản là lên xuống.
Có ba phương pháp:
1) PREORDER: ROOT, LEFT, RIGHT.
You need to think of this as a recursive process:
Grab the Root. (G)
Then Check the Left. (It's a tree)
Grab the Root of the Left. (D)
Then Check the Left of D. (It's a tree)
Grab the Root of the Left (B)
Then Check the Left of B. (A)
Check the Right of B. (C, and it's a leaf node. Finish B tree. Continue D tree)
Check the Right of D. (It's a tree)
Grab the Root. (E)
Check the Left of E. (Nothing)
Check the Right of E. (F, Finish D Tree. Move back to G Tree)
Check the Right of G. (It's a tree)
Grab the Root of I Tree. (I)
Check the Left. (H, it's a leaf.)
Check the Right. (K, it's a leaf. Finish G tree)
DONE: G, D, B, A, C, E, F, I, H, K
2) INORDER: LEFT, ROOT, RIGHT
Where the root is "in" or between the left and right child node.
Check the Left of the G Tree. (It's a D Tree)
Check the Left of the D Tree. (It's a B Tree)
Check the Left of the B Tree. (A)
Check the Root of the B Tree (B)
Check the Right of the B Tree (C, finished B Tree!)
Check the Right of the D Tree (It's a E Tree)
Check the Left of the E Tree. (Nothing)
Check the Right of the E Tree. (F, it's a leaf. Finish E Tree. Finish D Tree)...
Onwards until...
DONE: A, B, C, D, E, F, G, H, I, K
3) POSTORDER:
LEFT, RIGHT, ROOT
DONE: A, C, B, F, E, D, H, K, I, G
Cách sử dụng (còn gọi là tại sao chúng ta quan tâm):
Tôi thực sự rất thích cách giải thích Quora đơn giản này về các phương pháp Traversal Depth First Depth và cách chúng thường được sử dụng:
"In-Order Traversal sẽ in các giá trị [để BST (cây tìm kiếm nhị phân)] "
" Truyền tải trước đơn đặt hàng được sử dụng để tạo một bản sao của [cây tìm kiếm nhị phân]. "
"Truyền tải bưu điện được sử dụng để xóa [cây tìm kiếm nhị phân]."
https://www.quora.com/What-is-the-use-of-pre-order-and-post-order-traversal-of-binary-trees-in-computing
Tôi nghĩ sẽ rất thú vị khi viết cả hai theo cách mà chỉ bằng cách chuyển đổi một số dòng mã sẽ cung cấp cho bạn một thuật toán này hoặc thuật toán khác, do đó bạn sẽ thấy rằng dillema của bạn không mạnh như lúc đầu .
Cá nhân tôi thích cách giải thích của BFS khi làm ngập một cảnh quan: các khu vực có độ cao thấp sẽ bị ngập trước, và chỉ sau đó các khu vực có độ cao mới theo sau. Nếu bạn tưởng tượng các độ cao cảnh quan như các cô lập như chúng ta thấy trong sách địa lý, thì dễ dàng thấy rằng BFS lấp đầy tất cả các khu vực dưới cùng một isoline cùng một lúc, giống như điều này sẽ xảy ra với vật lý. Do đó, việc giải thích độ cao là khoảng cách hoặc chi phí tỷ lệ cho một ý tưởng khá trực quan về thuật toán.
Với suy nghĩ này, bạn có thể dễ dàng điều chỉnh ý tưởng đằng sau tìm kiếm đầu tiên để tìm cây bao trùm tối thiểu một cách dễ dàng, con đường ngắn nhất và nhiều thuật toán tối thiểu hóa khác.
Tôi chưa thấy bất kỳ sự giải thích trực quan nào về DFS (chỉ có tiêu chuẩn về mê cung, nhưng nó không mạnh bằng BFS và lũ lụt), vì vậy đối với tôi, dường như BFS có tương quan tốt hơn với các hiện tượng vật lý như được mô tả ở trên, trong khi DFS tương quan tốt hơn với các lựa chọn dillema trên các hệ thống hợp lý (tức là người hoặc máy tính quyết định di chuyển để thực hiện một trò chơi cờ vua hoặc đi ra khỏi mê cung).
Vì vậy, đối với tôi sự khác biệt giữa những lời nói dối về hiện tượng tự nhiên phù hợp nhất với mô hình lan truyền của chúng (chuyển vị) trong cuộc sống thực.