Có, bạn có thể thực hiện nén này trong thời gian , nhưng không dễ dàng :) Trước tiên chúng tôi thực hiện một số quan sát và sau đó trình bày thuật toán. Chúng tôi cho rằng cây ban đầu không bị nén - điều này không thực sự cần thiết nhưng giúp phân tích dễ dàng hơn.O(nlogn)
Đầu tiên, chúng tôi mô tả "sự bình đẳng về cấu trúc" theo quy nạp. Đặt và là hai (phụ) cây. Nếu và đều là cây null (hoàn toàn không có đỉnh), thì chúng tương đương về mặt cấu trúc. Nếu và đều không phải là cây rỗng, thì chúng tương đương về mặt cấu trúc nếu con trái của chúng có cấu trúc tương đương và con phải của chúng có cấu trúc tương đương. "Tương đương cấu trúc" là điểm cố định tối thiểu so với các định nghĩa này.T ' T T ' T T 'TT′TT′TT′
Ví dụ, bất kỳ hai nút lá nào đều có cấu trúc tương đương nhau, vì cả hai đều có các cây null là cả hai con của chúng, tương đương về mặt cấu trúc.
Vì thật khó chịu khi nói 'những đứa con bên trái của chúng có cấu trúc tương đương nhau và những đứa con bên phải của chúng cũng vậy', chúng tôi thường sẽ nói 'những đứa trẻ của chúng có cấu trúc tương đương' và có cùng ý định. Cũng lưu ý đôi khi chúng ta nói 'đỉnh này' khi chúng ta muốn nói 'cây con bắt nguồn từ đỉnh này'.
Định nghĩa trên ngay lập tức cho chúng ta một gợi ý về cách thực hiện nén: nếu chúng ta biết tương đương cấu trúc của tất cả các cây con có độ sâu tối đa , thì chúng ta có thể dễ dàng tính toán tương đương cấu trúc của các cây con có độ sâu . Chúng ta phải thực hiện tính toán này một cách thông minh để tránh thời gian chạy .d + 1 O ( n 2 )dd+1O(n2)
Thuật toán sẽ gán các định danh cho mọi đỉnh trong quá trình thực thi. Mã định danh là một số trong tập . Mã định danh là duy nhất và không bao giờ thay đổi: do đó, chúng tôi giả sử chúng tôi đặt một số biến (toàn cầu) thành 1 khi bắt đầu thuật toán và mỗi khi chúng tôi gán một mã định danh cho một số đỉnh, chúng tôi gán giá trị hiện tại của biến đó cho đỉnh và gia tăng giá trị của biến đó.{1,2,3,…,n}
Đầu tiên chúng ta chuyển đổi cây đầu vào thành (nhiều nhất ) danh sách chứa các đỉnh có độ sâu bằng nhau, cùng với một con trỏ tới cha mẹ của chúng. Điều này được thực hiện dễ dàng trong thời gian O ( n ) .nO(n)
Đầu tiên chúng ta nén tất cả các lá (chúng ta có thể tìm thấy các lá này trong danh sách với các đỉnh có độ sâu 0) thành một đỉnh duy nhất. Chúng tôi gán đỉnh này một định danh. Nén hai đỉnh được thực hiện bằng cách chuyển hướng cha mẹ của một trong hai đỉnh để trỏ đến đỉnh khác thay thế.
Chúng tôi thực hiện hai quan sát: thứ nhất, bất kỳ đỉnh nào cũng có con có độ sâu hoàn toàn nhỏ hơn và thứ hai, nếu chúng tôi thực hiện nén trên tất cả các đỉnh có độ sâu nhỏ hơn (và đã cho chúng định danh), thì hai đỉnh có độ sâu d tương đương về mặt cấu trúc và có thể được nén nếu các định danh của con cái họ trùng khớp. Quan sát cuối cùng này xuất phát từ lập luận sau: hai đỉnh tương đương về mặt cấu trúc nếu con cái của chúng tương đương về mặt cấu trúc và sau khi nén, điều này có nghĩa là con trỏ của chúng chỉ vào cùng một con, điều đó có nghĩa là các định danh của con cái chúng bằng nhau.dd
Chúng tôi lặp qua tất cả các danh sách với các nút có độ sâu bằng nhau từ độ sâu nhỏ đến độ sâu lớn. Đối với mỗi cấp độ, chúng tôi tạo một danh sách các cặp số nguyên, trong đó mỗi cặp tương ứng với các định danh của con của một số đỉnh ở cấp đó. Chúng ta có hai đỉnh ở mức đó tương đương về mặt cấu trúc nếu các cặp số nguyên tương ứng của chúng bằng nhau. Sử dụng thứ tự từ điển, chúng ta có thể sắp xếp chúng và thu được các cặp số nguyên bằng nhau. Chúng tôi nén các bộ này thành các đỉnh đơn như trên và cung cấp cho chúng định danh.
O(n)nO(nlogn)