Mengapa menyisipkan di tengah daftar tertaut O (1)?

105

Menurut artikel Wikipedia tentang daftar tertaut , memasukkan di tengah daftar tertaut dianggap O (1). Saya akan berpikir itu akan menjadi O (n). Tidakkah Anda perlu menemukan node yang mungkin berada di dekat akhir daftar?

Apakah analisis ini tidak memperhitungkan penemuan operasi node (meskipun diperlukan) dan hanya penyisipan itu sendiri?

EDIT :

Daftar tertaut memiliki beberapa keunggulan dibandingkan array. Penyisipan elemen pada titik tertentu dari daftar adalah operasi waktu-konstan, sedangkan penyisipan dalam array mungkin memerlukan pemindahan setengah dari elemen, atau lebih.

Pernyataan di atas sedikit menyesatkan saya. Koreksi saya jika saya salah, tetapi menurut saya kesimpulannya harus:

Array:

  • Menemukan titik penyisipan / penghapusan O (1)
  • Melakukan penyisipan / penghapusan O (n)

Daftar Tertaut:

  • Menemukan titik penyisipan / penghapusan O (n)
  • Melakukan penyisipan / penghapusan O (1)

Saya pikir satu-satunya saat Anda tidak perlu menemukan posisi adalah jika Anda menyimpan semacam penunjuk ke sana (seperti kepala dan ekor dalam beberapa kasus). Jadi kami tidak bisa secara langsung mengatakan bahwa daftar tertaut selalu mengalahkan array untuk opsi sisipkan / hapus.

Rob Sobers
sumber

Jawaban:

113

Anda benar, artikel menganggap "Pengindeksan" sebagai operasi terpisah. Jadi penyisipan itu sendiri adalah O (1), tetapi sampai ke simpul tengah itu adalah O (n).

CookieOfFortune
sumber
3
Yang membuat perbedaan besar ketika memasukkan lebih dari 1 objek pada posisi yang sama ...
Memiliki QUIT - Anony-Mousse
@ Anony-Mousse, bisakah Anda menjelaskannya lebih lanjut? yaitu kita perlu menemukan posisi penyisipan hanya sekali saat memasukkan beberapa objek?
MyTitle
2
Ini adalah O (n) dalam ukuran daftar yang ada, bukan jumlah penyisipan yang Anda rencanakan untuk dilakukan di sana.
Memiliki QUIT - Anony-Mousse
28

Penyisipan itu sendiri adalah O (1). Penemuan node adalah O (n).

Evansbee
sumber
25

Tidak, ketika Anda memutuskan untuk memasukkan, diasumsikan Anda sudah di tengah iterasi melalui daftar.

Operasi pada Daftar Tertaut sering dilakukan sedemikian rupa sehingga tidak diperlakukan sebagai "daftar" generik, tetapi sebagai kumpulan node - anggap node itu sendiri sebagai iterator untuk loop utama Anda. Jadi saat Anda melihat-lihat daftar, Anda melihat sebagai bagian dari logika bisnis Anda bahwa node baru perlu ditambahkan (atau yang lama dihapus) dan Anda melakukannya. Anda dapat menambahkan 50 node dalam satu iterasi dan masing-masing node tersebut hanya O (1) waktu untuk memutuskan tautan dua node yang berdekatan dan memasukkan yang baru ..

Sunting: Sobat, Anda mengetik paragraf kedua dan tiba-tiba alih-alih menjadi responden pertama, Anda yang ke-5 mengatakan hal yang sama seperti 4 yang pertama!

Bill K
sumber
1
Ha ya itu menyebalkan ... saya memberi Anda +1 karena nilainya menyatakan bahwa kompleksitas penyisipan daftar tertaut dipertimbangkan dalam konteks sudah berada di penunjuk yang diinginkan.
Daniel Macias
6

Untuk tujuan membandingkan dengan larik, yang ditunjukkan bagan itu, itu adalah O (1) karena Anda tidak perlu memindahkan semua item setelah simpul baru.

Jadi ya, mereka berasumsi bahwa Anda sudah memiliki pointer ke node itu, atau mendapatkan pointer itu sepele. Dengan kata lain, masalahnya adalah: " diberi node di X , kode apa yang akan dimasukkan setelah node ini?" Anda bisa mulai dari titik sisipan.

Joel Coehoorn
sumber
5

