[Powered by Google Translate] [Seksyen 7: Lebih Selesa] [Rob Bowden] [Universiti Harvard] [Ini adalah CS50] [CS50.TV] Semua hak. Jadi seperti yang saya katakan dalam e-mel saya, ini akan menjadi bahagian binari pokok-intensif. Tetapi ada tidak begitu banyak soalan. Jadi kita pergi untuk mencuba dan menarik keluar setiap soalan dan pergi ke detail menyakitkan semua cara terbaik untuk melakukan sesuatu. Jadi betul-betul pada permulaan, kita pergi melalui lukisan sampel pokok binari dan barangan. Jadi di sini, "Ingatlah bahawa pokok binari mempunyai nod yang sama kepada mereka senarai berkaitan, kecuali bukannya satu penunjuk terdapat dua: satu untuk 'anak' kiri dan satu untuk 'kanak-kanak' yang betul. " Jadi pokok binari adalah sama seperti senarai berpaut, kecuali struct akan mempunyai dua petunjuk. Ada pokok trinary, yang akan mempunyai tiga petunjuk, terdapat N-ary pokok, yang hanya mempunyai penunjuk generik yang anda kemudian perlu malloc menjadi cukup besar untuk mempunyai petunjuk yang cukup untuk semua kanak-kanak yang mungkin. Jadi pokok binari hanya berlaku untuk mempunyai beberapa berterusan dua. Jika anda mahu, anda boleh memberikan senarai berpaut sebagai pokok unari, tetapi saya tidak fikir sesiapa memanggilnya bahawa. "Lukiskan gambarajah kotak dan anak panah nod pokok binari mengandungi nombor kegemaran Nate, 7, di mana setiap penunjuk kanak-kanak adalah batal. " Mod Jadi iPad. Ia akan menjadi agak mudah. Kami hanya akan mempunyai nod, saya akan menarik sebagai persegi. Dan saya akan menarik nilai di sini. Jadi nilai akan pergi di sini, dan kemudian turun di sini kita akan mempunyai penunjuk kiri di sebelah kiri dan penunjuk yang betul di sebelah kanan. Dan ia adalah sangat banyak supaya konvensyen memanggilnya kiri dan kanan, penunjuk nama. Kedua-dua akan menjadi batal. Itu hanya akan batal, dan yang hanya akan menjadi batal. Okay. Jadi kembali ke sini. "Dengan senarai dikaitkan, kita hanya terpaksa untuk menyimpan penunjuk kepada nod pertama dalam senarai untuk ingat senarai keseluruhan yang berkaitan, atau keseluruhan senarai. Begitu juga, dengan pokok-pokok, kita hanya perlu untuk menyimpan penunjuk kepada nod tunggal untuk ingat keseluruhan pokok. Nod Ini adalah calle 'akar pokok. Membina gambarajah anda dari sebelum atau menarik yang baru seperti yang anda mempunyai gambaran kotak dan anak panah pokok binari dengan nilai 7, maka 3 di sebelah kiri, kemudian 9 di sebelah kanan, dan kemudian 6 pada sebelah kanan daripada 3. " Mari kita lihat jika saya boleh ingat semua itu dalam kepala saya. Jadi ini akan menjadi akar kami di sini. Kami akan mempunyai penunjuk beberapa tempat, sesuatu yang kita akan panggil akar, dan ia menunjuk kepada lelaki ini. Sekarang untuk membuat nod baru, apa yang kita ada, 3 di sebelah kiri? Jadi nod baru dengan 3, dan ia pada mulanya mata batal. Saya hanya akan meletakkan N. Sekarang kita mahu untuk membuat yang pergi ke sebelah kiri 7. Jadi kita mengubah penunjuk ini kini menunjukkan lelaki ini. Dan kita melakukan perkara yang sama. Kami ingin 9 di sini yang pada mulanya hanya mengatakan batal. Kami akan menukar penunjuk ini, titik hingga 9, dan sekarang kita mahu untuk meletakkan 6 ke kanan 3. Jadi ia akan membuat 6. Dan lelaki itu akan menunjukkan di sana. Okay. Jadi itulah semua ia meminta kita lakukan. Sekarang mari kita pergi atas beberapa istilah. Kita sudah bercakap tentang bagaimana akar pokok itu adalah nod yang paling atas di pokok itu. Satu mengandungi 7. Nod di bawah pokok itu dipanggil daun. Sebarang nod yang hanya mempunyai batal sebagai kanak-kanak adalah daun. Jadi ia adalah mustahil, jika pokok binari kami adalah hanya nod tunggal, bahawa pokok adalah daun, dan itulah ia. "'Ketinggian' pokok itu adalah bilangan hop anda perlu membuat untuk mendapatkan dari atas ke daun. " Kami akan masuk ke dalam, dalam kedua, perbezaan antara pokok binari seimbang dan tidak seimbang, tapi sekarang, ketinggian keseluruhan pokok ini Saya akan katakan ialah 3, walaupun jika anda mengira bilangan hop anda perlu membuat untuk mendapatkan hingga 9, maka ia adalah benar-benar hanya ketinggian 2. Sekarang ini adalah pokok binari yang tidak seimbang, tetapi kita akan bercakap tentang seimbang apabila ia mendapat untuk menjadi relevan. Jadi sekarang kita boleh bercakap tentang nod dalam pokok dari segi relatif kepada nod lain di pokok itu. Jadi sekarang kita mempunyai ibu bapa, anak-anak, adik-beradik, nenek moyang, dan keturunan. Mereka rasa agak biasa, apa yang mereka maksudkan. Jika kita bertanya - ibu bapa itu. Jadi apakah ibu bapa 3? [Pelajar] 7. >> Yeah. Ibu bapa hanya akan menjadi apa yang menunjukkan kepada anda. Kemudian apakah kanak-kanak dari 7? [Pelajar] 3 dan 9. >> Yeah. Perhatikan bahawa "kanak-kanak" bermaksud kanak-kanak, jadi 6 tidak akan terpakai, kerana ia adalah seperti cucu. Tetapi kemudian jika kita pergi keturunan, jadi apa keturunan 7? [Pelajar] 3, 6 dan 9. >> Yeah. Keturunan nod akar akan menjadi segala-galanya di pokok itu, kecuali mungkin nod akar itu sendiri, jika anda tidak mahu menganggap bahawa keturunan. Dan akhirnya, nenek moyang, jadi ia adalah arah bertentangan. Jadi apakah nenek moyang 6? [Pelajar] 3 dan 7. >> Yeah. 9 tidak dimasukkan. Ia hanya belakang keturunan langsung ke akar akan menjadi nenek moyang anda. "Kami mengatakan bahawa pokok binari 'mengarahkan' jika untuk setiap nod dalam pokok itu, semua keturunan di sebelah kiri mempunyai nilai-nilai yang lebih rendah dan semua orang-orang di sebelah kanan mempunyai nilai yang lebih besar. Sebagai contoh, pokok atas diperintahkan tetapi ia tidak hanya susunan mungkin diperintahkan. " Sebelum kita dapat itu, diperintahkan pokok binari juga dikenali sebagai pokok carian binari. Di sini kita berlaku untuk memanggil ia pokok binari diperintahkan, tetapi saya tidak pernah mendengar ia dipanggil pokok binari diperintahkan sebelum, dan pada kuiz kita lebih cenderung untuk meletakkan pokok carian binari. Mereka satu dan sama, dan ia adalah penting anda mengenali perbezaan di antara pokok binari dan pokok carian binari. Satu pokok binari hanya pokok yang mata kepada dua perkara. Setiap nod mata kepada dua perkara. Tidak ada hujah tentang nilai-nilai yang ia menjurus kepada. Jadi seperti di sini, kerana ia adalah pokok carian binari, kita tahu bahawa jika kita pergi kiri 7, maka semua nilai-nilai yang kita mungkin boleh mencapai dengan pergi kiri 7 perlu kurang daripada 7. Perhatikan bahawa semua nilai kurang daripada 7 adalah 3 dan 6. Mereka semua adalah ke kiri 7. Jika kita pergi ke kanan 7, segala-galanya telah menjadi lebih daripada 7, begitu 9 adalah hak 7, jadi kami baik. Ini bukan kes untuk pokok binari, untuk pokok binari tetap kita hanya boleh mempunyai 3 di atas, 7 ke kiri, 9 ke kiri 7; tiada pesanan nilai jua. Sekarang, kita akan sebenarnya tidak melakukan ini kerana ia adalah membosankan dan tidak perlu, tetapi "cuba untuk menarik seberapa ramai diperintahkan pokok seperti yang anda boleh berfikir menggunakan 7 nombor, 3, 9, dan 6. Berapa banyak perkiraan yang berbeza berada di sana? Apakah ketinggian setiap satu? " Kami akan melakukan beberapa, tetapi idea utama adalah, ini adalah dengan cara tiada perwakilan unik pokok binari yang mengandungi nilai-nilai ini. Apa yang kami perlukan adalah beberapa pokok binari yang mengandungi 7, 3, 6, dan 9. Satu lagi salah yang sah yang mungkin akan menjadi akar ialah 3, pergi ke kiri dan ia 6, pergi ke kiri dan ia adalah 7, pergi ke kiri dan ia adalah 9. Itulah pokok carian binari yang sah. Ia tidak sangat membantu, kerana ia adalah sama seperti senarai berkaitan dan semua ini petunjuk hanya batal. Tetapi ia adalah pokok yang sah. Yeah? [Pelajar] Jangan nilai perlu menjadi lebih besar di sebelah kanan? Atau adakah ini? >> Ini Saya bermaksud untuk pergi dengan cara yang lain. Terdapat juga - yeah, mari kita beralih bahawa. 9, 7, 6, 3. Tangkapan yang baik. Ia masih mempunyai untuk mentaati apa carian binari pokok yang sepatutnya dilakukan. Jadi segala-galanya ke kiri mempunyai menjadi kurang daripada nod yang diberikan. Kita hanya boleh bergerak, berkata, ini 6 dan meletakkan ia di sini. Tidak, kita tidak boleh. Kenapa saya terus berbuat demikian? Mari kita lakukan - di sini adalah 6, di sini ialah 7, 6 mata kepada 3. Ini adalah masih pokok carian binari yang sah. Apakah salah jika saya - mari kita lihat jika saya boleh tampil dengan perkiraan. Ya, okay. Jadi apa yang salah dengan pokok ini? Saya rasa saya telah diberi petunjuk bahawa ada sesuatu yang salah dengan itu. Kenapa saya terus berbuat demikian? Okay. Ini kelihatan munasabah. Jika kita melihat pada setiap nod, seperti 7, kemudian ke kiri 7 adalah 3. Jadi kita mempunyai 3, perkara ke kanan sebanyak 3 ialah 6. Dan jika anda melihat pada 6, perkara yang hak daripada 6 9. Jadi mengapa ini bukan pokok carian binari yang sah? [Pelajar] 9 adalah masih kiri 7. >> Yeah. Ia mesti benar bahawa semua nilai yang anda mungkin boleh mencapai dengan pergi ke kiri 7 adalah kurang daripada 7. Jika kita pergi kiri 7, kita dapat 3 dan kita masih boleh mendapatkan hingga 6, kita masih boleh mendapatkan hingga 9, tetapi dengan mempunyai pergi kurang daripada 7, kita tidak harus mampu untuk mendapatkan nombor yang lebih besar daripada 7. Jadi ini tidak adalah pokok carian binari yang sah. Abang saya sebenarnya mempunyai soalan temuduga yang pada asasnya ini, hanya kod sehingga sesuatu untuk mengesahkan sama ada pokok adalah pokok carian binari, dan sebagainya perkara pertama yang beliau lakukan adalah hanya menyemak untuk melihat jika kiri dan kanan adalah betul, dan kemudian melelar bawah sana. Tetapi anda tidak boleh hanya berbuat demikian, anda perlu menjejaki hakikat bahawa sekarang saya telah pergi kiri 7, segala-galanya di pohon mestilah kurang daripada 7. Algoritma yang betul perlu untuk menjejaki batas bahawa nilai mungkin boleh jatuh masuk Kami tidak akan pergi melalui mereka semua. Terdapat hubungan berulangnya bagus, walaupun kita tidak mendapat kepada mereka, atau kita tidak akan sampai kepada mereka, menentukan berapa ramai sebenarnya. Jadi, terdapat 14 daripada mereka. Idea bagaimana anda akan melakukan matematik adalah seperti, anda boleh memilih mana-mana satu untuk menjadi nod akar, dan kemudian jika saya memilih 7 menjadi nod akar, maka terdapat, katakan, beberapa nombor yang boleh pergi menjadi nod kiri saya, dan terdapat beberapa nombor yang boleh menjadi nod kanan saya, tetapi jika saya telah n jumlah nombor, maka jumlah yang boleh pergi ke kiri ditambah dengan jumlah yang boleh pergi ke kanan n - 1. Jadi nombor yang tinggal, mereka perlu mampu untuk pergi sama ada ke kiri atau kanan. Ia seolah-olah sukar bahawa, jika saya meletakkan 3 pertama maka segala-galanya telah pergi ke kiri, tetapi jika saya meletakkan 7, maka beberapa perkara yang boleh pergi kiri dan beberapa perkara yang boleh pergi ke kanan. Dan oleh '3 'pertama saya bermakna segala-galanya boleh pergi ke kanan. Ia benar-benar, anda hanya perlu untuk berfikir tentang hal seperti, berapa banyak perkara yang boleh pergi pada tahap seterusnya pokok itu. Dan ia datang untuk menjadi 14; atau anda boleh menarik mereka semua, dan kemudian anda akan mendapat 14. Akan kembali di sini, "Tertib pokok binari adalah sejuk kerana kita boleh mencari melalui mereka dalam cara yang sangat serupa untuk mencari lebih pelbagai disusun. Untuk berbuat demikian, kita bermula di akar dan bekerja cara kami ke bawah pokok ke arah daun, memeriksa nilai setiap nod terhadap nilai-nilai kita sedang mencari. Jika nilai nod semasa adalah kurang daripada nilai kita sedang mencari, anda pergi bersebelahan untuk kanak-kanak kanan nod. Jika tidak, anda pergi kepada anak kiri nod. Pada satu ketika, anda akan mencari nilai yang anda sedang mencari, atau anda akan menghadapi satu null, menunjukkan nilai bukan di pokok itu. " Saya mempunyai untuk melukis pokok yang kita lalui sebelum ini, yang akan mengambil kedua. Tetapi kita mahu melihat sama ada 6, 10, dan 1 di pokok itu. Jadi apa yang ia adalah, 7, 9, 3, 6. Okay. Nombor yang anda mahu melihat, kita mahu mencari 6. Bagaimanakah ini berfungsi algoritma? Nah, kita juga mempunyai beberapa penunjuk akar ke pokok kita. Dan kita akan pergi ke akar dan berkata, adalah nilai ini bersamaan dengan nilai kita sedang mencari? Jadi kita sedang mencari bagi 6, jadi ia tidak sama. Jadi kita terus pergi, dan kini kita katakan, okay, jadi 6 adalah kurang daripada 7. Adakah ini bermakna kita mahu pergi ke kiri, atau adakah kita mahu pergi ke kanan? [Pelajar] Kiri. >> Yeah. Ia adalah jauh lebih mudah, semua yang anda perlu lakukan adalah menarik salah satu nod mungkin pokok itu dan kemudian anda Don 't - dan bukannya cuba untuk berfikir dalam kepala anda, okay, jika ia kurang, saya pergi ke kiri atau pergi kanan, hanya melihat gambar ini, ia adalah sangat jelas bahawa saya perlu pergi ke kiri jika nod ini adalah lebih besar daripada nilai yang saya cari. Jadi anda pergi ke kiri, sekarang saya pada 3. Saya mahu - 3 adalah kurang daripada nilai Saya mencari yang adalah 6. Jadi kita pergi ke kanan, dan sekarang saya berakhir pada 6, yang merupakan nilai Saya cari, jadi saya kembali benar. Nilai seterusnya saya akan mencari adalah 10. Okay. Jadi 10, kini, akan - memotong bahawa - akan mengikuti akar. Sekarang, 10 akan menjadi lebih daripada 7, jadi saya mahu melihat ke kanan. Saya akan datang ke sini, 10 akan menjadi lebih besar daripada 9, jadi saya akan mahu melihat ke kanan. Saya datang ke sini, tetapi di sini sekarang saya di batal. Apa yang perlu saya lakukan jika saya memukul batal? [Pelajar] Return palsu? >> Yeah. Saya tidak menjumpai 10. 1 adalah akan menjadi satu kes yang hampir sama, kecuali ia hanya akan dijentik; bukan mencari ke sebelah kanan, saya akan melihat ke bawah sebelah kiri. Sekarang saya fikir kita sebenarnya mendapatkan kod. Berikut adalah di mana - membuka perkakas CS50 dan mengemudi jalan anda di sana, tetapi anda boleh juga hanya melakukannya dalam ruang. Ia mungkin sesuai untuk melakukannya di dalam ruang, kerana kita boleh bekerja di dalam ruang. "Mula-mula kita akan memerlukan jenis definisi baru bagi nod pokok binari yang mengandungi nilai int. Menggunakan boilerplate typedef di bawah, mencipta definisi jenis baru bagi nod dalam pokok binari. Jika anda tersekat. . . "Blah, blah, blah. Okay. Jadi mari kita meletakkan boilerplate di sini, struct nod typedef, dan nod. Ya, okay. Jadi apakah bidang kita akan mahu dalam nod kami? [Pelajar] Int dan kemudian dua petunjuk? >> Nilai Int, dua petunjuk? Bagaimana saya menulis petunjuk? [Pelajar] struct. >> Saya perlu mengezum masuk Yeah, jadi nod struct * meninggalkan, dan struct nod * betul. Dan ingat perbincangan dari masa lalu, bahawa ini tidak masuk akal, ini tidak masuk akal, ini tidak masuk akal. Anda perlu segala-galanya ada dalam usaha untuk menentukan struct rekursi. Okay, supaya apa yang pokok kami akan kelihatan seperti. Jika kita lakukan pokok trinary, maka nod mungkin kelihatan seperti b1, b2, struct nod * b3, mana b adalah cawangan - sebenarnya, saya lebih mendengar ia kiri, tengah, kanan, tetapi apa sahaja. Kami hanya mengambil berat tentang binari, jadi kanan, kiri. "Sekarang mengisytiharkan * nod pembolehubah global untuk akar pokok itu." Jadi kita tidak akan berbuat demikian. Dalam usaha untuk membuat perkara yang lebih sukar dan lebih umum, kita tidak akan mempunyai pembolehubah nod global. Sebaliknya, dalam utama yang kita akan mengisytiharkan semua perkara nod kami, dan itu bererti bahawa di bawah, apabila kita mula menjalankan fungsi Mengandungi dan fungsi kami memasukkan kami, bukannya Mengandungi kita berfungsi hanya menggunakan pembolehubah nod global, kita akan mempunyai ia mengambil sebagai hujah pokok yang kita mahu ia untuk memproses. Mempunyai pembolehubah global sepatutnya untuk membuat perkara yang mudah. Kami pergi untuk membuat perkara yang sukar. Sekarang mengambil minit atau lebih untuk hanya melakukan perkara seperti ini, di mana di dalam utama anda mahu untuk mewujudkan pokok ini, dan itulah semua yang anda mahu lakukan. Cuba dan membina pokok ini dalam fungsi utama anda. Okay. Jadi anda tidak perlu telah dibina pokok keseluruhan cara lagi. Tetapi sesiapa yang mempunyai sesuatu yang saya boleh tarik sehingga untuk menunjukkan bagaimana seseorang mungkin mula membina pokok tersebut? [Pelajar] terhantuk Seseorang, cuba untuk keluar. [Bowden] Sesiapa selesa dengan pembinaan pokok mereka? [Pelajar] Pasti. Ia tidak dilakukan. >> Ia adalah denda. Kita hanya boleh selesai - oh, anda boleh menyimpan? Hore. Jadi di sini kita mempunyai - oh, saya sedikit memotong. Saya dizum dalam? Mengezum masuk, tatal keluar. >> Saya mempunyai satu soalan. >> Yeah? [Pelajar] Apabila anda menentukan struct, adalah perkara-perkara seperti dimulakan untuk apa-apa? [Bowden] No >> Okay. Jadi, anda akan perlu untuk memulakan - [Bowden] No Apabila anda menentukan, atau apabila anda mengisytiharkan struct, ia tidak dimulakan secara lalai, ia hanya suka jika anda mengaku int. Ia adalah perkara yang sama. Ia seperti setiap bidang individu boleh mempunyai nilai sampah di dalamnya. >> Dan ia mungkin untuk menentukan atau untuk mengisytiharkan struct dalam cara yang ia tidak memulakan mereka? [Bowden] Ya. Jadi, jalan pintas pengawalan sintaks akan kelihatan seperti - Ada dua cara yang boleh kita lakukan ini. Saya fikir kita perlu menyusun untuk membuat dilafaz pasti juga tidak ini. Perintah hujah yang datang dalam struct, anda meletakkan sebagai perintah hujah di dalam ini pendakap kerinting. Jadi jika anda mahu untuk memulakan hingga 9 dan meninggalkan batal dan kemudian kanan menjadi batal, ia akan menjadi 9, null, null. Alternatif, dan editor tidak suka sintaks ini, dan ia difikirkan Saya mahu sebuah blok baru, tetapi alternatif adalah sesuatu seperti - di sini, saya akan meletakkan ia pada baris baru. Anda dengan jelas boleh mengatakan, saya lupa sintaks yang tepat. Jadi jelas anda boleh menangani mereka dengan nama, dan berkata, Nilai c, atau. = 9, kiri = NULL. Saya meneka ini keperluan untuk menjadi koma. Kanan = NULL, jadi cara ini anda tidak sebenarnya perlu tahu perintah struct itu, dan apabila anda membaca ini, ia adalah lebih jelas tentang apa nilai yang dimulakan. Ini berlaku untuk menjadi salah satu perkara yang - begitu, bagi sebahagian besar, C + + adalah superset C. Anda boleh mengambil kod C, bergerak ia lebih kepada C + +, dan ia perlu menyusun. Ini adalah salah satu daripada perkara-perkara yang C + + tidak menyokong, jadi orang cenderung untuk tidak melakukannya. Saya tidak tahu jika itulah sebab hanya orang cenderung untuk tidak melakukannya, tetapi kes di mana saya perlu menggunakannya diperlukan untuk bekerja dengan C + + dan jadi saya tidak boleh menggunakan ini. Satu lagi contoh sesuatu yang tidak berfungsi dengan C + + adalah bagaimana malloc mengembalikan "* tidak sah," teknikal, tetapi anda hanya boleh mengatakan char * x = malloc apa sahaja, dan ia secara automatik akan dibuang * char. Itu cast automatik tidak berlaku dalam C + +. Itu tidak akan menyusun, dan jelas anda akan perlu untuk mengatakan * char, malloc, apa sahaja, untuk membuang * char. Tidak ada banyak perkara bahawa C dan C + + tidak bersetuju, tetapi mereka adalah dua. Jadi kita akan pergi dengan sintaks ini. Tetapi walaupun kita tidak pergi dengan sintaks itu, apa - mungkin salah dengan ini? [Pelajar] Saya tidak perlu dereference ia? >> Yeah. Ingatlah bahawa anak panah mempunyai dereference tersirat, dan sebagainya apabila kita hanya berurusan dengan struct, kita mahu menggunakan. untuk mendapatkan di dalam bidang struct itu. Dan masa sahaja kita menggunakan anak panah adalah apabila kita mahu lakukan - baik, arrow adalah bersamaan dengan - itulah apa yang ia akan bermakna jika saya menggunakan anak panah. Semua cara arrow, dereference ini, kini saya di struct, dan saya boleh mendapatkan bidang. Sama ada mendapatkan bidang secara langsung atau dereference dan mendapatkan bidang - Saya rasa ini harus nilai. Tetapi di sini saya berurusan dengan hanya struct, bukan penunjuk kepada struct satu, dan jadi saya tidak boleh menggunakan anak panah. Tetapi ini jenis perkara yang boleh kita lakukan untuk semua nod. Oh Tuhan saya. Ini adalah 6, 7, dan 3. Kemudian kita boleh menubuhkan cawangan di pokok kita, kita boleh mempunyai 7 - kita boleh, kiri harus menunjukkan kepada 3. Jadi bagaimana kita berbuat demikian? [Pelajar, difahami] >> Yeah. Alamat node3, dan jika anda tidak mempunyai alamat, maka ia hanya tidak akan mengumpulkannya. Tetapi ingat bahawa ini adalah petunjuk untuk nod seterusnya. Hak hendaklah menuding ke 9, dan 3 perlu menunjukkan di sebelah kanan hingga 6. Saya rasa ini adalah menetapkan semua. Sebarang komen atau soalan? [Pelajar, difahami] Akar akan menjadi 7. Kita hanya boleh mengatakan nod * ptr = atau akar, = & node7. Untuk tujuan kita, kita akan berurusan dengan memasukkan, jadi kita akan mahu untuk menulis fungsi untuk memasukkan ke dalam pokok ini binari dan masukkan tidak dapat dielakkan akan memanggil malloc untuk mewujudkan nod baru untuk pokok ini. Jadi perkara-perkara yang akan mendapat berantakan dengan hakikat bahawa sesetengah nod kini pada timbunan dan nodus lain akan berakhir pada timbunan apabila kita memasukkan mereka. Ini adalah betul-betul sah, tetapi sebab sahaja kami dapat melakukan ini pada timbunan adalah kerana ia adalah seperti contoh yang tersusun yang kita tahu pokok itu sepatutnya dibina sebagai 7, 3, 6, 9. Jika kita tidak mempunyai ini, maka kita tidak akan mempunyai malloc di tempat pertama. Seperti yang kita akan melihat sedikit kemudian, kita harus malloc'ing. Sekarang ia adalah sempurna yang munasabah untuk meletakkan pada timbunan, tetapi mari kita menukar ini kepada pelaksanaan malloc. Jadi setiap kini akan menjadi sesuatu seperti nod * node9 = malloc (sizeof (nod)). Dan kini kami akan perlu untuk melakukan pemeriksaan kami. jika (node9 == NULL) - Saya tidak mahu bahawa - return 1, dan kemudian kita boleh lakukan node9-> kerana sekarang ia adalah penunjuk, value = 6, node9-> kiri = NULL, node9-> right = NULL, dan kita akan perlu untuk berbuat demikian bagi setiap nod-nod. Jadi sebaliknya, mari kita meletakkan ia di dalam fungsi berasingan. Mari kita memanggilnya nod * build_node, dan ini adalah agak serupa dengan API kami sediakan untuk pengekodan Huffman. Kami memberi anda fungsi pengasal untuk pokok deconstructor "fungsi" bagi mereka pokok-pokok dan sama untuk hutan. Jadi di sini kita akan mempunyai fungsi pengasal hanya membina nod untuk kita. Dan ia akan kelihatan cukup banyak sama seperti ini. Dan saya juga akan menjadi malas dan tidak menukar nama pembolehubah, walaupun node9 tidak masuk akal lagi. Oh, saya rasa nilai node9 tidak perlu telah 6. Sekarang kita boleh kembali node9. Dan di sini kita harus kembali null. Semua orang bersetuju mengenai fungsi yang membina nod? Jadi sekarang kita hanya boleh memanggil bahawa untuk membina mana-mana nod dengan nilai yang diberikan dan penunjuk nol. Sekarang kita boleh memanggil bahawa, kita boleh melakukan nod * node9 = build_node (9). Dan mari kita buat. . . 6, 3, 7, 6, 3, 7. Dan sekarang kita mahu menubuhkan petunjuk yang sama, kecuali kini segala-galanya sudah di segi petunjuk jadi tidak perlu lagi alamat. Okay. Jadi apa perkara terakhir yang ingin saya lakukan? Terdapat ralat semakan bahawa saya tidak melakukan. Apakah membina kembali nod? [Pelajar, difahami] >> Yeah. Jika malloc gagal, ia akan kembali batal. Jadi, saya akan malas meletakkan ia ke bawah di sini bukannya melakukan suatu keadaan bagi setiap. Jika (node9 == NULL, atau - walaupun mudah, ini adalah bersamaan dengan hanya jika tidak node9. Jadi jika tidak node9, atau tidak node6, atau tidak node3, atau tidak node7, kembali 1. Mungkin kita harus mencetak malloc gagal, atau sesuatu. [Pelajar] Apakah palsu sama untuk menyeimbangkan serta? [Bowden] Mana-mana nilai sifar adalah palsu. Jadi nol ialah nilai sifar. Sifar adalah nilai sifar. Palsu adalah nilai sifar. Mana-mana - cukup banyak hanya 2 nilai sifar adalah batal dan sifar, palsu adalah hanya hash ditakrifkan sebagai sifar. Itu juga terpakai jika kita mengisytiharkan pembolehubah global. Jika kita tidak mempunyai nod akar * di sini, kemudian - Perkara yang baik tentang pembolehubah global adalah bahawa mereka sentiasa mempunyai nilai awal. Itu tidak benar fungsi, bagaimana di dalam sini, jika kita mempunyai, seperti, * nod atau x nod. Kami tidak mempunyai idea apa x.value, x.whatever, atau kita boleh mencetak mereka dan mereka boleh sewenang-wenangnya. Itu tidak benar pembolehubah global. Akar Jadi nod atau x nod. Secara lalai, segala-galanya yang global, jika tidak jelas dimulakan kepada nilai tertentu, mempunyai nilai sifar sebagai nilai. Jadi di sini, nod akar *, kita tidak jelas memulakan untuk apa-apa, jadi nilai lalai akan batal, yang merupakan nilai sifar petunjuk. Nilai lalai x akan bermakna bahawa x.value adalah sifar, x.left adalah batal, dan x.right adalah batal. Jadi kerana ia adalah struct, semua bidang struct yang akan menjadi nilai-nilai sifar. Kita tidak perlu untuk menggunakan bahawa sini, walaupun. [Pelajar] structs adalah berbeza daripada pembolehubah lain, dan pembolehubah lain nilai sampah; ini adalah sifar? [Bowden] nilai lain juga. Jadi, dalam x, x akan sifar. Jika ia adalah pada skop global, ia mempunyai nilai awal. >> Okay. [Bowden] Sama ada nilai awal anda memberikannya atau sifar. Saya fikir yang menjaga semua ini. Okay. Jadi bahagian seterusnya soalan bertanya, "Sekarang kita mahu menulis fungsi yang dipanggil mengandungi dengan prototaip bool mengandungi nilai int. " Kami tidak akan melakukan bool mengandungi nilai int. Prototaip kami akan kelihatan seperti bool mengandungi (nilai int. Dan kemudian kami juga akan lulus ia pokok bahawa ia harus memeriksa untuk melihat jika ia mempunyai nilai yang. Jadi nod * pokok). Okay. Dan kemudian kita boleh memanggil ia dengan sesuatu seperti, mungkin kita akan mahu printf atau sesuatu. Mengandungi 6, akar kita. Itu harus kembali satu, atau benar, sedangkan mengandungi 5 akar harus kembali palsu. Jadi mengambil kedua untuk melaksanakan ini. Anda boleh melakukannya sama ada iterative atau rekursif. Perkara yang baik tentang cara kita telah menetapkan perkara ini adalah bahawa ia meminjamkan dirinya kepada penyelesaian rekursi kami lebih mudah daripada cara pembolehubah global. Kerana jika kita hanya mempunyai mengandungi nilai int, maka kita mempunyai ada cara recursing turun subtrees. Kami akan perlu untuk mempunyai fungsi pembantu berasingan yang recurses menurunkan subtrees untuk kita. Tetapi oleh kerana kita telah mengubah ia untuk mengambil pokok itu sebagai hujah, yang ia sepatutnya sentiasa berada di tempat pertama, sekarang kita boleh recurse lebih mudah. Jadi lelaran atau rekursi, kita akan pergi ke atas kedua-duanya, tetapi kita akan melihat bahawa hujung rekursi sehingga menjadi agak mudah. Okay. Adakah sesiapa yang mempunyai sesuatu yang kita boleh bekerja dengan? [Pelajar] Saya telah mendapat lelaran penyelesaian. >> Baiklah, lelaran. Okay, ini kelihatan baik. Jadi, mahu untuk berjalan kita melaluinya? [Pelajar] Pasti. Jadi saya menetapkan pembolehubah menggoda untuk mendapatkan nod pertama pokok itu. Dan kemudian saya hanya bergelung melalui manakala menggoda tidak batal sama, jadi sementara masih di pokok itu, saya rasa. Dan jika nilai yang bersamaan dengan nilai yang menggoda menunjuk ke, maka ia mengembalikan nilai yang. Jika tidak, ia memeriksa jika ia adalah di sebelah kanan atau sebelah kiri. Jika anda pernah mendapatkan keadaan di mana terdapat ada pokok yang lebih, maka ia kembali - ia keluar gelung dan pulangan palsu. [Bowden] Okay. Jadi yang seolah-olah baik. Sesiapa yang mempunyai sebarang komen atas apa-apa? Saya tidak mempunyai komen ketepatan pada semua. Satu perkara yang boleh kita lakukan adalah lelaki ini. Oh, ia akan pergi memanjang sedikit. Saya akan menetapkan bahawa. Okay. Setiap orang harus ingat bagaimana pertigaan berfungsi. Terdapat memang kuiz pada masa lalu yang memberi anda berfungsi dengan operator pertigaan, dan berkata, menterjemah ini, melakukan sesuatu yang tidak menggunakan pertigaan. Jadi ini adalah satu kes yang sangat biasa apabila saya akan berfikir untuk menggunakan pertigaan, di mana jika keadaan beberapa menetapkan pembolehubah kepada sesuatu, lain menetapkan bahawa pemboleh ubah yang sama kepada sesuatu yang lain. Itu adalah sesuatu yang sangat kerap boleh berubah menjadi jenis ini perkara mana menetapkan pembolehubah yang ini - atau, dengan baik, adakah ini benar? Kemudian ini, lain ini. [Pelajar] Yang pertama adalah jika benar, betul-betul? [Bowden] Yeah. Cara saya selalu membacanya, temp sama dengan nilai yang lebih besar daripada nilai sementara, maka ini, lain ini. Ia bertanya soalan. Adakah ia lebih besar? Kemudian lakukan perkara pertama. Lain melakukan perkara kedua. Saya hampir selalu - kolon, saya hanya - dalam kepala saya, saya membaca lain. Adakah sesiapa yang mempunyai penyelesaian rekursi? Okay. Yang satu ini kita akan - ia sudah boleh menjadi besar, tetapi kita akan membuat ia lebih baik. Ini adalah cukup banyak idea yang tepat sama. Ia hanya, baik, adakah anda mahu jelaskan? [Pelajar] Pasti. Jadi kita memastikan bahawa pokok itu tidak menyeimbangkan 1, kerana jika pokok itu adalah batal, maka ia akan kembali palsu kerana kita tidak mendapati ia. Dan jika masih ada pokok, kita pergi ke - kita mula-mula memeriksa jika nilai nod semasa. Return benar jika ia, dan jika kita tidak recurse di sebelah kiri atau kanan. Adakah bunyi yang sesuai? >> Mm-hmm. (Perjanjian) Jadi melihat bahawa ini adalah hampir - strukturnya sangat serupa kepada penyelesaian lelaran. Ia hanya bahawa bukannya recursing, kita mempunyai gelung sementara. Dan kes asas di sini mana pokok tidak batal sama adalah keadaan di mana kita tercetus gelung sementara. Mereka sangat serupa. Tetapi kita akan mengambil langkah ini satu lagi. Sekarang, kita melakukan perkara yang sama di sini. Notis kita kembali perkara yang sama dalam kedua-dua ayat-ayat ini, kecuali satu hujah adalah berbeza. Jadi kita pergi untuk membuat yang ke pertigaan. Saya melanda sesuatu pilihan, dan ia dibuat simbol. Okay. Jadi kita pergi untuk kembali itu mengandungi. Ini semakin menjadi baris, baik, dizum dalam ia. Biasanya, sebagai perkara yang gaya, saya tidak fikir ramai orang meletakkan ruang selepas anak panah, tetapi saya rasa jika anda konsisten, ia adalah denda. Jika nilai adalah kurang daripada nilai pokok, kita mahu recurse di sebelah kiri pokok, lagi yang kita mahu recurse di sebelah kanan pokok. Jadi yang merupakan satu langkah membuat melihat ini lebih kecil. Langkah dua membuat melihat ini lebih kecil - kita boleh memisahkan baris. Okay. Langkah kedua menjadikan ia kelihatan lebih kecil di sini, jadi nilai pulangan bersamaan nilai pokok, atau mengandungi apa jua. Ini adalah satu perkara yang penting. Saya tidak pasti jika dia berkata ia dengan jelas di dalam kelas, tetapi ia dipanggil litar pintas penilaian. Idea di sini adalah nilai == nilai pokok. Jika itu adalah benar, maka ini adalah benar, dan kita mahu 'atau' dengan apa yang ada di sini. Jadi tanpa berfikir tentang apa yang ada di sini, apakah ungkapan keseluruhan akan kembali? [Pelajar] Benar? >> Ya, kerana benar apa-apa, or'd - or'd atau benar dengan apa-apa adalah semestinya benar. Jadi seberapa segera seperti yang kita lihat return value = nilai pokok, kita hanya akan kembali benar. Tidak juga akan recurse lagi mengandungi ke bawah baris. Kita boleh mengambil langkah ini satu lagi. Pulangan pokok tidak batal sama dan semua ini. Ia dibuat fungsi garis satu. Ini adalah juga satu contoh penilaian litar pintas. Tetapi sekarang ia adalah idea yang sama - bukan - jadi jika pokok tidak batal sama - atau, baik, jika pokok tidak batal sama, yang merupakan kes yang buruk, jika pokok sama batal, maka syarat pertama akan menjadi palsu. Jadi palsu yang ANDkan dengan apa-apa akan menjadi apa? [Pelajar] Palsu. >> Yeah. Ini adalah separuh lagi penilaian litar pintas, di mana jika pokok tidak batal tidak sama, maka kita tidak akan pergi - atau jika pokok tidak batal sama, maka kita tidak akan untuk melakukan nilai nilai == pokok. Kami hanya akan dengan serta-merta mengembalikan palsu. Yang penting, kerana jika ia tidak melakukan litar pintas menilai, kemudian jika pokok tidak batal sama, keadaan ini kedua akan kesalahan seg, kerana pokok-> nilai dereferencing null. Jadi itulah. Boleh membuat ini - beralih sekali lebih. Ini adalah satu perkara yang sangat biasa juga, tidak membuat ini selaras dengan ini, tetapi ia adalah perkara biasa dalam keadaan, mungkin tidak betul di sini, tetapi jika (pokok! = NULL, dan pokok-> nilai == nilai), melakukan apa sahaja. Ini adalah satu keadaan yang sangat biasa, di mana sebaliknya mempunyai untuk memecahkan ini kepada dua IFS, di mana suka, adalah batal pokok? Okay, ia tidak batal, jadi sekarang adalah nilai pokok yang bersamaan dengan nilai? Melakukan ini. Sebaliknya, keadaan ini, ini tidak akan seg bersalah kerana ia akan keluar jika ini berlaku kepada menjadi batal. Well, saya rasa jika pokok anda adalah penunjuk yang benar-benar tidak sah, ia masih boleh seg bersalah, tetapi ia tidak boleh seg kesalahan jika pokok adalah batal. Jika ia tidak batal, ia akan memecahkan sebelum anda pernah dereferenced penunjuk di tempat pertama. [Pelajar] Adakah ini dipanggil penilaian malas? [Bowden] penilaian Malas adalah satu perkara yang berasingan. Penilaian Malas adalah lebih seperti anda meminta untuk nilai, anda bertanya untuk mengira nilai, jenis, tetapi anda tidak perlu ia segera. Jadi sehingga anda benar-benar perlu, ia tidak dinilai. Ini bukan perkara yang sama, tetapi dalam pset Huffman, ia mengatakan bahawa kita "malas" menulis. Sebab kita berbuat demikian adalah kerana kita sebenarnya buffering menulis - kita tidak mahu untuk menulis bit individu pada satu-satu masa, atau bait individu pada satu-satu masa, kita bukannya mahu untuk mendapatkan sebahagian bait. Kemudian, apabila kita mempunyai sebahagian bait, maka kita akan menulis ia keluar. Walaupun anda meminta untuk menulis - dan fwrite dan fread melakukan perkara yang sama perkara. Mereka penampan membaca dan menulis. Walaupun anda meminta untuk menulis dengan segera, ia mungkin tidak akan. Dan anda tidak boleh yakin bahawa perkara-perkara yang akan ditulis sehingga anda memanggil hfclose atau apa sahaja ia adalah, yang kemudian berkata, okay, saya menutup fail saya, yang bermakna saya lebih baik akan menulis segala-galanya yang saya telah tidak ditulis lagi. Ia tidak perlu untuk menulis segala-galanya keluar sehingga anda menutup fail, dan kemudian ia perlu. Jadi itulah hanya apa yang malas - ia menunggu sehingga ia telah berlaku. Ini - mengambil 51 dan anda akan pergi ke dalam lebih terperinci, kerana OCaml dan segala-galanya di 51, segala-galanya adalah rekursi. Tiada lelaran penyelesaian, pada asasnya. Semuanya adalah rekursi, dan penilaian malas akan menjadi penting untuk banyak keadaan di mana, jika anda tidak malas menilai, yang bermakna - Contoh sungai, yang panjang tak terhingga. Secara teori, anda boleh berfikir nombor tabii sebagai aliran 1-2-3-4-5-6-7, Jadi malas dinilai perkara yang halus. Jika saya katakan saya mahu bilangan yang kesepuluh, maka saya boleh menilai sehingga bilangan kesepuluh. Jika saya mahu bilangan seratus, maka saya boleh menilai sehingga bilangan seratus. Tanpa penilaian malas, maka ia akan cuba untuk menilai semua nombor serta-merta. Anda menilai nombor tak terhingga banyaknya, dan bahawa hanya tidak mungkin. Jadi terdapat banyak keadaan di mana penilaian malas hanya penting untuk mendapatkan perkara untuk bekerja. Sekarang kita mahu menulis memasukkan mana insert akan menjadi sama berubah dalam takrif. Jadi sekarang ia memasukkan bool (nilai int). Kami pergi untuk menukar bahawa untuk memasukkan bool (int nilai nod * pokok). Kami sebenarnya pergi untuk menukar bahawa sekali lagi dalam sedikit, kita akan melihat mengapa. Dan mari kita bergerak build_node, hanya untuk palang pintu itu, atas memasukkan jadi kita tidak perlu menulis prototaip fungsi. Yang merupakan petunjuk bahawa anda akan perlu menggunakan build_node pada sisip. Okay. Ambil satu minit untuk itu. Saya rasa saya disimpan semakan jika anda mahu tarik dari itu, atau sekurang-kurangnya, saya lakukan sekarang. Saya mahu berehat sedikit untuk berfikir tentang logik memasukkan, jika anda tidak boleh berfikir ia. Pada asasnya, anda hanya akan pernah memasukkan di daun. Seperti, jika saya memasukkan 1, maka saya pasti akan boleh memasukkan 1 - Saya akan bertukar kepada hitam - I'll akan memasukkan 1 di sini. Atau jika saya memasukkan 4, saya mahu memasukkan 4 di sini. Jadi tidak kira apa yang anda lakukan, anda akan perlu memasukkan di daun. Semua yang anda perlu lakukan adalah melelar ke bawah pokok itu sehingga anda sampai ke nod yang perlu nod ibu bapa, ibu bapa nod baru, dan kemudian menukar penunjuk kiri atau kanan, bergantung kepada sama ada ia adalah lebih besar daripada atau kurang daripada nod semasa. Tukar penunjuk yang menuding kepada nod baru anda. Jadi melelar bawah pokok, membuat titik daun ke nod baru. Juga berfikir tentang mengapa yang melarang jenis situasi sebelum, di mana saya membina pokok perduaan di mana ia adalah betul jika anda hanya memandang pada nod tunggal, tetapi 9 adalah untuk sebelah kiri 7 jika anda terlelar turun sepanjang jalan. Jadi itulah mustahil dalam senario ini, kerana - berfikir tentang memasukkan 9 atau sesuatu; pada nod yang pertama, Saya akan melihat 7 dan saya hanya akan pergi ke kanan. Jadi tidak kira apa yang saya lakukan, jika saya memasukkan dengan pergi ke daun, dan daun menggunakan algoritma yang sesuai, ia akan menjadi mustahil bagi saya untuk memasukkan 9 ke kiri 7 kerana secepat saya mencecah 7 saya akan pergi ke kanan. Adakah sesiapa yang mempunyai sesuatu untuk memulakan dengan? [Pelajar] saya lakukan. >> Pasti. [Pelajar, difahami] [Pelajar lain, difahami] [Bowden] Ia dihargai. Okay. Ingin menjelaskan? [Pelajar] Sejak kita tahu bahawa kita telah memasukkan nod baru pada akhir pokok itu, Saya bergelung melalui pokok iterative sehingga saya mendapat kepada nod yang menunjukkan untuk menyeimbangkan. Dan kemudian saya memutuskan untuk meletakkan ia sama ada di sebelah kanan atau sebelah kiri menggunakan pembolehubah yang betul, ia memberitahu saya di mana untuk meletakkan ia. Dan kemudian, pada dasarnya, saya hanya dibuat yang lepas - bahawa titik sementara nod ke nod baru bahawa ia telah mewujudkan, sama ada di sebelah kiri atau di sebelah kanan, bergantung pada apa nilai hak. Akhirnya, saya menetapkan nilai nod baru kepada nilai ujian. [Bowden] Okay, jadi saya melihat satu isu di sini. Ini adalah seperti 95% jalan sana. Satu isu yang saya lihat, baik, tidak sesiapa melihat isu? Apakah keadaan di mana mereka keluar daripada gelung? [Pelajar] Jika menggoda adalah batal? >> Yeah. Jadi bagaimana anda keluar gelung jika menggoda adalah batal. Tetapi apa yang saya lakukan di sini? Saya dereference menggoda, yang tidak dapat dielakkan batal. Jadi perkara lain yang anda perlu lakukan bukan sahaja menjejaki sehingga menggoda adalah batal, anda mahu untuk menjejaki ibu bapa pada setiap masa. Kami juga mahu nod ibu bapa *, saya rasa kita boleh memastikan bahawa pada null pada mulanya. Ini akan mempunyai tingkah laku yang pelik untuk akar pokok itu, tetapi kita akan mendapat itu. Jika nilai adalah lebih besar daripada apa sahaja, maka temp = menggoda betul. Tetapi sebelum kita berbuat demikian, ibu bapa temp =. Atau adakah ibu bapa yang sentiasa akan menggoda sama? Adakah bahawa kes? Jika menggoda tidak batal, maka saya akan bergerak ke bawah, tidak kira apa, kepada nod yang menggoda adalah ibu bapa. Jadi ibu bapa yang akan menjadi temp, dan kemudian saya bergerak temp turun. Sekarang menggoda adalah batal, tetapi mata ibu bapa kepada ibu bapa perkara yang batal. Jadi turun di sini, saya tidak mahu untuk menetapkan hak sama dengan 1. Jadi saya berpindah ke kanan, jadi jika kanan = 1, dan saya rasa anda juga mahu lakukan - jika anda bergerak ke kiri, anda mahu untuk menetapkan hak sama rata kepada 0. Atau yang lain jika anda pernah bergerak ke kanan. Jadi kanan = 0. Jika kanan = 1, sekarang kita mahu untuk membuat ibu bapa newnode penunjuk yang betul, lain, kita mahu untuk membuat newnode ibu bapa penunjuk kiri. Soalan pada itu? Okay. Jadi ini adalah cara kita - baik, sebenarnya, bukannya melakukan perkara ini, kita 1/2 dijangka anda untuk menggunakan build_node. Dan kemudian jika newnode sama batal, kembalikan palsu. Itulah yang Sekarang, ini adalah apa yang kita harapkan anda lakukan. Ini adalah apa penyelesaian kakitangan lakukan. Saya tidak bersetuju dengan ini sebagai cara yang "betul" pergi mengenainya tetapi ini adalah betul-betul halus dan ia akan berfungsi. Satu perkara yang hak pelik sedikit sekarang ialah jika pokok itu bermula sebagai batal, kita lulus dalam pokok nol. Saya rasa ia bergantung kepada bagaimana anda menentukan tingkah laku lulus dalam pokok nol. Saya akan berfikir bahawa jika anda lulus dalam pokok nol, kemudian memasukkan nilai ke dalam pokok nol hanya perlu kembali pokok di mana nilai hanya adalah bahawa nod tunggal. Adakah orang bersetuju dengan itu? Anda boleh, jika anda mahu, jika anda lulus dalam pokok nol dan anda ingin memasukkan nilai ke dalamnya, kembali palsu. Ia terpulang kepada anda untuk menentukan bahawa. Untuk melakukan perkara pertama yang saya kata dan kemudian - baik, anda akan mempunyai masalah berbuat demikian, kerana ia akan menjadi lebih mudah jika kita mempunyai penunjuk global kepada benda itu, tetapi kita tidak, jadi jika pokok adalah batal, ada apa-apa yang boleh kita lakukan tentang itu. Kami hanya boleh kembali palsu. Jadi saya akan menukar insert. Kita teknikal hanya boleh menukar hak ini di sini, bagaimana ia iterating atas perkara, tetapi saya akan untuk menukar insert untuk mengambil nod ** pokok. Petunjuk Double. Apa maknanya? Daripada berurusan dengan penunjuk ke nodus, perkara yang saya akan memanipulasi penunjuk ini. Saya akan memanipulasi penunjuk ini. Saya akan memanipulasi petunjuk langsung. Ini masuk akal kerana, berfikir tentang turun - baik, sekarang ini mata untuk menyeimbangkan. Apa yang saya mahu lakukan adalah memanipulasi penunjuk ini menunjukkan tidak menyeimbangkan. Saya mahu ia menunjukkan nod baru saya. Jika saya hanya menjejaki petunjuk petunjuk saya, maka saya tidak perlu untuk menjejaki penunjuk ibu bapa. Saya hanya boleh menjejaki untuk melihat jika penunjuk menunjuk untuk menyeimbangkan, dan jika penunjuk menunjuk untuk menyeimbangkan, mengubahnya menuding kepada nod yang saya mahu. Dan saya boleh menukar ia kerana saya mempunyai penunjuk kepada penunjuk. Mari kita lihat ini sekarang. Anda sebenarnya boleh melakukannya rekursif cukup mudah. Adakah kita mahu berbuat demikian? Ya, kita lakukan. Mari kita lihat ia rekursif. Pertama, apa kes asas kami akan menjadi? Hampir selalu kes asas kami, tetapi sebenarnya, ini adalah jenis yang sukar. Perkara pertama yang pertama, jika (pokok == NULL) Saya rasa kita hanya akan kembali palsu. Ini adalah berbeza daripada null pokok anda. Ini adalah penunjuk penunjuk akar anda menjadi batal yang bermakna bahawa penunjuk akar anda tidak wujud. Jadi turun di sini, jika saya lakukan nod * - mari kita hanya menggunakan semula ini. Nod * akar = NULL, dan kemudian saya akan memanggil memasukkan dengan melakukan sesuatu seperti, memasukkan 4 ke akar &. Jadi & akar, jika akar * nod kemudian & akar akan menjadi ** nod. Ini adalah sah. Dalam kes ini, pokok, di sini, pokok tidak adalah batal atau memasukkan. Di sini. Pokok adalah tidak batal, pokok * adalah batal, yang baik kerana jika pokok * adalah batal, maka saya boleh memanipulasi ia kini menunjukkan apa yang saya mahu ia menunjukkan. Tetapi jika pokok adalah batal, yang bermakna saya hanya datang ke sini dan kata batal. Yang tidak masuk akal. Saya tidak boleh berbuat apa-apa dengan itu. Jika pokok adalah batal, kembali palsu. Jadi Saya pada dasarnya sudah berkata apa kes asas sebenar kami. Dan apa yang akan menjadi? [Pelajar, difahami] [Bowden] Ya. Jadi, jika (* pokok == NULL). Ini berkaitan dengan kes itu di sini di mana jika penunjuk merah saya adalah penunjuk Saya memberi tumpuan kepada, jadi seperti saya memberi tumpuan kepada penunjuk ini, kini saya memberi tumpuan kepada penunjuk ini. Sekarang saya memberi tumpuan kepada penunjuk ini. Jadi jika penunjuk merah saya, yang ** nod saya, pernah - jika *, penunjuk merah saya, pernah batal, yang bermakna bahawa saya di kes di mana saya memberi tumpuan kepada penunjuk bahawa mata - ini adalah penunjuk yang dimiliki daun. Saya ingin menukar penunjuk ini untuk menunjukkan kepada nod baru saya. Kembali di sini. Newnode saya hanya akan menjadi nod * n = build_node (nilai) maka n, jika n = NULL, kembali palsu. Yang lain kita mahu mengubah apa penunjuk sedang menunjuk ke kini menunjukkan kepada nod yang baru dibina kami. Kita sebenarnya boleh berbuat demikian di sini. Daripada mengatakan n, kita katakan * pokok = jika pokok *. Semua orang memahami bahawa? Bahawa dengan berurusan dengan petunjuk untuk petunjuk, kita boleh mengubah penunjuk nol untuk menunjukkan kepada perkara-perkara yang kita mahu mereka menunjukkan. Itulah kes asas kami. Sekarang kami berulang, atau rekursi kami, akan menjadi sangat serupa kepada semua recursions lain yang kami telah lakukan. Kami akan mahu untuk memasukkan nilai, dan kini saya akan menggunakan pertigaan lagi, tetapi apa yang keadaan kita akan menjadi? Apa yang kita sedang mencari untuk membuat keputusan sama ada kita mahu pergi kiri atau kanan? Mari kita melakukannya dalam langkah-langkah yang berasingan. Jika (nilai <) apa? [Pelajar] nilai Pokok? [Bowden] Jadi ingat bahawa saya kini - [Pelajar, difahami] [Bowden] Yeah, jadi di sini, katakan bahawa ini anak panah hijau adalah satu contoh apa pokok kini ialah, adalah penunjuk kepada penunjuk ini. Jadi itu bermakna saya penunjuk kepada penunjuk kepada 3. Dereference dua kali kedengaran seperti bagus. Apa yang saya - bagaimana saya berbuat demikian? [Pelajar] Dereference sekali, dan kemudian melakukan arrow bahawa cara? [Bowden] Jadi (pokok *) adalah dereference sekali, -> nilai akan memberi saya nilai nod yang saya tidak langsung menunjuk ke. Jadi saya juga boleh menulis ia ** tree.value jika anda lebih suka bahawa. Sama ada berfungsi. Jika itu berlaku, maka saya mahu untuk memanggil memasukkan dengan nilai. Dan apa yang nod saya dikemaskini ** akan menjadi? Saya mahu pergi ke kiri, jadi tree.left ** akan menjadi kiri saya. Dan saya mahu penunjuk kepada perkara yang supaya jika kiri berakhir sehingga menjadi penunjuk nol, Saya boleh mengubah suai ia untuk menunjukkan kepada nod baru saya. Dan kes lain boleh menjadi sangat serupa. Mari kita sebenarnya membuat bahawa pertigaan saya sekarang. Memasukkan nilai jika nilai <(** pokok). Nilai. Kemudian kita mahu untuk mengemaskini ** kami ke kiri, lain kita mahu untuk mengemaskini ** kami ke kanan. [Pelajar] Adakah yang mendapat penunjuk penunjuk? [Bowden] Ingatlah bahawa - ** tree.right adalah bintang nod. [Pelajar, difahami] >> Yeah. ** Tree.right adalah seperti penunjuk ini atau sesuatu. Jadi dengan mengambil penunjuk itu, yang memberikan saya apa yang saya mahu penunjuk kepada lelaki itu. [Pelajar] Bolehkah kita pergi lebih lagi mengapa kita menggunakan dua petunjuk? [Bowden] Yeah. Jadi - tidak, anda boleh, dan penyelesaian yang sebelum adalah satu cara melakukannya tanpa melakukan dua petunjuk. Anda perlu dapat untuk memahami menggunakan dua petunjuk, dan ini adalah satu penyelesaian yang lebih bersih. Juga, notis bahawa, apa yang berlaku jika pokok saya - apa yang berlaku jika akar saya batal? Apa yang akan berlaku jika saya melakukan kes ini di sini? Jadi nod * akar = NULL, masukkan 4 ke akar &. Apa yang akar akan menjadi selepas ini? [Pelajar, difahami] >> Yeah. Akar nilai akan menjadi 4. Akar kiri akan menjadi batal, hak akar akan menjadi batal. Dalam kes di mana kita tidak lulus akar by Alamat, kita tidak boleh mengubah suai akar. Dalam kes di mana pokok - mana akar adalah batal, kita hanya terpaksa pulang palsu. Ada apa-apa yang kita boleh lakukan. Kita tidak boleh memasukkan nod ke pokok kosong. Tetapi sekarang kita boleh, kita hanya membuat pokok kosong ke pokok satu nod. Yang biasanya cara jangkaan bahawa ia sepatutnya untuk bekerja. Tambahan pula, ini adalah jauh lebih pendek berbanding juga mengesan ibu bapa, dan sebagainya anda melelar turun sepanjang jalan. Sekarang saya mempunyai ibu bapa saya, dan saya hanya mempunyai penunjuk hak ibu bapa saya untuk apa jua. Sebaliknya, jika kita lakukan ini iterative, ia akan menjadi idea yang sama dengan gelung sementara. Tetapi sebaliknya perlu berurusan dengan penunjuk ibu bapa saya, bukannya penunjuk semasa saya akan menjadi perkara yang bahawa saya terus mengubah suai untuk menunjukkan kepada nod baru saya. Saya tidak mempunyai untuk berurusan dengan sama ada ia menunjuk ke kiri. Saya tidak mempunyai untuk berurusan dengan sama ada ia menghala ke kanan. Ia hanya apa penunjuk ini, saya akan menetapkan ia untuk menunjukkan kepada nod baru saya. Semua orang memahami bagaimana ia berfungsi? Jika tidak mengapa kita mahu melakukannya dengan cara ini, tetapi sekurang-kurangnya bahawa kerja-kerja ini sebagai penyelesaian? [Pelajar] Di manakah kita kembali benar? [Bowden] Itu mungkin betul di sini. Jika kita memasukkan, kembalikan benar. Lain, turun di sini kita akan mahu kembali pulangan memasukkan apa sahaja. Dan apa yang istimewa tentang fungsi ini rekursi? Ia rekursi ekor, jadi selagi kita menyusun dengan pengoptimuman beberapa, ia akan menyedari bahawa dan anda tidak akan mendapatkan limpahan timbunan daripada ini, walaupun pokok kita mempunyai ketinggian 10,000 atau 10 juta. [Pelajar, difahami] [Bowden] Saya fikir ia tidak di Dash - atau apa yang pengoptimuman tahap diperlukan untuk rekursi ekor untuk diiktiraf. Saya fikir ia mengiktiraf - GCC dan dilafaz juga mempunyai makna yang berbeza bagi tahap pengoptimuman mereka. Saya mahu mengatakan ia DashO 2, untuk memastikan bahawa ia akan mengiktiraf rekursi ekor. Tetapi kita - anda boleh membina seperti contoh Fibonocci atau sesuatu. Ia tidak mudah untuk menguji dengan ini, kerana ia sukar untuk membina pokok binari yang begitu besar. Tetapi yeah, saya fikir ia adalah DashO 2, jika anda menyusun dengan DashO 2, ia akan mencari rekursi ekor dan mengoptimumkan yang keluar. Mari kita kembali kepada - memasukkan literal perkara terakhir yang diperlukan. Mari kita kembali kepada sisip di sini di mana kita pergi untuk melakukan idea yang sama. Ia masih akan mempunyai kecacatan tidak dapat untuk sepenuhnya mengendalikan apabila akar itu sendiri adalah batal, atau kemasukan lalu adalah batal, tetapi sebaliknya berurusan dengan penunjuk ibu bapa, mari kita menggunakan logik yang sama mengekalkan petunjuk kepada petunjuk. Jika di sini kita menyimpan nod kami ** kini, dan kita tidak perlu untuk menjejaki kanan lagi, tetapi nod ** kini = & pokok. Dan kini gelung sementara kita akan menjadi sementara kini * tidak batal sama. Tidak perlu menjejaki ibu bapa lagi. Tidak perlu untuk menjejaki kiri dan kanan. Dan saya akan memanggilnya sementara, kerana kita sudah menggunakan menggoda. Okay. Jadi, jika (nilai> * temp), kemudian & (* temp) -> right lain temp = & (* temp) -> kiri. Dan sekarang, pada ketika ini, selepas gelung selama ini, Saya hanya melakukan ini kerana mungkin ia adalah lebih mudah untuk berfikir tentang iterative daripada rekursif, tetapi selepas gelung selama ini, * Menggoda adalah penunjuk kita ingin menukar. Sebelum kita mempunyai ibu bapa, dan kita mahu untuk menukar sama ada kiri ibu bapa atau ibu bapa hak, tetapi jika kita mahu menukar hak ibu bapa, maka menggoda * adalah hak ibu bapa, dan kita boleh menukar ia secara langsung. Jadi turun di sini, kita boleh melakukan * temp = newnode, dan itulah ia. Jadi notis, semua yang kita lakukan dalam hal ini adalah mengambil baris kod. Dalam usaha untuk menjejaki induk dalam semua yang adalah usaha tambahan. Di sini, jika kita hanya menyimpan mengesan penunjuk penunjuk, dan walaupun kita mahu untuk mendapatkan menghapuskan semua ini pendakap kerinting kini, membuat ia kelihatan lebih pendek. Ini kini adalah penyelesaian yang sama yang tepat, tetapi kurang baris kod. Sebaik sahaja anda mula mengiktiraf ini sebagai penyelesaian yang sah, ia juga mudah sebab tentang daripada seperti, okay, mengapa saya mempunyai bendera ini di sebelah kanan int? Apa maksudnya? Oh, ia menandakan bahawa setiap kali saya pergi betul, saya perlu untuk menetapkan ia, lain jika saya pergi meninggalkan saya perlu untuk menetapkan ia kepada sifar. Di sini, saya tidak mempunyai sebab tentang itu, ia hanya lebih mudah untuk berfikir tentang. Soalan? [Pelajar, difahami] >> Yeah. Okay, jadi dalam bit terakhir - Saya rasa satu fungsi yang cepat dan mudah yang boleh kita lakukan adalah, let's - bersama-sama, saya rasa, cuba dan menulis mengandungi fungsi yang tidak peduli sama ada ia adalah pokok gelintaran perduaan. Ini mengandungi fungsi perlu kembali benar jika mana-mana sahaja di pokok binari umum ini adalah nilai yang kita cari. Jadi mari kita melakukannya rekursif dan kemudian kami akan melakukannya iterative. Kita boleh sebenarnya hanya melakukannya bersama-sama, kerana ini akan menjadi benar-benar pendek. Apa kes asas saya akan? [Pelajar, difahami] [Bowden] Jadi jika (pokok == NULL), maka apa? [Pelajar] Return palsu. [Bowden] yang lain, baik, saya tidak perlu yang lain. Jika kes asas saya yang lain. [Pelajar] Pokok nilai? >> Yeah. Jadi, jika (pokok-> nilai == nilai. Perhatikan kami kembali ke nod *, tidak nod ** s? Contains tidak akan perlu untuk menggunakan ** nod, kerana kita tidak mengubah petunjuk. Kami hanya menyeberangi mereka. Jika itu berlaku, maka kita mahu kembali benar. Yang lain kita mahu untuk melintasi kanak-kanak. Jadi kita tidak boleh sebab tentang sama ada segala-galanya ke kiri adalah kurang dan segala-galanya ke kanan adalah lebih besar. Jadi apa yang keadaan kita akan berada di sini - atau, apa yang kita akan lakukan? [Pelajar, difahami] >> Yeah. Nyata ini mengandungi (nilai, pokok> kiri) atau mengandungi (nilai, pokok-> right). Dan itu sahaja. Dan notis terdapat beberapa penilaian litar pintas, di mana jika kita berlaku untuk mencari nilai dalam pokok kiri, kita tidak perlu melihat pokok yang betul. Itulah fungsi keseluruhan. Sekarang mari kita melakukannya iterative, yang akan menjadi kurang baik. Kami akan mengambil permulaan yang biasa kini nod * = pokok. Walaupun (kini! = NULL). Cepat akan melihat masalah. Jika kini - di sini, jika kita pernah keluar daripada ini, maka kita telah kehabisan perkara untuk melihat, jadi kembali palsu. Jika (kini> nilai == nilai), kembali benar. Jadi sekarang, kita berada di tempat - kita tidak tahu sama ada kita mahu pergi kiri atau kanan. Jadi sewenang-wenangnya, mari kita hanya pergi ke kiri. Saya telah jelas menghadapi isu di mana saya telah benar-benar ditinggalkan segala-galanya - Saya akan hanya pernah memeriksa sebelah kiri pokok. Saya tidak akan memeriksa apa-apa yang kanak-kanak yang betul apa-apa. Bagaimana saya menetapkan ini? [Pelajar] Anda perlu menjejaki kiri dan kanan dalam timbunan. [Bowden] Yeah. Jadi mari kita membuat ia struct senarai, nod * n, dan kemudian nod ** seterusnya? Saya fikir yang berfungsi dengan baik. Kami mahu pergi ke kiri, atau let's - di sini. Struct = senarai senarai, ia akan mula daripada senarai struct ini. * Senarai = NULL. Jadi yang akan menjadi senarai berpaut kami subtrees bahawa kita telah melangkau lebih. Kami akan merentasi dibiarkan sekarang, tetapi kerana kita tidak dapat tidak perlu untuk kembali ke kanan, Kami akan menyimpan sebelah kanan di dalam senarai struct kami. Kemudian kita akan mempunyai new_list atau struct, struct list *, new_list = malloc (sizeof (senarai)). Saya akan mengabaikan kesilapan-memeriksa bahawa, tetapi anda perlu menyemak untuk melihat batal jika ia. New_list nod ia akan menunjukkan kepada - oh, itulah sebabnya saya mahu ia di sini. Ia akan untuk menunjukkan senarai struct kedua. Itulah betapa dikaitkan kerja senarai. Ini adalah sama seperti senarai int dikaitkan kecuali kita hanya menggantikan int * nod. Ia adalah betul-betul sama. Jadi new_list, nilai nod new_list kami, akan menjadi kini-> right. Nilai kami new_list-> seterusnya akan menjadi senarai asal kita, dan kemudian kita pergi untuk mengemaskini senarai kami untuk menunjukkan new_list. Sekarang kita perlu beberapa jenis cara perkara-perkara yang menarik, seperti yang kita telah dilalui anak pohon keseluruhan kiri. Sekarang kita perlu untuk menarik barangan daripada itu, seperti kini adalah batal, kita tidak mahu hanya kembali palsu. Kami mahu sekarang tarik luar di senarai baru kami. Satu cara yang mudah untuk melakukan ini - baik, sebenarnya, terdapat pelbagai cara untuk berbuat demikian. Sesiapa yang mempunyai cadangan? Jika perlu saya lakukan ini atau bagaimana yang perlu saya lakukan ini? Kita hanya mempunyai beberapa minit, tetapi apa-apa cadangan? Sebaliknya - satu cara, bukan keadaan kita yang sementara, apa yang kita sedang melihat tidak batal, sebaliknya kita akan terus pergi sehingga senarai kami sendiri adalah batal. Jadi, jika senarai kami akhirnya menjadi batal, maka kita telah kehabisan perkara untuk mencari, untuk mencari lebih. Tetapi itu bermakna bahawa perkara pertama dalam senarai kami hanya akan menjadi nod pertama. Perkara yang pertama akan - kita tidak lagi perlu melihat bahawa. Jadi senarai-> n akan menjadi pokok kami. senarai> seterusnya akan menjadi batal. Dan kini manakala senarai tidak batal sama. Cur akan tarik sesuatu dari senarai kami. Jadi kini akan sama senarai> n. Dan kemudian senarai akan sama senarai> n, atau senarai> seterusnya. Jadi, jika nilai kini sama nilai. Sekarang kita boleh menambah kedua-dua penunjuk kanan kita dan penunjuk kiri kita selagi mereka tidak batal. Down di sini, saya rasa kita sepatutnya dilakukan bahawa di tempat pertama. Jika (kini> right! = NULL) maka kita akan memasukkan nod tersebut ke dalam senarai kami. Jika (kini> kiri), ini adalah sedikit kerja tambahan, tetapi ia adalah denda. Jika (kini-> kiri! = NULL), dan kita akan memasukkan kiri ke dalam senarai dikaitkan kami, dan yang harus. Kami melelar - selagi kita mempunyai sesuatu dalam senarai kami, kita mempunyai satu lagi nod untuk melihat. Jadi kita melihat nod tersebut, kita memajukan senarai kami untuk satu depan. Jika nod tersebut adalah nilai yang kita cari, kita boleh kembali benar. Lagi memasukkan kedua-dua subtrees kiri dan kanan kita, selagi mereka tidak batal, ke dalam senarai kami supaya kita tidak dapat dielakkan pergi ke atas mereka. Jadi, jika mereka tidak batal, jika penunjuk akar kita menunjuk kepada dua perkara, maka pada mulanya, kita ditarik sesuatu supaya senarai kami akhirnya menjadi batal. Dan kemudian kita meletakkan dua perkara kembali, jadi kini senarai kami adalah saiz 2. Kemudian kita pergi ke gelung kembali dan kami hanya akan tarik, katakan, penunjuk kiri nod akar kita. Dan yang hanya akan menyimpan berlaku, kita akan berakhir sehingga menggelung ke atas segala-galanya. Perhatikan bahawa ini adalah jauh lebih rumit dalam penyelesaian rekursi. Dan saya telah berkata beberapa kali bahawa penyelesaian rekursi biasanya mempunyai banyak persamaan dengan lelaran penyelesaian. Berikut ini adalah apa penyelesaian rekursi melakukan. Satu-satunya perubahan adalah bahawa bukannya tersirat menggunakan timbunan, timbunan program, sebagai cara anda mengesan nodus apa yang anda masih perlu untuk melawat, sekarang anda perlu jelas menggunakan senarai berpaut. Dalam kedua-dua kes anda mengesan apa nod masih perlu dikunjungi. Dalam kes rekursi ia hanya mudah kerana timbunan dilaksanakan untuk anda sebagai timbunan program. Perhatikan bahawa senarai ini yang berkaitan, ia adalah timbunan. Apa sahaja yang kita hanya meletakkan pada timbunan segera apa yang kita akan tarik luar tindanan untuk melawat seterusnya. Kami kehabisan masa, tetapi apa-apa soalan? [Pelajar, difahami] [Bowden] Yeah. Jadi, jika kita mempunyai senarai berpaut kami, semasa akan untuk menunjukkan kepada lelaki ini, dan kini kami hanya memajukan senarai berpaut kami untuk memberi tumpuan kepada lelaki ini. Kami menyeberangi lebih senarai dikaitkan dalam barisan itu. Dan kemudian saya rasa kita harus membebaskan senarai berpaut kami dan barangan sekali sebelum kembali benar atau palsu, kita perlu melelar lebih dikaitkan senarai kami dan sentiasa turun di sini, saya rasa, jika hak kita kini tidak sama dengan, tambah, jadi sekarang kita mahu untuk membebaskan kini kerana, dengan baik, adakah kita benar-benar lupa tentang senarai? Yeah. Jadi itulah apa yang kami mahu lakukan di sini. Mana penunjuk? Cur ketika itu - kita mahu ke senarai struct * 10 bersamaan senarai seterusnya. Senarai percuma, senarai = temp. Dan dalam kes di mana kita kembali benar, kita tidak perlu untuk melelar atas baki senarai berpaut kami membebaskan perkara. Perkara yang baik tentang penyelesaian rekursi membebaskan perkara hanya bermakna pop factorings off tindanan yang akan berlaku untuk anda. Jadi kami telah pergi dari sesuatu yang seperti 3 baris kod keras untuk berfikir tentang kepada sesuatu yang jauh lebih banyak sukar untuk berfikir tentang baris kod. Apa-apa lagi soalan? Semua hak. Kami baik. Bye! [CS50.TV]