ประหยัดในการเริ่มต้นอาร์เรย์


19

ฉันเพิ่งอ่านว่ามันเป็นไปได้ที่จะมีอาร์เรย์ที่ไม่จำเป็นต้องเริ่มต้นคือมันเป็นไปได้ที่จะใช้พวกเขาโดยไม่ต้องใช้เวลาพยายามตั้งสมาชิกแต่ละคนเป็นค่าเริ่มต้น เช่นคุณสามารถเริ่มใช้อาร์เรย์ราวกับว่ามันได้รับการเริ่มต้นโดยค่าเริ่มต้นโดยไม่ต้องเริ่มต้นได้ (ขออภัยฉันจำไม่ได้ว่าอ่านตรงไหน)

ตัวอย่างเช่นสาเหตุที่อาจเป็นเรื่องน่าประหลาดใจ:

สมมติว่าคุณกำลังพยายามที่จะจำลอง ที่เลวร้ายที่สุดกรณี Hashtable (สำหรับแต่ละแทรก / search / ลบ) ของจำนวนเต็มในช่วง[ 1 , n 2 ]O(1)[1,n2]

คุณสามารถจัดสรรอาเรย์ที่มีขนาดบิต2บิตและใช้แต่ละบิตเพื่อแสดงการมีอยู่ของจำนวนเต็มใน hashtable หมายเหตุ: หน่วยความจำจัดสรรถือว่าO ( 1 )เวลาn2O(1)

ตอนนี้ถ้าคุณไม่ได้มีการเริ่มต้นอาร์เรย์นี้ทั้งหมดลำดับใด ๆ ของการพูดดำเนินการเมื่อวัน Hashtable ตอนนี้กรณีที่เลวร้ายO ( n )nO(n)

ดังนั้นในความเป็นจริงคุณจะต้องมีการนำแฮช "สมบูรณ์แบบ" มาใช้ซึ่งลำดับของการปฏิบัติการใช้พื้นที่Θ ( n 2 )แต่ทำงานในเวลาO ( n ) !nΘ(n2)O(n)

โดยปกติแล้วหนึ่งคาดว่า runtime ของคุณจะเป็นอย่างน้อยไม่ดีเท่าการใช้พื้นที่ของคุณ!

หมายเหตุ: ตัวอย่างข้างต้นอาจถูกใช้สำหรับการดำเนินการของชุดเบาบางหรือเมทริกซ์กระจัดกระจายดังนั้นฉันจึงไม่เพียง แต่สนใจทางทฤษฎี

ดังนั้นคำถามคือ:

เป็นไปได้อย่างไรที่จะมีอาร์เรย์เช่นโครงสร้างข้อมูลซึ่งทำให้เราสามารถข้ามขั้นตอนการเริ่มต้นได้


@Aryabhata การอ้างอิงที่คุณพูดถึงคืออะไร?
uli

1
"การใช้หน่วยความจำ" ไม่เหมือนกับ "มีการจัดสรร แต่ไม่เคยเข้าถึงหน่วยความจำ" ดังนั้นฉันคิดว่าแรงจูงใจ "ความขัดแย้ง" ไม่ได้มีอยู่จริง
Raphael

1
ฉันคิดว่าย่อหน้าแรกค่อนข้างชัดเจน: มีค่าเริ่มต้นโดยไม่ต้องสละเวลากรอกข้อมูลด้วยค่าเริ่มต้น คำตอบในกรณีที่คนอื่นมีเวลาเขียนขึ้นก่อนที่ฉันจะอยู่ที่นี่scholar.google.co.uk/ ......นอกจากนี้ยังมีคำอธิบายสั้น ๆ เกี่ยวกับบล็อกของฉันrgrig.blogspot.co.uk/2008/12/array -puzzle-solution.html
rgrig

@uli: นี่เป็นคำถามที่เพาะผมจริง ๆ แล้วอ่านมานานแล้ว
Aryabhata

@ ราฟาเอล: มันยังคงน่าแปลกใจเมื่อคุณได้ยินเกี่ยวกับสิ่งนี้เป็นครั้งแรก ความขัดแย้งส่วนใหญ่ไม่ใช่ :-)
Aryabhata

คำตอบ:


