Chiều rộng đầu tiên Vs Độ sâu đầu tiên


171

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.


6
Bạn đã kiểm tra wikipedia ( độ sâu đầu tiên , chiều rộng đầu tiên )? Có những ví dụ mã trên các trang đó, cùng với rất nhiều hình ảnh đẹp.
rmeador

Tôi cũng có suy nghĩ đó, nhưng sau đó các ví dụ đưa ra đẹp hơn một chút so với những gì được tìm thấy trên wikipedia ....
jonnybazookatone

Câu trả lời:


291

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.

  • Đối với độ sâu đầu tiên sử dụng một ngăn xếp. (Việc triển khai đệ quy sử dụng ngăn xếp cuộc gọi ...)
  • Đối với chiều rộng đầu tiên sử dụng một hàng đợi.

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.


@dmckee Cảm ơn! Tôi tin rằng bạn có nghĩa là "Làm việc trên tải trọng tại Node", phải không?
batbrat

4
Có thể lưu ý rằng bạn có thể sửa đổi phiên bản đầu tiên chuyên sâu để có tiền tố ( 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, Athay 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.
Theraot

@Theraot cảm ơn vì đã thêm nó vào! Vâng, tôi biết về các loại giao dịch này và tại sao Infix chỉ có ý nghĩa đối với cây nhị phân.
batbrat

Làm thế nào để quyết định giải pháp nào có độ phức tạp không gian hoặc thời gian tốt hơn?
IgorGanapolsky 10/03/2016

1
@IgorGanapolsky Nên giống nhau cho cả hai về nguyên tắc (xét cho cùng, chúng sử dụng cùng một mã). Một câu hỏi thú vị hơn là cách chúng tác động đến bộ đệm và bộ làm việc, nhưng tôi nghĩ điều đó sẽ phụ thuộc vào hình thái của cây.
dmckee --- ex-moderator mèo con

95

Hiểu các điều khoản:

Bức ảnh này sẽ cho bạn ý tưởng về bối cảnh sử dụng các từ rộngsâu .

Hiểu về chiều rộng và chiều sâu


Độ sâu tìm kiếm đầu tiên:

Độ sâu tìm kiếm đầu tiên

  • 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

    1. Nếu có thể, hãy truy cập một đỉnh không mong muốn liền kề, đánh dấu nó là đã truy cập và đẩy nó lên ngăn xếp.
    2. Nếu bạn không thể làm theo Quy tắc 1, thì nếu có thể, hãy bật một đỉnh khỏi ngăn xếp.
    3. Nếu bạn không thể làm theo Quy tắc 1 hoặc Quy tắc 2, bạn đã hoàn thành.
  • 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.


Bề rộng-Tìm kiếm đầu tiên:

Bề rộng-Tìm kiếm đầu tiên

  • Thuật toán tìm kiếm đầu tiên thích ở càng gần điểm bắt đầu càng tốt.
  • Loại tìm kiếm này thường được thực hiện bằng cách sử dụng a Queue.
  • Các quy tắc cần tuân thủ: Hãy bắt đầu Vertex A đỉnh hiện tại
    1. Ghé thăm đỉnh không mong muốn tiếp theo (nếu có một) liền kề với đỉnh hiện tại, đánh dấu nó và chèn nó vào hàng đợi.
    2. Nếu bạn không thể thực hiện Quy tắc 1 vì không còn các đỉnh không mong muốn nữa, hãy xóa một đỉnh khỏi hàng đợi (nếu có thể) và biến nó thành đỉnh hiện tại.
    3. Nếu bạn không thể thực hiện Quy tắc 2 vì hàng đợi trống, bạn đã hoàn thành.
  • 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.


6
Nếu tôi có thêm mười phiếu bầu nữa, tôi sẽ làm như vậy.
snr

@snr bạn có thể thưởng một tiền thưởng;)
Snow

@Snow nếu bạn nói chỉ thị của nó, tôi có thể. Tôi không biết làm thế nào.
sn

Cảm ơn bạn @snr, tôi rất vui khi nhận được tiền thưởng đầu tiên của tôi. Tôi đánh giá cao rất nhiều.
Yogesh Umesh Vaity

1
Cảm ơn @Snow, tôi rất vui vì các bạn thấy câu trả lời của tôi hữu ích.
Yogesh Umesh Vaity

4

Cho cây nhị phân này:

nhập mô tả hình ảnh ở đâ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


2

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.


1
Bạn có thể thực hiện chúng với một thuật toán tương tự, chỉ cần sử dụng stack cho DFS và xếp hàng cho BFS. Vấn đề với BFS là bạn cần theo dõi tất cả các nút được nhìn thấy cho đến nay. DFS trong vật lý .. Tôi tưởng tượng các vũ trụ thay thế và bạn muốn một vũ trụ có sự sống, tất cả những đứa trẻ gốc rễ, là những vụ nổ lớn khác nhau và bạn đi đến tận cùng với cái chết của vũ trụ, không có sự sống? bạn quay trở lại phân nhánh cuối cùng và thử một lượt khác, cho đến khi tất cả đã cạn kiệt và bạn đi đến vụ nổ lớn tiếp theo, thiết lập các định luật vật lý mới cho vũ trụ mới. siêu trực quan. một vấn đề tốt là tìm cách với con ngựa trong bàn cờ vua.
juanmf
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.