Ya, Anda dapat melakukan kompresi ini dalam waktu , tetapi itu tidak mudah :) Pertama-tama kita membuat beberapa pengamatan dan kemudian menyajikan algoritma. Kami menganggap pohon tersebut awalnya tidak dikompresi - ini tidak benar-benar diperlukan tetapi membuat analisis lebih mudah.O(nlogn)
Pertama, kami mencirikan 'kesetaraan struktural' secara induktif. Biarkan dan menjadi dua (sub) pohon. Jika dan keduanya pohon nol (tidak memiliki simpul sama sekali), mereka secara struktural setara. Jika dan keduanya bukan pohon nol, maka mereka secara struktural setara jika anak-anak kiri mereka setara secara struktural dan anak-anak kanan mereka setara secara struktural. 'Kesetaraan struktural' adalah titik tetap minimal atas definisi-definisi ini.T ′ T T ′ T T ′TT′TT′TT′
Sebagai contoh, setiap dua simpul daun secara struktural setara, karena mereka berdua memiliki pohon nol sebagai kedua anak-anak mereka, yang secara struktural setara.
Karena agak menjengkelkan untuk mengatakan 'anak-anak kiri mereka secara struktural setara dan begitu juga anak-anak mereka', kita akan sering mengatakan 'anak-anak mereka setara secara struktural' dan bermaksud sama. Perhatikan juga kita kadang mengatakan 'titik ini' ketika kita berarti 'subtree berakar pada titik ini'.
Definisi di atas segera memberi kita petunjuk bagaimana melakukan kompresi: jika kita mengetahui kesetaraan struktural semua sub-pohon dengan kedalaman paling banyak , maka kita dapat dengan mudah menghitung kesetaraan struktural dari sub-pohon dengan kedalaman . Kita harus melakukan perhitungan ini dengan cara yang cerdas untuk menghindari waktu berjalan .d + 1 O ( n 2 )dd+1O(n2)
Algoritme akan menetapkan pengidentifikasi untuk setiap titik selama eksekusi. Identifier adalah angka dalam set . Pengidentifikasi unik dan tidak pernah berubah: oleh karena itu kami menganggap kami menetapkan beberapa variabel (global) ke 1 pada awal algoritma, dan setiap kali kami menetapkan pengidentifikasi ke beberapa titik, kami menetapkan nilai saat ini dari variabel tersebut ke titik dan penambahan nilai variabel itu.{1,2,3,…,n}
Kami pertama-tama mengubah pohon input menjadi (paling banyak ) daftar yang berisi simpul dengan kedalaman yang sama, bersama dengan pointer ke induknya. Ini mudah dilakukan dalam waktu O ( n ) .nO(n)
Pertama-tama kita mengompres semua daun (kita dapat menemukan daun-daun ini dalam daftar dengan simpul kedalaman 0) menjadi satu simpul tunggal. Kami menetapkan titik ini sebagai pengidentifikasi. Kompresi dua simpul dilakukan dengan mengarahkan induk dari salah satu simpul untuk menunjuk ke simpul lain sebagai gantinya.
Kami membuat dua pengamatan: pertama, setiap simpul memiliki anak-anak dengan kedalaman yang sangat kecil, dan kedua, jika kami telah melakukan kompresi pada semua simpul kedalaman yang lebih kecil dari (dan telah memberi mereka pengidentifikasi), maka dua simpul kedalaman d secara struktural setara dan dapat dikompresi jika pengidentifikasi anak-anak mereka bertepatan. Pengamatan terakhir ini mengikuti dari argumen berikut: dua simpul secara struktural setara jika anak-anak mereka setara secara struktural, dan setelah kompresi ini berarti pointer mereka menunjuk ke anak yang sama, yang pada gilirannya berarti pengidentifikasi anak-anak mereka sama.dd
Kami beralih melalui semua daftar dengan node dengan kedalaman yang sama dari kedalaman kecil ke kedalaman besar. Untuk setiap level kami membuat daftar pasangan bilangan bulat, di mana setiap pasangan sesuai dengan pengidentifikasi anak-anak dari beberapa titik pada tingkat itu. Kami memiliki dua simpul pada level tersebut yang secara struktural setara jika pasangan integer yang sesuai adalah sama. Dengan menggunakan pemesanan leksikografis, kita dapat mengurutkannya dan mendapatkan set pasangan integer yang sama. Kami memampatkan set ini ke simpul tunggal seperti di atas dan memberi mereka pengidentifikasi.
Pengamatan di atas membuktikan bahwa pendekatan ini bekerja dan menghasilkan pohon terkompresi. Total waktu berjalan adalah ditambah waktu yang dibutuhkan untuk mengurutkan daftar yang kami buat. Karena jumlah total pasangan integer yang kita buat adalah n , ini memberi kita bahwa total waktu berjalan adalah O ( n log n ) , seperti yang diperlukan. Menghitung berapa banyak node yang tersisa di akhir prosedur adalah sepele (lihat saja berapa banyak pengidentifikasi yang telah kami bagikan).O(n)nO(nlogn)