15

นี่เป็นกลอุบายทั่วไปที่สามารถใช้เพื่อวัตถุประสงค์อื่นได้ ด้านล่างฉันให้การใช้งาน (ในรหัสเทียม)

ให้เวกเตอร์ที่สามตัวคือ A , PและV ที่มีขนาดnแต่ละอัน เราจะใช้สิ่งเหล่านี้เพื่อดำเนินการตามที่ร้องขอโดยโครงสร้างข้อมูลของเรา นอกจากนี้เรายังรักษาตัวแปรP o s การดำเนินการจะดำเนินการดังต่อไปนี้:APVnpos

init:
  pos <- 0

set(i,x):
if not(V[i] < pos and P[V[i]] = i) 
  V[i] <- pos, P[pos] <- i, pos <- pos + 1
A[i] <- x

get(i):
if (V[i] < pos and P[V[i]] = i) 
  return A[i] 
else 
  return empty 

อาร์เรย์เพียงเก็บค่าที่ผ่านs อีทีขั้นตอน อาร์เรย์VและPทำงานเป็นใบรับรองที่สามารถบอกได้ว่าตำแหน่งที่กำหนดในAได้รับการเริ่มต้นแล้วหรือไม่AsetVPA

โปรดทราบว่าในทุกช่วงเวลาองค์ประกอบในตั้งแต่0ถึงp o s - 1จะเริ่มต้นได้ เราจึงสามารถใช้อย่างปลอดภัยค่าเหล่านี้เป็นใบรับรองสำหรับค่าที่เริ่มใน ทุกตำแหน่งฉันในที่ถูกเตรียมมีองค์ประกอบที่สอดคล้องกันในเวกเตอร์Pมีค่าเท่ากับฉัน นี้จะชี้ให้เห็นโดยV [ ผม ] ดังนั้นถ้าเราดูองค์ประกอบที่เกี่ยวข้องP [ V [ i ] ]และค่าของมันคือiP0pos1AiAPiV[i]P[V[i]]iเรารู้ว่าได้รับการเตรียมใช้งาน (ตั้งแต่Pไม่เคยโกหกเพราะองค์ประกอบทั้งหมดที่เรากำลังพิจารณาอยู่จะเริ่มต้นได้) ในทำนองเดียวกันถ้าA [ i ]ไม่ได้เริ่มต้นดังนั้นV [ i ]อาจชี้ไปที่ตำแหน่งในPนอกช่วง0 .. p o s - 1เมื่อเรารู้ว่ามันไม่ได้ถูกกำหนดค่าเริ่มต้นหรืออาจชี้ไปที่ ตำแหน่งในช่วงนั้น แต่P [ j ] นี้สอดคล้องกับตำแหน่งที่แตกต่างในAและดังนั้นA[i]PA[i]V[i]P0..pos1P[j]Aเพื่อให้เรารู้ว่า [ ผม]ไม่ได้รับการเริ่มต้นP[j]iA[i]

ง่ายที่จะเห็นว่าการดำเนินการทั้งหมดนี้เสร็จสิ้นในเวลาที่แน่นอน นอกจากนี้พื้นที่ที่ใช้คือสำหรับแต่ละเวกเตอร์และO ( 1 )สำหรับตัวแปรp o sดังนั้นO ( n )ทั้งหมดO(n)O(1)posO(n)


แต่มันไม่ได้เป็นไปได้ว่ามีโอกาสเท่ากับฉันโดยไม่ต้อง[ ผม]ได้เคยชุด? P[V[i]]iA[i]
Robert S. Barnes

มันเป็น แต่แล้ว pos จะเล็กกว่า V [i] ตอนนี้ใช่ไหม? สาเหตุมิฉะนั้นมันจะไม่เกิดขึ้นโดยบังเอิญ เนื่องจากการมี pos สูงกว่า V [i] หมายความว่าเราได้กำหนดค่าของ P ที่ index V [i] โดยเฉพาะให้เป็นค่าเฉพาะที่เราเลือกคือ i
wolfdawn

โปรดทราบว่านี่เป็นตัวอย่างคลาสสิกของสิ่งที่เป็นไปไม่ได้ที่จะทำใน (พกพา) C.
TLW
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.