[Powered by Google Translate] [Bagian 6: Kurang Nyaman] [Nate Hardison] [Harvard University] [Ini adalah CS50.] [CS50.TV] Baiklah. Selamat datang ke bagian 6. Minggu ini, kita akan berbicara tentang struktur data dalam bagian, terutama karena masalah minggu ini ditetapkan pada spellr melakukan sejumlah eksplorasi struktur data yang berbeda. Ada banyak cara yang berbeda Anda dapat pergi dengan sejumlah masalah, dan struktur data yang Anda tahu tentang, hal-hal yang lebih keren yang dapat Anda lakukan. Jadi mari kita mulai. Pertama kita akan berbicara tentang tumpukan, tumpukan dan antrian struktur data yang akan kita bicarakan. Tumpukan dan antrian benar-benar membantu ketika kita mulai berbicara tentang grafik, yang kita tidak akan melakukan begitu banyak sekarang. Tapi mereka benar-benar baik untuk memahami salah satu struktur data yang besar fundamental CS. Deskripsi dalam spesifikasi sejumlah masalah, jika Anda menarik itu, berbicara tentang tumpukan sebagai mirip dengan tumpukan nampan makan yang Anda miliki di kantin di ruang makan di mana ketika staf makan datang dan menempatkan nampan makan keluar setelah mereka telah dibersihkan mereka, mereka stack mereka satu di atas yang lain. Dan kemudian ketika anak-anak datang untuk mendapatkan makanan, mereka menarik nampan off, pertama atas satu, kemudian yang di bawahnya, maka yang di bawah itu. Jadi, pada dasarnya, baki pertama bahwa staf makan meletakkan adalah yang terakhir yang akan diambil off. Yang terakhir bahwa staf makan memakai adalah yang pertama yang akan diambil off untuk makan malam. Dalam spec sejumlah masalah, yang Anda dapat men-download jika Anda belum melakukannya, kita berbicara tentang pemodelan stucture tumpukan data yang menggunakan jenis struct. Jadi apa yang kita punya di sini, ini mirip dengan apa yang disajikan dalam kuliah, kecuali dalam kuliah kita disajikan ini dengan ints sebagai lawan s * char. Ini akan menjadi tumpukan yang menyimpan apa? Daniel? Apa yang kita menyimpan dalam tumpukan ini? [Daniel] Strings? >> Kami menyimpan string dalam tumpukan ini, tepatnya. Semua yang perlu Anda miliki untuk membuat stack adalah array dari kapasitas tertentu, yang dalam hal ini, kapasitas akan berada di semua topi karena konstan. Dan maka selain array, semua yang kita butuhkan untuk melacak adalah ukuran saat array. Satu hal yang perlu dicatat di sini bahwa agak dingin adalah bahwa kita sedang menciptakan struktur data yang ditumpuk di atas lain struktur data, array. Ada berbagai cara untuk mengimplementasikan tumpukan. Kami tidak akan melakukannya belum cukup, tapi mudah-mudahan setelah melakukan linked-list masalah, Anda akan melihat bagaimana Anda dapat dengan mudah menerapkan tumpukan di atas linked list juga. Tetapi untuk sekarang, kita akan tetap ke array. Jadi sekali lagi, semua yang kita butuhkan adalah array dan kita hanya perlu untuk melacak ukuran array. [Sam] Maaf, mengapa Anda mengatakan stack adalah di atas senar? Bagi saya rasanya seperti senar berada dalam stack. [Hardison] Ya. Kami sedang menciptakan, kami mengambil array kita struktur data - itu pertanyaan yang bagus. Jadi pertanyaannya adalah mengapa, bagi orang-orang yang menonton secara online ini, mengapa kita mengatakan bahwa tumpukan di atas senar, karena di sini sepertinya senar berada di dalam stack? Yang benar-benar terjadi. Apa yang saya maksudkan adalah bahwa kita punya sebuah struktur data array. Kami punya sebuah array char * s, ini array dari string, dan kami akan menambahkan bahwa dalam rangka menciptakan struktur data yang ditumpuk. Jadi tumpukan adalah sedikit lebih kompleks daripada array. Kita bisa menggunakan array untuk membangun stack. Jadi, di sanalah kita mengatakan bahwa tumpukan dibangun di atas sebuah array. Demikian juga, seperti saya katakan sebelumnya, kita dapat membangun sebuah tumpukan di atas linked list. Alih-alih menggunakan array untuk memegang elemen kami, kita bisa menggunakan linked list untuk menahan unsur kami dan membangun tumpukan sekitar itu. Mari kita berjalan melalui beberapa contoh, melihat beberapa kode, untuk melihat apa yang sebenarnya terjadi di sini. Di sebelah kiri, saya telah dilemparkan ke bawah apa yang struct tumpukan akan terlihat seperti dalam memori jika kapasitas yang # didefinisikan sebagai empat. Kami punya empat elemen array char * kami. Kami punya string [0], string [1], string [2], string [3], dan kemudian bahwa ruang terakhir untuk bilangan bulat ukuran kami. Apakah ini masuk akal? Oke. Inilah yang terjadi jika apa yang saya lakukan di sebelah kanan, yang akan menjadi kode saya, adalah hanya menyatakan struct, struct ditumpuk disebut s. Ini adalah apa yang kita dapatkan. Hal ini meletakkan jejak di memori. Pertanyaan pertama di sini adalah apa isi dari struct stack? Sekarang mereka bukan apa-apa, tapi mereka tidak benar-benar apa-apa. Mereka ini jenis sampah. Kami tidak tahu apa yang ada di dalamnya. Ketika kita mendeklarasikan s tumpukan, kami hanya melempar yang turun di atas memori. Ini semacam seperti mendeklarasikan int i dan tidak menginisialisasi itu. Anda tidak tahu apa yang ada di sana. Anda dapat membaca apa yang ada di sana, tapi mungkin tidak super bermanfaat. Satu hal yang Anda ingin selalu ingat untuk lakukan adalah menginisialisasi apa saja yang perlu diinisialisasi. Dalam kasus ini, kita akan menginisialisasi ukuran menjadi nol, karena itu akan berubah menjadi sangat penting bagi kami. Kita bisa pergi ke depan dan menginisialisasi semua pointer, semua s * char, menjadi beberapa nilai dimengerti, mungkin nol. Tapi itu tidak benar-benar penting bahwa kita melakukan itu. Sekarang, dua operasi utama pada tumpukan adalah? Siapa saja ingat dari kuliah apa yang Anda lakukan dengan tumpukan? Ya? [Stella] Mendorong dan muncul? >> Tepat. Mendorong dan muncul adalah dua operasi utama pada tumpukan. Dan apa yang mendorong lakukan? >> Ini menempatkan sesuatu ke atas dari tumpukan, dan kemudian popping membawanya pergi. [Hardison] Tepat. Jadi mendorong mendorong sesuatu di atas tumpukan. Ini seperti makan staf meletakkan nampan makan di atas meja. Dan muncul adalah mengambil nampan makan dari tumpukan. Mari kita berjalan melalui beberapa contoh dari apa yang terjadi ketika kita mendorong hal-hal ke dalam stack. Jika kita mendorong string 'halo' ke stack kami, ini adalah apa diagram kita akan terlihat seperti sekarang. Lihat apa yang terjadi? Kami mendorong ke elemen pertama dari array string kami dan kami menaikkan jumlah ukuran kami untuk menjadi 1. Jadi jika kita melihat perbedaan antara dua slide, di sini adalah 0, inilah sebelum push. Berikut adalah setelah push. Sebelum push, setelah push. Dan sekarang kita memiliki satu elemen dalam tumpukan kita. Ini adalah string "hello", dan hanya itu. Segala sesuatu yang lain dalam array, dalam array string kita, masih sampah. Kami belum diinisialisasi. Katakanlah kita mendorong string lain ke stack kami. Kita akan mendorong "dunia" pada saat ini. Sehingga Anda dapat melihat "dunia" di sini pergi di atas "halo", dan jumlah ukuran naik ke 2. Sekarang kita dapat mendorong "CS50", dan yang akan pergi di atas lagi. Jika kita kembali, Anda dapat melihat bagaimana kita mendorong hal-hal di atas tumpukan. Dan sekarang kita bisa pop. Ketika kita muncul sesuatu dari tumpukan, apa yang terjadi? Siapa saja melihat perbedaannya? Ini cukup halus. [Mahasiswa] Ukuran. >> Ya, ukuran berubah. Apa lagi yang akan Anda diharapkan untuk berubah? [Mahasiswa] The string juga. >> Kanan. String juga. Ternyata bahwa ketika Anda melakukannya dengan cara ini, karena kita tidak menyalin elemen ke dalam stack kami, kita sebenarnya tidak perlu melakukan apa-apa, kita hanya bisa menggunakan ukuran untuk melacak jumlah hal dalam array kita sehingga ketika kita pop lagi, lagi kita hanya akan memundurkan ukuran kami turun ke 1. Tidak perlu untuk benar-benar masuk dan menimpa apapun. Agak funky. Ternyata bahwa kita biasanya hanya meninggalkan hal-hal sendirian karena itu sedikit pekerjaan untuk kita lakukan. Jika kita tidak harus kembali dan menimpa sesuatu, lalu mengapa melakukannya? Jadi ketika kita pop off dua kali dari tumpukan, semua yang dilakukan adalah memundurkan ukuran beberapa kali. Dan lagi, ini hanya karena kita tidak menyalin sesuatu ke dalam stack kami. Ya? Silakan. [Mahasiswa, dipahami] >> Dan kemudian apa yang terjadi ketika Anda mendorong sesuatu lagi? Ketika Anda mendorong sesuatu lagi, mana pergi? Mana pergi, Basil? >> Ke string [1]? >> Kanan. Kenapa tidak bisa masuk ke string [3]? [Basil] Karena lupa bahwa ada sesuatu dalam string [1] dan [2]? [Hardison] Tepat. Tumpukan kami, pada dasarnya, "lupa" bahwa itu berpegangan pada apa dalam string [1] atau string [2], jadi ketika kita menekan "woot", itu hanya menempatkan bahwa ke elemen pada string [1]. Apakah ada pertanyaan tentang bagaimana ini bekerja, pada tingkat dasar? [Sam] Jadi ini tidak dinamis dengan cara apapun, dalam hal jumlah atau dalam hal ukuran stack? [Hardison] Tepat. Ini adalah - intinya adalah bahwa ini bukan tumpukan dinamis growning. Ini adalah tumpukan yang dapat menampung, paling banyak, empat char * s, paling banyak empat hal. Jika kita mencoba dan mendorong hal yang kelima, apa yang Anda pikir seharusnya terjadi? [Mahasiswa, dipahami] [Hardison] Tepat. Ada beberapa hal yang bisa terjadi. Ini mungkin bisa seg kesalahan, tergantung pada apa yang kita - bagaimana tepatnya kita menerapkan back-end. Ini bisa menimpa. Bisa memiliki buffer overflow yang kita bicarakan di kelas. Apa yang akan menjadi hal yang paling jelas yang mungkin ditimpa jika kita mencoba untuk mendorong hal ekstra pada tumpukan kita? Jadi Anda sebutkan buffer overflow. Apa yang mungkin menjadi hal yang akan mendapatkan ditulis di atas atau diinjak-injak jika kita meluap dengan sengaja mencoba untuk mendorong hal ekstra? [Daniel, dipahami] Kemungkinan >>. Tapi awalnya, apa yang mungkin terjadi? Bagaimana jika kita mencoba untuk mendorong hal yang keempat? Ini mungkin menimpa ukuran, setidaknya dengan diagram memori yang kita punya. Dalam spesifikasi sejumlah masalah, yang adalah apa yang kita akan melaksanakan hari, apa yang kita ingin lakukan adalah hanya kembali palsu. Metode mendorong kami akan mengembalikan nilai boolean, dan bahwa nilai boolean akan benar jika push berhasil dan false jika kita tidak dapat menekan apa-apa lagi karena tumpukan penuh. Mari kita berjalan melalui sedikit kode yang sekarang. Berikut fungsi mendorong kami. Mendorong fungsi kita untuk stack akan mengambil dalam string untuk menempatkan di stack. Ini akan mengembalikan true jika string berhasil mendorong pada sebaliknya tumpukan dan palsu. Ada saran tentang apa yang mungkin menjadi hal pertama yang baik untuk dilakukan di sini? [Sam] Jika ukuran sama dengan kapasitas kemudian kembali palsu? [Hardison] Bingo. Nice job. Jika ukurannya kapasitas, kita akan kembali palsu. Kita tidak bisa meletakkan sesuatu yang lebih dalam tumpukan kita. Jika tidak, kita ingin menempatkan sesuatu di atas tumpukan. Apa itu "bagian atas tumpukan," awalnya? [Daniel] Ukuran 0? Ukuran >> 0. Apa atas tumpukan setelah ada satu hal dalam tumpukan? Missy, kau tahu? [Missy] Satu. Ukuran >> adalah satu, tepatnya. Kau terus menambah ukuran, dan setiap kali Anda meletakkan dalam elemen baru pada ukuran indeks dalam array. Kita bisa melakukannya dengan semacam satu-liner, jika itu masuk akal. Jadi kita punya berbagai string kita, kita akan mengaksesnya di indeks ukuran, dan kami hanya akan menyimpan char * kami di sana. Perhatikan bagaimana ada yang tidak menyalin string yang terjadi di sini, tidak ada alokasi memori dinamis? Dan kemudian Missy dibesarkan apa yang sekarang kita lakukan, karena kita telah disimpan string di tempat yang tepat dalam array, dan dia berkata bahwa kita harus kenaikan ukuran per satu sehingga kita siap untuk mendorong berikutnya. Jadi kita bisa melakukan itu dengan s.size + +. Pada titik ini, kami telah didorong ke array kita. Apa hal terakhir yang harus kita lakukan? [Mahasiswa] Kembali benar. >> Kembali benar. Jadi cukup sederhana, kode cukup sederhana. Tidak terlalu banyak. Setelah Anda membungkus kepala Anda sekitar bagaimana stack bekerja, ini cukup sederhana untuk diterapkan. Sekarang, bagian selanjutnya dari ini bermunculan string off dari stack. Aku akan memberi kalian waktu untuk bekerja pada ini sedikit. Ini hampir dasarnya kebalikan dari apa yang kami lakukan di sini di push. Apa yang saya lakukan adalah benar - oops. Saya telah boot up sebuah alat di sini, dan di alat, Saya sudah berhenti masalah set 5 spesifikasi. Jika kita tampilannya di sini, kita bisa melihat aku di cdn.cs50.net/2012/fall/psets/pset5.pdf. Apakah kalian download kode ini yang terletak di sini, section6.zip? Baiklah. Jika Anda belum melakukannya, lakukan itu sekarang, benar-benar cepat. Saya akan melakukannya di jendela terminal saya. Saya benar-benar melakukannya di sini. Ya. Ya, Sam? >> Saya punya pertanyaan tentang mengapa Anda mengatakan kurung s.string 's ukuran = str? Apa str? Apakah itu didefinisikan suatu tempat sebelumnya, atau - oh, di str * char? [Hardison] Ya, tepatnya. Itu adalah argumen. >> Oh, oke. Maaf. [Hardison] Kami menetapkan string untuk mendorong masuk Pertanyaan lain yang mungkin akan muncul bahwa kita tidak benar-benar bicarakan di sini adalah kami mengambil begitu saja bahwa kita memiliki variabel ini disebut s yang berada di lingkup dan dapat diakses kepada kami. Kami mengambil begitu saja bahwa s adalah ini struct stack. Jadi melihat kembali kode push, Anda dapat melihat bahwa kita sedang melakukan hal-hal dengan string yang mendapat disahkan pada tapi kemudian tiba-tiba, kita mengakses s.size, seperti, mana s berasal? Dalam kode yang kita akan melihat dalam arsip bagian dan kemudian hal-hal yang Anda akan lakukan dalam masalah Anda set, kami telah membuat tumpukan kami struct variabel global sehingga kita dapat memiliki akses ke dalam semua fungsi yang berbeda kami tanpa harus secara manual lulus sekitar dan lulus dengan referensi, melakukan semua hal semacam itu. Kami hanya menipu sedikit, jika Anda mau, untuk membuat hal-hal yang lebih baik. Dan itu adalah sesuatu yang kita lakukan di sini karena itu untuk bersenang-senang, itu lebih mudah. Seringkali, Anda akan melihat orang-orang melakukan hal ini jika mereka memiliki satu struktur data besar yang sedang dioperasi dalam program mereka. Mari kita kembali ke alat. Apakah semua orang berhasil mendapatkan section6.zip tersebut? Semua orang unzip menggunakan section6.zip unzip? Jika Anda pergi ke direktori 6 bagian - aah, seluruh tempat - dan Anda daftar apa yang ada di sini, Anda melihat bahwa Anda punya tiga file yang berbeda c.. Anda punya antrian, SLL suatu, yang sendiri-linked list, dan stack. Jika Anda membuka stack.c, Anda dapat melihat bahwa kita punya struct ini ditetapkan untuk kita, struct yang tepat bahwa kita hanya berbicara tentang dalam slide. Kami punya variabel global kami untuk stack, kita punya fungsi mendorong kami, dan kemudian kita punya fungsi pop kita. Aku akan menaruh kode untuk mendorong kembali pada slide di sini, tapi apa yang saya ingin kalian lakukan adalah, untuk yang terbaik dari kemampuan Anda, pergi dan melaksanakan fungsi pop. Setelah Anda telah menerapkan hal itu, Anda dapat mengkompilasi ini dengan membuat tumpukan, dan kemudian menjalankan executable tumpukan resultan, dan yang akan menjalankan semua ini kode uji di sini yang ada di utama. Dan utamanya mengurus benar-benar membuat push dan pop panggilan dan memastikan bahwa semuanya berjalan baik-baik saja melalui. Hal ini juga menginisialisasi ukuran stack di sini sehingga Anda tidak perlu khawatir tentang menginisialisasi itu. Anda dapat berasumsi bahwa itu diinisialisasi dengan benar oleh waktu yang Anda mengaksesnya dalam fungsi pop. Apakah itu masuk akal? Jadi di sini kita pergi. Ada kode push. Aku akan memberikan kalian 5 atau 10 menit. Dan jika Anda memiliki pertanyaan untuk sementara saat Anda sedang coding, silakan bertanya dengan keras. Jadi jika Anda mendapatkan ke titik mencuat, hanya bertanya. Biar saya tahu, biarkan orang lain tahu. Bekerja dengan tetangga Anda juga. [Daniel] Kami hanya menerapkan pop sekarang? Hanya >> pop. Meskipun Anda dapat menyalin pelaksanaan mendorong jika Anda ingin sehingga pengujian akan bekerja. Karena sulit untuk menguji hal-hal yang masuk ke - atau, sulit untuk menguji hal-hal yang muncul keluar dari tumpukan jika tidak ada sesuatu dalam tumpukan untuk mulai dengan. Apa pop seharusnya kembali? Unsur dari atas tumpukan. Ini seharusnya untuk mendapatkan elemen off dari atas tumpukan dan kemudian lakukan dengan decrement ukuran stack, dan sekarang Anda telah kehilangan unsur di atas. Dan kemudian Anda kembali elemen di atas. [Mahasiswa, dipahami] [Hardison] Jadi apa yang terjadi jika Anda melakukan itu? [Mahasiswa, dipahami] Apa yang akhirnya terjadi adalah Anda mungkin mengakses baik elemen yang belum diinisialisasi belum, sehingga Anda perhitungan di mana elemen terakhir adalah mati. Jadi di sini, jika Anda perhatikan, dalam mendorong, kita mengakses string pada elemen s.size karena indeks baru. Ini puncak baru dari stack. Sedangkan pada pop, s.size akan menjadi ruang berikutnya, ruang yang di atas semua elemen dalam tumpukan Anda. Jadi elemen paling atas tidak di s.size, melainkan, itu di bawahnya. Hal lain yang harus dilakukan ketika Anda - di pop, adalah Anda harus untuk penurunan ukuran. Jika Anda ingat kembali ke diagram kecil kami di sini, benar-benar, satu-satunya hal yang kita lihat terjadi ketika kita disebut pop adalah bahwa ukuran ini turun, pertama 2, kemudian ke 1. Kemudian ketika kita mendorong elemen baru, itu akan pergi di tempat yang tepat. [Basil] Jika s.size adalah 2, maka tidak akan pergi ke elemen 2, dan kemudian Anda ingin pop elemen yang off? Jadi jika kita pergi ke - >> Jadi mari kita lihat ini lagi. Jika ini adalah tumpukan kami di titik ini dan kita sebut pop, di mana indeks adalah elemen paling atas? [Basil] Pada 2, tapi itu akan muncul 3. >> Kanan. Jadi itulah di mana ukuran kami adalah 3, tapi kami ingin pop elemen pada indeks 2. Ini semacam khas off dengan salah satu yang Anda miliki dengan pengindeksan nol-array. Jadi Anda ingin pop elemen ketiga, namun unsur ketiga tidak di indeks 3. Dan alasan kita tidak perlu melakukan itu minus 1 ketika kita mendorong adalah karena sekarang, Anda melihat bahwa elemen paling atas, jika kita mendorong sesuatu yang lain ke stack pada saat ini, kita ingin mendorong pada indeks 3. Dan kebetulan bahwa ukuran dan indeks berbaris ketika Anda mendorong. Siapa yang punya implementasi tumpukan bekerja? Anda punya setumpuk bekerja satu. Apakah Anda memiliki pop bekerja belum? [Daniel] Ya. Saya kira begitu. Program >> sedang berjalan dan tidak seg patahan, itu mencetak? Apakah itu mencetak "sukses" ketika Anda menjalankannya? Ya. Membuat stack, menjalankannya, jika mencetak "sukses" dan tidak pergi booming, maka semua bagus. Baiklah. Mari kita pergi ke alat benar-benar cepat, dan kami akan berjalan melalui ini. Jika kita melihat apa yang terjadi di sini dengan pop, Daniel, apa hal pertama yang Anda lakukan? [Daniel] Jika s.size lebih besar dari 0. [Hardison] Oke. Dan mengapa kau lakukan itu? [Daniel] Untuk memastikan bahwa ada sesuatu di dalam tumpukan. [Hardison] Kanan. Anda ingin menguji untuk memastikan bahwa s.size lebih besar dari 0; jika tidak, apa yang Anda inginkan untuk terjadi? [Daniel] Kembali nol? Kembali >> nol, tepatnya. Jadi jika s.size lebih besar dari 0. Lalu apa yang akan kita lakukan? Apa yang kita lakukan jika stack tidak kosong? [Stella] Anda akan memundurkan ukuran? >> Anda akan memundurkan ukuran, oke. Jadi, bagaimana Anda melakukannya? >> S.size--. [Hardison] Besar. Dan kemudian apa yang Anda lakukan? [Stella] Dan kemudian aku berkata kembali s.string [s.size]. [Hardison] Besar. Jika Anda kembali nol. Ya, Sam? [Sam] Mengapa tidak perlu s.size + 1? [Hardison] Plus 1? >> Ya. >> Got it. [Sam] Saya pikir karena Anda mengambil keluar 1, maka Anda akan kembali tidak salah satu yang mereka minta. [Hardison] Dan ini adalah hanya apa yang kita bicarakan dengan seluruh masalah ini dari 0 indeks. Jadi jika kita tampilannya kembali ke sini. Jika kita melihat orang ini di sini, Anda dapat melihat bahwa ketika kita pop, kita bermunculan elemen pada indeks 2. Jadi kita mengurangi ukuran pertama kami, maka ukuran kami sesuai indeks kami. Jika kita tidak akan memundurkan ukuran pertama, maka kita harus melakukan ukuran -1 dan kemudian penurunan. Besar. Semua baik? Setiap pertanyaan tentang ini? Ada sejumlah cara yang berbeda untuk menulis ini juga. Pada kenyataannya, kita bisa melakukan sesuatu yang bahkan - bisa kita lakukan satu-kapal. Kita bisa melakukan kembali satu baris. Jadi kita benar-benar dapat memundurkan sebelum kita kembali dengan melakukan itu. Jadi menempatkan - sebelum s.size tersebut. Yang membuat garis benar-benar padat. Dimana perbedaan antara - ukuran s dan. S.size-- adalah bahwa ini postfix - mereka menyebutnya postfix karena - datang setelah s.size-- berarti bahwa s.size dievaluasi untuk tujuan mencari indeks seperti saat ini ketika baris ini dijalankan, dan kemudian ini - terjadi setelah baris dijalankan. Setelah elemen di s.size indeks diakses. Dan bukan itu yang kita inginkan, karena kita ingin penurunan yang terjadi terlebih dahulu. Othewise, kita akan mengakses array, efektif, di luar batas. Kita akan mengakses elemen di atas salah satu yang kita benar-benar ingin mengakses. Ya, Sam? >> Apakah lebih cepat atau menggunakan RAM kurang untuk membuat dalam satu baris atau tidak? [Hardison] Jujur, itu benar-benar tergantung. [Sam, tidak dapat dipahami] >> Ya, itu tergantung. Anda dapat melakukan trik compiler untuk mendapatkan compiler untuk mengakui bahwa, biasanya, saya bayangkan. Jadi kita telah menyebutkan sedikit tentang hal ini optimasi compiler yang dapat Anda lakukan dalam menyusun, dan itulah jenis hal yang kompilator mungkin bisa mengetahui, seperti oh, hei, mungkin aku bisa melakukan ini semua dalam satu operasi, sebagai lawan memuat variabel ukuran dari RAM, decrementing itu, menyimpannya kembali keluar, dan kemudian memuatnya kembali lagi untuk memproses sisa operasi ini. Tapi biasanya, tidak, ini bukan semacam hal yang akan membuat program anda lebih cepat secara signifikan. Setiap pertanyaan lebih lanjut tentang tumpukan? Jadi mendorong dan muncul. Jika kalian ingin mencoba edisi hacker, apa yang kami lakukan dalam edisi hacker sebenarnya hilang dan membuat tumpukan ini tumbuh secara dinamis. Tantangan ada di sini terutama dalam fungsi push, untuk mencari tahu bagaimana untuk membuat array yang tumbuh Anda terus mendorong elemen lebih dan lebih ke stack. Ini sebenarnya tidak terlalu banyak kode tambahan. Hanya panggilan untuk - Anda harus ingat untuk mendapatkan panggilan ke malloc di sana benar, dan kemudian mencari tahu ketika Anda akan menelepon realloc. Itulah tantangan yang menyenangkan jika Anda tertarik. Tapi untuk saat ini, mari kita lanjutkan, dan mari kita bicara tentang antrian. Gulir lewat sini. Antrian adalah saudara dekat dari stack. Jadi dalam stack, hal-hal yang diletakkan di terakhir adalah hal pertama untuk kemudian diambil. Kami punya terakhir ini, keluar pertama, atau LIFO, memesan. Sedangkan dalam antrian, seperti yang Anda harapkan dari ketika Anda sedang berdiri di garis, orang pertama untuk masuk baris, hal pertama yang harus masuk ke antrian, adalah hal pertama yang akan diambil dari antrian. Antrian juga sering digunakan ketika kita sedang berhadapan dengan grafik, seperti kita berbicara tentang sebentar dengan tumpukan, dan antrian juga berguna untuk berbagai hal lainnya. Satu hal yang muncul sering mencoba untuk mempertahankan, misalnya, daftar diurutkan dari elemen. Dan Anda dapat melakukan ini dengan array. Anda dapat menyimpan daftar diurutkan dari hal-hal dalam array, tapi di mana itu akan sulit maka Anda harus selalu mencari tempat yang tepat untuk memasukkan hal berikutnya. Jadi jika Anda memiliki sebuah array dari angka, 1 sampai 10, dan kemudian Anda ingin memperluas bahwa untuk semua angka 1 sampai 100, dan Anda mendapatkan angka-angka secara acak dan mencoba untuk menjaga semuanya diurutkan saat Anda pergi melalui, Anda akhirnya harus melakukan banyak pergeseran. Dengan beberapa jenis antrian dan beberapa jenis struktur data yang mendasari, Anda benar-benar bisa tetap cukup sederhana. Anda tidak harus menambahkan sesuatu dan kemudian Reshuffle semuanya setiap kali. Anda juga tidak harus melakukan banyak pergeseran dari unsur internal sekitar. Ketika kita melihat antrian, Anda melihat bahwa - juga di queue.c di kode bagian - struct bahwa kami telah memberikan Anda benar-benar mirip dengan struct yang kami berikan untuk Anda stack. Ada satu pengecualian untuk ini, dan bahwa satu pengecualian adalah bahwa kita memiliki bilangan bulat tambahan yang disebut kepala, dan kepala di sini adalah untuk melacak kepala antrian, atau elemen pertama dalam antrian. Dengan tumpukan, kami mampu melacak elemen bahwa kami akan mengambil, atau atas tumpukan, dengan hanya menggunakan ukuran, sedangkan dengan antrian, kita harus berurusan dengan ujung-ujung. Kami sedang berusaha untuk taktik hal-hal di di akhir, tapi kemudian kembali hal-hal dari depan. Jadi secara efektif, dengan kepala, kita memiliki indeks awal antrian, dan ukuran memberi kita indeks akhir antrian sehingga kita bisa mengambil hal-hal dari kepala dan menambahkan hal-hal ke ekor. Sedangkan dengan stack, kami hanya pernah berurusan dengan bagian atas tumpukan. Kami tidak pernah mengakses bawah tumpukan. Kami hanya menambahkan hal-hal ke atas dan mengambil hal off dari atas sehingga kita tidak perlu bahwa bidang ekstra di dalam struct kami. Apakah itu umumnya masuk akal? Baiklah. Ya, Charlotte? [Charlotte, dipahami] [Hardison] Itu pertanyaan yang bagus, dan itu salah satu yang muncul dalam kuliah. Mungkin berjalan melalui beberapa contoh akan menggambarkan mengapa kita tidak ingin menggunakan string [0] sebagai kepala antrian. Jadi bayangkan bahwa kita memiliki antrian kita, kita akan menyebutnya antrian. Pada awalnya, ketika kita baru saja instantiated itu, ketika kita baru saja menyatakan hal itu, kami belum diinisialisasi apa-apa. Ini semua sampah. Jadi tentu saja kami ingin memastikan bahwa kami menginisialisasi baik ukuran dan bidang kepala menjadi 0, sesuatu yang wajar. Kita juga bisa pergi ke depan dan nol keluar unsur-unsur dalam antrian kami. Dan untuk membuat ini cocok diagram, perhatikan bahwa sekarang antrian kami hanya bisa menampung tiga elemen; sedangkan tumpukan kami bisa menampung empat, antrian kami hanya bisa menampung tiga. Dan itu hanya untuk membuat diagram fit. Hal pertama yang terjadi di sini adalah kita enqueue string "hi". Dan seperti yang kita lakukan dengan tumpukan, tidak ada yang sangat berbeda di sini, kita membuang string pada string di [0] dan kenaikan ukuran kami oleh 1. Kami enqueue "bye", itu akan memakai. Jadi ini terlihat seperti tumpukan untuk sebagian besar. Kami memulai di sini, elemen baru, elemen baru, ukuran terus naik. Apa yang terjadi pada saat ini ketika kita ingin dequeue sesuatu? Ketika kita ingin dequeue, yang merupakan elemen yang ingin kita dequeue? [Basil] Strings [0]. >> Nol. Tepat, Basil. Kami ingin menyingkirkan string pertama, yang satu ini, "hi". Jadi apa hal lain yang berubah? Perhatikan ketika kita muncul sesuatu dari tumpukan, kita hanya mengubah ukuran, tapi di sini, kami punya beberapa hal yang berubah. Tidak hanya melakukan perubahan ukuran, tetapi perubahan kepala. Ini akan kembali ke titik Charlotte sebelumnya: mengapa kita memiliki kepala ini juga? Apakah masuk akal sekarang, Charlotte? >> Jenis. [Hardison] Jenis? Jadi apa yang terjadi ketika kita dequeued? Apa kepala melakukan itu sekarang adalah menarik? [Charlotte] Oh, karena berubah - Oke. Oh, begitu. Karena kepala - di mana kepala menunjuk ke perubahan dalam hal lokasi. Ini tidak lagi selalu satu indeks nol. >> Ya, tepatnya. Apa yang terjadi adalah jika dequeueing elemen tinggi dilakukan dan kita tidak memiliki bidang ini kepala karena kami selalu memanggil string ini pada 0 indeks kepala antrian kami, maka kita harus menggeser sisa antrian ke bawah. Kami harus menggeser "bye" dari dari string [1] ke string [0]. Dan string [2] ke string [1]. Dan kita harus melakukan ini untuk seluruh daftar elemen, array seluruh elemen. Dan ketika kita melakukan hal ini dengan sebuah array, yang jadi sangat mahal. Jadi di sini, itu bukan masalah besar. Kami hanya memiliki tiga elemen dalam array kita. Tetapi jika kita memiliki antrian seribu atau sejuta elemen elemen, dan kemudian tiba-tiba, kami mulai membuat sekelompok dequeue memanggil semua dalam satu lingkaran, hal-hal yang benar-benar akan memperlambat karena menggeser semuanya turun terus-menerus. Kau tahu, bergeser 1, pergeseran oleh 1, pergeseran oleh 1, pergeseran oleh 1. Sebaliknya, kita menggunakan kepala ini, kita menyebutnya sebagai "pointer" meskipun itu tidak benar-benar pointer dalam arti sempit, itu bukan tipe pointer. Ini bukan * int atau char * atau sesuatu seperti itu. Tapi itu menunjuk atau menunjukkan kepala antrian kami. Ya? [Mahasiswa] Bagaimana dequeue tahu untuk hanya pop off apa pun di kepala? [Hardison] Bagaimana dequeue tahu bagaimana pop off apa pun yang di kepala? Kanan >>, yeah. >> Apa itu melihat hanya apapun bidang kepala diatur ke. Jadi dalam hal ini kasus pertama, jika kita melihat di sini, kepala kita adalah 0, indeks 0. >> Kanan. [Hardison] Jadi itu hanya mengatakan apa-apa, baik, elemen pada indeks 0, string "hi", adalah elemen di kepala antrian kami. Jadi kita akan dequeue orang itu. Dan itu akan menjadi elemen yang akan dikembalikan ke pemanggil. Ya, Saad? Jadi >> kepala pada dasarnya menetapkan - di mana Anda akan indeks itu? Itulah awal dari itu? >> Ya. Oke >>. [Hardison] Itu menjadi awal baru untuk array kita. Jadi, ketika Anda dequeue sesuatu, yang harus Anda lakukan adalah mengakses elemen pada indeks q.head, dan itu akan menjadi elemen yang ingin Anda dequeue. Anda juga harus untuk penurunan ukuran. Kita akan melihat di mana sedikit hal mendapatkan sedikit rumit dengan ini. Kami dequeue, dan sekarang, jika kita enqueue lagi, di mana kita enqueue? Mana elemen berikutnya masuk dalam antrian kita? Katakanlah kita ingin enqueue string "CS". Ke mana indeks akan pergi? [Siswa] Strings [2]. >> Dua. Mengapa 2 dan tidak 0? [Basil] Karena sekarang kepala adalah 1, sehingga seperti awal daftar? [Hardison] Kanan. Dan apa menandai akhir dari daftar? Apa yang kita gunakan untuk menunjukkan akhir dari antrian kita? Kepala adalah kepala antrian kami, awal dari antrian kami. Apa akhir dari antrian kita? [Siswa] Ukuran. >> Ukuran, tepatnya. Jadi unsur-unsur baru kami masuk pada ukuran, dan unsur-unsur yang kita lepas landas datang dari kepala. Ketika kita enqueue elemen berikutnya, kita memasukkannya ke dalam pada ukuran. [Siswa] Sebelum Anda menempatkan bahwa dalam sekalipun, ukuran 1, kan? [Hardison] Kanan. Jadi tidak cukup pada ukuran. Ukuran +, tidak +1, tetapi kepala +. Karena kita bergeser segalanya dengan jumlah kepala. Jadi di sini, sekarang kita punya antrian ukuran 1 yang dimulai pada indeks 1. Ekor adalah indeks 2. Ya? [Siswa] Apa yang terjadi ketika Anda dequeue string [0], dan string 'slot dalam memori hanya mendapatkan dikosongkan, pada dasarnya, atau hanya lupa? [Hardison] Ya. Dalam hal ini, kami hanya melupakan mereka. Jika kita menyimpan salinan dari mereka untuk - banyak struktur data akan sering menyimpan salinan mereka sendiri dari unsur-unsur sehingga orang mengelola struktur data tidak perlu khawatir tentang di mana semua pointer akan. Struktur Data berpegang pada segala sesuatu, berpegang pada semua salinan, untuk memastikan bahwa semuanya tetap tepat. Namun, dalam kasus ini, struktur data yang baru saja, untuk kesederhanaan, tidak membuat salinan dari apa pun yang kita menyimpan di dalamnya. [Mahasiswa] Jadi ini array terus menerus -? >> Ya. Jika kita melihat kembali apa definisi itu struktur ini, itu. Ini hanya sebuah array standar seperti yang Anda lihat, array char * s. Apakah itu -? >> Ya, aku hanya ingin tahu jika Anda akhirnya akan kehabisan memori, sampai batas tertentu, jika Anda memiliki semua tempat kosong dalam array Anda? [Hardison] Ya, itulah titik yang baik. Jika kita melihat apa yang terjadi sekarang di titik ini, kami telah mengisi antrian kami, sepertinya. Tapi kita belum benar-benar penuh antrian kami karena kita memiliki antrian yang ukuran 2, tetapi mulai pada indeks 1, karena di situlah pointer kepala kita. Seperti yang Anda katakan, bahwa elemen pada string [0], pada indeks 0, tidak benar-benar ada. Ini bukan dalam antrian kami lagi. Kami hanya tidak repot-repot untuk masuk dan menimpanya ketika kita dequeued itu. Jadi meskipun sepertinya kita sudah kehabisan memori, kita benar-benar belum. Tempat itu tersedia bagi kita untuk menggunakan. Perilaku yang tepat, jika kita mencoba dan pertama dequeue sesuatu seperti "bye", yang akan pop bye off. Sekarang antrian kami dimulai pada indeks 2 dan ukuran 1. Dan sekarang jika kita mencoba dan enqueue sesuatu lagi, katakanlah 50, 50 harus pergi di tempat ini pada indeks 0 karena masih tersedia bagi kita. Ya, Saad? [Saad] Apakah itu terjadi secara otomatis? [Hardison] Ini tidak terjadi cukup otomatis. Anda harus melakukan matematika untuk membuatnya bekerja, tapi pada dasarnya apa yang kami lakukan adalah kami baru saja melilit. [Saad] Dan tidak apa-apa jika ini memiliki lubang di tengah-tengah itu? [Hardison] Ini adalah jika kita dapat membuat matematika bekerja dengan benar. Dan ternyata itu sebenarnya tidak begitu sulit untuk dilakukan dengan operator mod. Jadi sama seperti yang kita lakukan dengan Caesar dan hal-hal kripto, menggunakan mod, kita bisa mendapatkan sesuatu untuk membungkus dan terus sekitar dan sekitar dan sekitar dengan antrian kami, menjaga bahwa pointer kepala bergerak. Perhatikan ukuran yang selalu menghormati jumlah elemen benar-benar dalam antrian. Dan itu hanya pointer kepala yang terus bersepeda melalui. Jika kita melihat apa yang terjadi di sini, jika kita kembali ke awal, dan Anda hanya menonton apa yang terjadi pada kepala ketika kita enqueue sesuatu, tidak ada yang terjadi di kepala. Ketika kita enqueued sesuatu yang lain, tidak ada yang terjadi di kepala. Segera setelah kami dequeued sesuatu, kepala naik per satu. Kami enqueued sesuatu, tidak ada yang terjadi di kepala. Ketika kita dequeue sesuatu, tiba-tiba kepala akan bertambah. Ketika kita enqueue sesuatu, tidak ada yang terjadi di kepala. Apa yang akan terjadi pada saat ini jika kita dequeue sesuatu lagi? Setiap pikiran? Apa yang akan terjadi ke kepala? Apa yang harus terjadi pada kepala jika kita dequeue sesuatu yang lain? Kepala sekarang adalah di indeks 2, yang berarti bahwa kepala antrian string [2]. [Mahasiswa] Yang mengembalikan 0? >> Ini harus kembali ke 0. Ini harus membungkus kembali sekitar, tepatnya. Sejauh ini, setiap kali kita disebut dequeue, kami telah menambahkan satu ke kepala, menambahkan satu ke kepala, menambahkan satu ke kepala, menambahkan satu ke kepala. Segera setelah itu pointer kepala sampai ke indeks terakhir dalam array kami, maka kita harus membungkusnya kembali sekitar ke awal, kembali ke 0. [Charlotte] Apakah yang menentukan kapasitas antrian dalam tumpukan? [Hardison] Dalam hal ini, kami baru saja menggunakan sebuah konstanta # didefinisikan. Oke >>. [Hardison] Di file c yang sebenarnya., Anda bisa masuk dan kotoran dengan itu sedikit dan menjadikannya sebagai besar atau sesedikit yang Anda inginkan. [Charlotte] Jadi, ketika Anda membuat antrian, bagaimana Anda membuat komputer tahu seberapa besar Anda ingin stack menjadi? [Hardison] Itu pertanyaan yang bagus. Ada beberapa cara. Salah satunya adalah untuk hanya mendefinisikannya depan dan mengatakan ini akan menjadi antrian yang memiliki 4 elemen atau 50 elemen atau 10.000. Cara lain adalah dengan melakukan apa yang orang hacker edisi lakukan dan membuat fungsi untuk memiliki antrian Anda tumbuh secara dinamis sebagai hal-hal yang lebih akan ditambahkan masuk [Charlotte] Jadi untuk pergi dengan pilihan pertama, apa sintaks yang Anda gunakan untuk memberitahu program apa ukuran antrian? [Hardison] Ah. Jadi mari kita keluar dari hal ini. Aku masih di sini stack.c, jadi aku hanya akan menggulir ke atas sini. Dapatkah Anda melihat ini di sini? Ini adalah # define kapasitas 10. Dan ini hampir sintaks yang sama persis yang kita miliki untuk antrian. Kecuali dalam antrian, kita punya bahwa bidang struct ekstra di sini. [Charlotte] Oh, saya pikir kapasitas berarti kemampuan untuk string. [Hardison] Ah. >> Bahwa itu adalah panjang maksimum kata. >> Got it. Ya. Kapasitas di sini - itu adalah titik besar. Dan ini adalah sesuatu yang rumit karena apa yang kita telah menyatakan di sini adalah sebuah array dari char * s. Sebuah array dari pointer. Ini merupakan array dari karakter. Ini mungkin apa yang Anda lihat ketika Anda telah menyatakan buffer Anda untuk file I / O, ketika Anda telah membuat string secara manual pada stack. Namun, apa yang kita miliki di sini adalah sebuah array dari char * s. Jadi itu sebuah array dari pointer. Sebenarnya, jika kita tampilannya kembali keluar dan kami melihat apa yang terjadi di sini dalam presentasi, Anda melihat bahwa unsur-unsur yang sebenarnya, data karakter tidak disimpan dalam array itu sendiri. Apa yang disimpan dalam array kita di sini adalah pointer ke data karakter. Oke. Jadi kita telah melihat bagaimana ukuran antrian seperti dengan stack, ukuran selalu menghormati jumlah elemen saat ini dalam antrian. Setelah membuat 2 enqueues, ukuran 2. Setelah membuat dequeue ukuran sekarang adalah 1. Setelah membuat enqueue lain ukurannya kembali ke 2. Jadi ukuran pasti menghormati jumlah elemen dalam antrian, dan kemudian kepala hanya terus bersepeda. It goes dari 0-1-2,, 0-1-2 0-1-2. Dan setiap kali kita sebut dequeue, pointer kepala akan bertambah dengan indeks berikutnya. Dan jika kepala adalah tentang untuk pergi ke, itu loop kembali sekitar ke 0. Maka dengan itu, kita dapat menulis fungsi dequeue. Dan kita akan meninggalkan fungsi enqueue bagi kalian untuk melaksanakan gantinya. Ketika kita dequeue elemen keluar dari antrian kami, apa hal pertama yang Daniel lakukan ketika kita mulai menulis fungsi pop untuk tumpukan? Biarkan aku mendengar dari seseorang yang tidak berbicara lagi. Mari kita lihat, Saad, apakah Anda ingat apa yang Daniel lakukan sebagai hal pertama ketika ia menulis pop? [Saad] Ada, itu - >> Dia diuji untuk sesuatu. [Saad] Jika ukuran lebih besar dari 0. >> Tepat. Dan apa itu pengujian untuk? [Saad] Yang sedang menguji untuk melihat apakah ada sesuatu di dalam array. [Hardison] Ya. Tepat. Jadi Anda tidak bisa pop apa pun keluar dari tumpukan jika itu kosong. Demikian juga, Anda tidak bisa dequeue apa pun dari antrian jika itu kosong. Apa hal pertama yang harus kita lakukan dalam fungsi dequeue kami di sini, menurut Anda? [Saad] Jika ukuran lebih besar dari 0? >> Ya. Dalam hal ini, saya sebenarnya hanya diuji untuk melihat apakah itu adalah 0. Jika itu adalah 0, kita dapat kembali null. Tapi logika yang sama persis. Dan mari kita lanjutkan dengan ini. Jika ukuran tidak 0, di mana merupakan elemen yang ingin kita dequeue? [Saad] Pada kepala? >> Tepat. Kami hanya bisa mengeluarkan elemen pertama dalam antrian kami dengan mengakses elemen di kepala. Gila apa-apa. Setelah itu, apa yang harus kita lakukan? Apa yang telah terjadi? Apa hal lain yang kita bicarakan di dequeue? Dua hal yang harus terjadi, karena antrian kami telah berubah. [Daniel] Mengurangi ukuran. >> Kita harus mengurangi ukuran, dan meningkatkan kepala? Tepat. Untuk meningkatkan kepala, kita tidak bisa hanya membabi buta meningkatkan kepala, ingat. Kita tidak bisa hanya melakukan queue.head + +. Kita harus juga menyertakan mod dengan kapasitas. Dan mengapa kita mod oleh kapasitas, Stella? [Stella] Karena itu untuk membungkus sekitar. >> Tepat. Kami mod oleh kapasitas karena memiliki untuk membungkus kembali sekitar ke 0. Jadi sekarang, pada titik ini, kita bisa melakukan apa yang dikatakan Daniel. Kita bisa memundurkan ukuran. Dan kemudian kami hanya dapat mengembalikan elemen yang berada di bagian atas antrian. Ini terlihat agak degil pada awalnya. Anda mungkin memiliki pertanyaan. Maaf? [Sam] Kenapa pertama di bagian atas antrian? Mana itu pergi? [Hardison] Ini berasal dari baris keempat dari bawah. Setelah kita uji untuk memastikan bahwa antrian kita tidak kosong, kita tarik keluar * char pertama, kita tarik keluar elemen yang duduk di indeks kepala dari array kita, array kami >> string, dan panggilan yang pertama? [Hardison] Dan kami menyebutnya pertama. Ya. Hanya untuk menindaklanjuti itu, mengapa Anda berpikir kami harus melakukan itu? [Sam] Setiap pertama hanya kembali q.strings [q.head]? >> Ya. >> Karena kita melakukan ini berubah q.head dengan fungsi mod, dan tidak ada cara untuk melakukan itu dalam garis kembali juga. [Hardison] Tepat. Kau tepat. Sam benar-benar spot on. Alasan kami harus menarik keluar elemen pertama dalam antrian dan menyimpannya ke dalam variabel karena baris ini di mana kami baru saja q.head, ada operator mod di sana adalah bukan sesuatu yang bisa kita lakukan dan telah berlaku pula di kepala tanpa - dalam satu baris. Jadi kita benar-benar harus menarik keluar elemen pertama, kemudian menyesuaikan kepala, menyesuaikan ukuran, dan kemudian kembali elemen yang kita ditarik keluar. Dan ini adalah sesuatu yang kita akan lihat datang kemudian dengan daftar terhubung, seperti yang kita bermain-main dengan mereka. Seringkali ketika Anda membebaskan atau membuang daftar link Anda perlu mengingat elemen berikutnya, pointer berikutnya dari sebuah linked list sebelum membuang satu saat. Karena jika tidak, anda membuang informasi apa yang tersisa dalam daftar. Sekarang, jika Anda pergi ke alat Anda, Anda membuka queue.c--x keluar dari ini. Jadi jika saya membuka queue.c, biarkan aku zoom di sini, Anda akan melihat bahwa Anda memiliki file yang sama tampak. Tampak serupa file apa yang kita punya sebelumnya dengan stack.c. Kami punya struct kami untuk antrian didefinisikan seperti yang kita lihat pada slide. Kami memiliki fungsi enqueue kami yang untuk Anda lakukan. Dan kami memiliki fungsi dequeue sini. Fungsi dequeue dalam file tersebut diimplementasikan, tapi aku akan meletakkannya kembali pada PowerPoint sehingga Anda dapat mengetik dalam, jika Anda ingin. Jadi selama 5 menit berikutnya atau lebih, kalian bekerja pada enqueue yang hampir kebalikan dari dequeue. Anda tidak harus menyesuaikan kepala ketika Anda enqueueing, tapi apa yang Anda harus menyesuaikan? Ukuran. Jadi, ketika Anda enqueue, kepala tetap tak tersentuh, ukuran akan berubah. Tapi itu tidak mengambil sedikit - Anda harus bermain-main dengan mod yang untuk mencari tahu persis apa indeks elemen baru harus dimasukkan pada. Jadi saya akan memberikan kalian sedikit, memasang dequeue kembali pada slide, dan seperti yang kalian punya pertanyaan, berteriak mereka sehingga kita dapat semua berbicara tentang mereka sebagai kelompok. Juga, dengan ukuran Anda jangan - ketika Anda menyesuaikan ukuran, Anda dapat selalu hanya - Anda harus mod ukuran pernah? [Daniel] No >> Anda tidak perlu mod ukuran, benar. Karena ukuran akan selalu, jika kau - dengan asumsi Anda mengelola hal-hal yang tepat, ukuran akan selalu berada di antara 0 dan 3. Di mana Anda harus mod ketika Anda melakukan enqueue? [Mahasiswa] Hanya untuk kepala. >> Hanya untuk kepala, tepatnya. Dan mengapa Anda harus mod sama sekali di enqueue? Ketika adalah situasi di mana Anda harus mod? [Siswa] Jika Anda memiliki barang-barang di ruang, seperti di ruang 1 dan 2, dan kemudian Anda perlu menambahkan sesuatu pada 0. [Hardison] Ya, tepatnya. Jadi jika pointer kepala Anda di akhir, atau jika ukuran Anda ditambah kepala Anda lebih besar, atau lebih tepatnya, akan membungkus antrian. Jadi dalam situasi yang kita punya di sini pada slide sekarang, jika saya ingin enqueue sesuatu sekarang, kita ingin enqueue sesuatu di indeks 0. Jadi jika Anda melihat di mana 50 pergi, dan saya sebut enqueue 50, terbenam ada di bagian bawah. It goes dalam indeks 0. Ini menggantikan 'hi' yang sudah dequeued. [Daniel] Jangan Anda mengurus hal itu di dequeue sudah? Mengapa ia melakukan sesuatu dengan kepala di enqueue? [Hardison] Oh, jadi Anda tidak memodifikasi kepala, maaf. Tapi Anda harus menggunakan operator mod saat Anda mengakses elemen yang ingin Anda enqueue saat Anda mengakses elemen berikutnya dalam antrian Anda. [Basil] saya tidak melakukan itu, dan saya mendapat "sukses" di sana. [Daniel] Oh, saya mengerti apa yang Anda katakan. [Hardison] Jadi Anda tidak - Anda hanya lakukan di q.size? [Basil] Ya. Saya baru saja mengubah sisi, aku tidak melakukan apa-apa dengan kepala. [Hardison] Anda tidak benar-benar harus mengatur ulang kepala menjadi apa-apa, tetapi ketika Anda indeks ke dalam array string, Anda benar-benar harus pergi ke depan dan menghitung mana elemen berikutnya adalah, karena withe stack, elemen berikutnya dalam tumpukan Anda selalu pada indeks yang sesuai dengan ukurannya. Jika kita melihat kembali pada fungsi mendorong kami tumpukan, kita selalu bisa memetik dalam elemen baru kami tepat di ukuran indeks. Sedangkan dengan antrian, kita tidak bisa melakukan itu karena jika kita berada di situasi ini, jika kita enqueued 50 string baru kami akan pergi ke kanan di string [1] yang kita tidak ingin lakukan. Kami ingin memiliki string baru pergi pada indeks 0. Apakah orang - ya? [Mahasiswa] Saya punya pertanyaan, tapi itu tidak benar-benar berhubungan. Apa artinya ketika seseorang hanya panggilan sesuatu seperti pointer pred? Apa nama yang singkat untuk? Aku tahu itu hanya sebuah nama. [Hardison] pointer Pred? Mari kita lihat. Dalam konteks apa? [Mahasiswa] Itu untuk insert. Aku bisa meminta Anda nanti jika Anda ingin karena itu tidak benar-benar berhubungan, tapi aku hanya - [Hardison] Dari kode insert Daud dari kuliah? Kita dapat menarik bahwa sampai dan berbicara tentang itu. Kita akan membicarakannya berikutnya, setelah kami mendapatkan daftar terkait. Jadi mari kita benar-benar cepat melihat apa fungsi enqueue terlihat seperti. Apa hal pertama yang orang coba lakukan sejalan enqueue Anda? Ke antrian ini? Mirip dengan apa yang Anda lakukan untuk mendorong tumpukan. Apa yang Anda lakukan, Stella? [Stella, dipahami] [Hardison] Tepat. Jika (q.size KAPASITAS ==) - Saya harus menempatkan kawat gigi saya di tempat yang tepat - return false. Zoom dalam sedikit. Oke. Sekarang apa hal berikutnya yang harus kami lakukan? Sama seperti dengan stack, dan dimasukkan di tempat yang tepat. Dan jadi apa adalah tempat yang tepat untuk memasukkan itu? Dengan tumpukan itu ukuran indeks, dengan ini itu tidak cukup itu. [Daniel] Saya memiliki q.head--atau - q.strings >>? >> Ya. q.strings [q.head + q.size mod KAPASITAS]? [Hardison] Kita mungkin ingin menempatkan tanda kurung di sekitar ini sehingga kita mendapatkan prioritas yang tepat dan jadi itulah cleart untuk semua orang. Dan menetapkan bahwa yang sama? >> Untuk str? >> Untuk str. Besar. Dan sekarang apa hal terakhir yang harus kita lakukan? Sama seperti yang kami lakukan dalam stack. >> Increment ukuran? >> Increment ukuran. Boom. Dan kemudian, karena kode pemula saja kembali palsu secara default, kita ingin mengubah ini menjadi true jika semuanya berjalan melalui dan semuanya berjalan dengan baik. Baiklah. Itu banyak informasi untuk bagian. Kami tidak cukup lebih. Kami ingin berbicara sangat cepat tentang sendiri-linked list. Aku akan menempatkan ini sehingga kita dapat kembali ke sini kelak. Tapi mari kita kembali ke presentasi kami untuk hanya beberapa slide. Jadi enqueue adalah TODO, sekarang kita sudah melakukannya. Sekarang mari kita lihat sendiri-linked list. Kami berbicara tentang ini sedikit lebih dalam kuliah. Berapa banyak dari kalian melihat demo di mana kita memiliki orang-orang canggung menunjuk ke tiap nomor lain dan memegang? >> Saya dalam hal itu. >> Apa yang kalian pikirkan? Apakah itu, mudah-mudahan demystify ini agak sedikit? Dengan daftar, ternyata kita berurusan dengan tipe ini bahwa kita akan memanggil node. Sedangkan dengan antrian dan tumpukan kami memiliki struct yang kita sebut antrian di stack, kami punya ini antrian baru di jenis tumpukan, daftar di sini adalah benar-benar hanya terdiri dari sekelompok node. Dengan cara yang sama bahwa string adalah hanya sekelompok karakter semua berbaris di samping satu sama lain. Sebuah linked list hanyalah sebuah node dan node lain dan lain node dan node lain. Dan bukannya menghancurkan semua node bersama-sama dan menyimpannya contiguously semua tepat di samping satu sama lain dalam memori, memiliki pointer ini selanjutnya memungkinkan kita untuk menyimpan node manapun, secara acak. Dan kemudian jenis kawat mereka semua bersama-sama menunjuk dari satu ke yang berikutnya. Dan apa keuntungan besar bahwa ini memiliki lebih dari array? Atas segala sesuatu menyimpan contiguously hanya terjebak di samping satu sama lain? Kau ingat? Ya? >> Alokasi memori dinamis? >> Alokasi memori dinamis dalam arti apa? [Siswa] Dalam Anda dapat tetap membuatnya lebih besar dan Anda tidak harus memindahkan seluruh array Anda? [Hardison] Tepat. Jadi dengan array, bila Anda ingin menempatkan elemen baru ke tengah-tengah itu, Anda harus menggeser segalanya untuk membuat ruang. Dan seperti kita bicarakan dengan antrian, itu sebabnya kita menjaga pointer kepala, sehingga kita tidak terus-menerus hal pergeseran. Karena yang mendapat mahal jika Anda punya array besar dan Anda terus-menerus melakukan hal-sisipan acak. Sedangkan dengan daftar, yang harus Anda lakukan adalah membuangnya di sebuah node baru, menyesuaikan pointer, dan Anda sudah selesai. Apa yang menyebalkan tentang hal ini? Selain dari fakta bahwa itu tidak mudah untuk bekerja dengan sebagai array? Ya? [Daniel] Nah, saya kira itu jauh lebih sulit untuk mengakses elemen tertentu dalam linked list? [Hardison] Anda tidak bisa hanya melompat ke elemen sewenang-wenang di tengah daftar terkait. Bagaimana Anda harus melakukannya, bukan? >> Anda harus melangkah melalui seluruh hal. [Hardison] Ya. Anda harus melalui satu per satu waktu, satu per satu. Ini adalah besar - itu adalah rasa sakit. Apa yang lain - ada lagi kejatuhan ini. [Basil] Anda tidak bisa maju dan mundur? Anda harus pergi satu arah? [Hardison] Ya. Jadi bagaimana kita mengatasi itu, kadang-kadang? [Basil] Ganda-terkait daftar? >> Tepat. Ada daftar doubly-linked. Ada juga - maaf? [Sam] Apakah itu sama dengan menggunakan hal yang pred - Aku baru ingat, tidak bahwa apa hal pred adalah untuk? Bukankah itu di antara ganda dan tunggal? [Hardison] Mari kita lihat apa sebenarnya yang dia lakukan. Jadi di sini kita pergi. Berikut daftar kode. Di sini kita memiliki predptr, di sini. Apakah ini apa yang Anda bicarakan? Jadi ini - dia membebaskan daftar dan dia mencoba untuk menyimpan pointer untuk itu. Ini bukan ganda, tunggal dihubungkan-daftar. Kita bisa bicara lebih lanjut tentang ini nanti karena ini berbicara tentang membebaskan daftar dan saya ingin menunjukkan beberapa hal lain terlebih dahulu. tapi itu hanya - itu mengingat nilai ptr [Mahasiswa] Oh, itu pointer mendahului? >> Ya. Sehingga kita kemudian dapat kenaikan ptr sendiri sebelum kita kemudian bebas apa predptr adalah. Karena kita tidak bisa ptr gratis dan kemudian memanggil ptr = ptr berikutnya, kan? Itu akan menjadi buruk. Jadi mari kita lihat, kembali ke orang ini. Hal lain yang buruk tentang daftar adalah bahwa sedangkan dengan array kita hanya memiliki semua elemen sendiri ditumpuk di samping satu sama lain, disini kami juga telah memperkenalkan pointer ini. Jadi ada sebuah bongkahan tambahan memori yang kita harus menggunakan untuk setiap elemen yang kita menyimpan dalam daftar kami. Kami mendapatkan fleksibilitas, tetapi datang pada biaya. Muncul dengan biaya waktu, dan ia datang dengan biaya memori juga. Waktu dalam arti bahwa kita sekarang harus melalui setiap elemen dalam array untuk menemukan satu pada indeks 10, atau yang akan menjadi indeks 10 dalam array. Hanya benar-benar cepat, ketika kita keluar diagram daftar ini, biasanya kita berpegang pada kepala daftar atau pointer pertama daftar dan perhatikan bahwa ini adalah pointer yang benar. Ini hanya 4 byte. Ini bukan sebuah simpul yang sebenarnya itu sendiri. Jadi Anda melihat bahwa itu tidak memiliki nilai int di dalamnya, tidak ada pointer berikutnya di dalamnya. Ini benar-benar hanya sebuah pointer. Ini akan menunjukkan sesuatu yang merupakan struct simpul yang sebenarnya. [Sam] Sebuah pointer yang disebut simpul? >> Ini - tidak ada. Ini adalah pointer ke sesuatu node jenis. Ini adalah pointer ke struct node. >> Oh, oke. Diagram pada kode, kiri di sebelah kanan. Kita dapat mengatur ke nol, yang merupakan cara yang baik untuk memulai. Bila Anda diagram itu, Anda juga menuliskannya sebagai null atau Anda meletakkan garis melalui itu seperti itu. Salah satu cara termudah untuk bekerja dengan daftar, dan kami meminta Anda tambahkan baik dan menambahkan untuk melihat perbedaan antara keduanya, namun mengawali pasti lebih mudah. Bila Anda tambahkan, ini adalah di mana Anda - ketika Anda tambahkan (7), Anda pergi dan membuat struct simpul dan Anda mengatur pertama yang menunjukkan hal itu, karena sekarang, karena kita prepended itu, itu akan berada di awal daftar. Jika kita tambahkan (3), yang menciptakan node lain, tapi sekarang 3 datang sebelum 7. Jadi kita pada dasarnya mendorong hal-hal ke daftar kami. Sekarang, Anda dapat melihat bahwa tambahkan, kadang-kadang orang menyebutnya mendorong, karena Anda mendorong elemen baru ke daftar Anda. Hal ini juga mudah untuk menghapus di depan daftar. Jadi orang sering akan memanggil pop itu. Dan dengan cara itu, Anda dapat meniru tumpukan menggunakan linked list. Whoops. Maaf, sekarang kita masuk ke append. Jadi di sini kita prepended (7), sekarang kita tambahkan (3). Jika kita prepended sesuatu yang lain ke daftar ini, jika kita prepended (4), maka kita akan memiliki 4 dan kemudian 3 dan kemudian 7. Jadi kita bisa pop dan menghapus 4, hapus 3, hapus 7. Seringkali cara yang lebih intuitif untuk berpikir tentang hal ini adalah dengan append. Jadi saya sudah digambarkan apa itu akan terlihat seperti dengan menambahkan di sini. Di sini, ditambahkan (7) tidak terlihat berbeda karena hanya ada satu elemen dalam daftar. Dan menambahkan (3) menempatkan itu di akhir. Mungkin Anda bisa lihat sekarang trik dengan append adalah karena kita hanya tahu di mana awal daftar ini, untuk menambahkan ke daftar Anda harus berjalan semua jalan melalui daftar untuk sampai ke akhir, berhenti, kemudian membangun simpul Anda dan segala sesuatu memetik bawah. Kawat semua hal atas. Jadi dengan tambahkan, karena kami hanya merobek ini benar-benar cepat, ketika Anda tambahkan ke daftar, itu cukup sederhana. Anda membuat simpul baru, melibatkan beberapa alokasi memori dinamis. Jadi di sini kita membuat struct node menggunakan malloc. Jadi kita menggunakan malloc karena itu akan menyisihkan memori bagi kita untuk nanti karena kita tidak ingin hal ini - kami ingin memori ini bertahan untuk waktu yang lama. Dan kita mendapatkan pointer ke ruang memori yang baru saja kita dialokasikan. Kami menggunakan ukuran node, kita tidak menjumlahkan bidang. Kami tidak secara manual menghasilkan jumlah byte, sebagai gantinya kita menggunakan sizeof sehingga kita tahu kita mendapatkan jumlah yang tepat byte. Kami pastikan untuk menguji bahwa panggilan malloc kami berhasil. Ini adalah sesuatu yang ingin Anda lakukan pada umumnya. Pada mesin modern, kehabisan memori bukanlah sesuatu yang mudah kecuali Anda mengalokasikan satu ton barang dan membuat daftar besar, tetapi jika Anda sedang membangun barang-barang untuk, katakanlah, seperti iPhone atau Android, Anda memiliki sumber daya memori terbatas, terutama jika Anda melakukan sesuatu yang intens. Jadi ada baiknya untuk masuk ke praktik. Perhatikan bahwa saya telah menggunakan beberapa fungsi yang berbeda di sini bahwa Anda telah melihat bahwa adalah jenis baru. Jadi fprintf adalah seperti printf kecuali argumen pertama adalah aliran yang ingin Anda cetak. Dalam kasus ini, kita ingin mencetak ke string standard error yang berbeda dari outstream standar. Secara default itu muncul di tempat yang sama. Hal ini juga mencetak keluar ke terminal, tetapi Anda bisa - menggunakan perintah-perintah tersebut Anda belajar tentang, teknik pengalihan Anda pelajari dalam video Tommy untuk mengatur masalah 4, Anda dapat langsung ke daerah yang berbeda, kemudian keluar, di sini, keluar program anda. Ini dasarnya seperti kembali dari main, kecuali kita menggunakan keluar karena di sini kembali tidak akan melakukan apa-apa. Kami tidak dalam utama, sehingga kembali tidak keluar dari program seperti yang kita inginkan. Jadi kita menggunakan fungsi keluar dan memberikan kode kesalahan. Maka di sini kita menetapkan bidang nilai node baru, bidang saya untuk menjadi sama dengan i, dan kemudian kita kawat itu. Kami mengatur pointer berikutnya node baru untuk menunjuk ke pertama, dan kemudian pertama sekarang akan menunjuk ke simpul baru. Ini baris pertama dari kode, kita benar-benar membangun node baru. Bukan yang terakhir dua baris fungsi ini, tetapi yang pertama. Anda benar-benar dapat menarik keluar ke fungsi, menjadi fungsi pembantu. Itu sering apa yang saya lakukan adalah, saya menariknya keluar ke fungsi, Saya menyebutnya sesuatu seperti simpul membangun, dan yang membuat fungsi tambahkan cukup kecil, itu hanya 3 baris kemudian. Saya membuat panggilan ke fungsi simpul saya membangun, dan kemudian saya segalanya kawat up. Hal terakhir yang saya ingin menunjukkan kepada Anda, dan aku akan membiarkan Anda melakukan append dan semua itu sendiri, adalah bagaimana iterate atas daftar. Ada banyak cara yang berbeda untuk iterate atas daftar. Dalam kasus ini, kita akan menemukan panjang daftar. Jadi kita mulai dengan panjang = 0. Ini sangat mirip dengan menulis strlen untuk string. Ini adalah apa yang saya ingin menunjukkan, ini untuk loop di sini. Ini terlihat agak funky, itu tidak biasa int i = 0, i berikutnya. Aku akan membiarkan Anda mengisi kekosongan di sini karena kita kehabisan waktu. Tapi ingatlah ini saat Anda bekerja pada psets spellr Anda. Daftar terhubung, jika Anda menerapkan tabel hash, pasti akan datang sangat berguna. Dan memiliki idiom ini untuk perulangan atas hal-hal yang akan membuat hidup jauh lebih mudah, mudah-mudahan. Ada pertanyaan, dengan cepat? [Sam] Akankah Anda mengirimkan SLL selesai dan sc? [Hardison] Ya. Saya akan mengirimkan slide selesai dan menyelesaikan tumpukan SLL dan queue.cs. [CS50.TV]