Penyisipan ke dalam daftar tertaut berbeda dengan pengulangan di atasnya. Anda tidak menemukan item tersebut, Anda menyetel ulang penunjuk untuk meletakkan item di sana. Tidak masalah apakah itu akan disisipkan di dekat ujung depan atau dekat ujung, penyisipan masih melibatkan penunjuk yang ditugaskan kembali. Ini akan tergantung pada bagaimana itu diterapkan, tentu saja, tapi itulah kekuatan daftar - Anda dapat menyisipkan dengan mudah. Mengakses melalui indeks adalah tempat array bersinar. Untuk daftar, bagaimanapun, biasanya akan menjadi O (n) untuk menemukan item ke-n. Setidaknya itulah yang saya ingat dari sekolah.

itsmatt
sumber
3

Karena tidak melibatkan perulangan apapun.

Memasukkan itu seperti:

  • masukkan elemen
  • tautan ke sebelumnya
  • tautan ke berikutnya
  • selesai

ini adalah waktu yang konstan dalam hal apapun.

Akibatnya, memasukkan n elemen satu demi satu adalah O (n).

Tomalak
sumber
3

Apakah analisis ini tidak memperhitungkan penemuan operasi node (meskipun diperlukan) dan hanya penyisipan itu sendiri?

Anda mengerti. Penyisipan pada titik tertentu mengasumsikan bahwa Anda sudah menahan penunjuk ke item yang ingin Anda sisipkan setelah:

InsertItem(item * newItem, item * afterItem)
e. James
sumber
2

Menyisipkan adalah O (1) setelah Anda tahu di mana Anda akan meletakkannya.

Lance Richardson
sumber
2

Tidak, itu tidak termasuk pencarian. Tetapi jika Anda sudah memiliki penunjuk ke item di tengah daftar, memasukkan pada titik itu adalah O (1).

Jika Anda harus mencarinya, Anda harus menambahkan waktu untuk mencari, yang seharusnya O (n).

TED
sumber
0

Artikel ini tentang membandingkan array dengan daftar. Menemukan posisi sisipan untuk kedua larik dan daftar adalah O (N), jadi artikel mengabaikannya.


sumber
1
Bukankah menemukan titik penyisipan sebuah array menjadi O (1)? Karena array disimpan dalam memori yang berdekatan, yang harus dilakukan hanyalah menambahkan offset.
Rob Sobers
@ vg1890 - Anda harus mencari offsetnya terlebih dahulu.
0

O (1) tergantung pada fakta bahwa Anda memiliki item di mana Anda akan memasukkan item baru. (sebelum atau sesudah). Jika tidak, itu adalah O (n) karena Anda harus menemukan item itu.

Glenn
sumber
0

Saya pikir itu hanya kasus apa yang Anda pilih untuk dihitung untuk notasi O (). Dalam kasus memasukkan operasi normal untuk menghitung adalah operasi salin. Dengan array, memasukkan di tengah melibatkan menyalin semua yang ada di atas lokasi ke dalam memori. Dengan daftar yang ditautkan, ini menjadi pengaturan dua petunjuk. Anda perlu menemukan lokasinya tidak peduli apa yang akan dimasukkan.

workmad3
sumber
0

Jika Anda memiliki referensi node untuk disisipkan setelah operasi adalah O (1) untuk daftar tertaut.
Untuk sebuah array, nilainya tetap O (n) karena Anda harus memindahkan semua node konkutif.

Sani Singh Huttunen
sumber
0

Kasus yang paling umum mungkin menyisipkan di awal atau di akhir daftar (dan akhir daftar mungkin tidak perlu waktu untuk menemukannya).

Bandingkan dengan menyisipkan item di awal atau akhir larik (yang memerlukan pengubahan ukuran larik jika ada di akhir, atau mengubah ukuran dan memindahkan semua elemen jika di awal).

ChrisW
sumber
Dimungkinkan untuk membuat penyisipan item ke akhir array menjadi O (1) jika Anda menyimpan buffer elemen kosong di akhir, meskipun kadang-kadang penyisipan masih akan menjadi O (1). Kebanyakan koleksi melakukan ini. Dimungkinkan juga untuk membuat item inerting ke awal array menjadi O (1) dengan mengubah operator indeks Anda untuk mengembalikan nomor elemen (n + x)% len, di mana x adalah berapa kali Anda memasukkan item ke awal dari daftar. Deques terkadang diterapkan seperti ini (tetapi terkadang juga diterapkan dengan daftar tertaut ganda.
Brian