ประสิทธิภาพของพจนานุกรม C #


14

พจนานุกรม C # เป็นวิธีที่ง่ายในการค้นหาว่ามีบางอย่างมีอยู่ ฯลฯ ฉันมีคำถามว่าพวกเขาทำงานอย่างไร สมมุติว่าฉันใช้ ArrayList แทนพจนานุกรม แทนที่จะใช้ContainsKey(หรือวิธีที่เทียบเท่าในภาษาอื่น) ฉันวนลูป ArrayList เพื่อตรวจสอบว่ามีบางสิ่งอยู่ที่นั่น (หรือทำการค้นหาแบบไบนารีถ้าข้อมูลเรียงลำดับหรือคล้ายกัน) ประสิทธิภาพแตกต่างกันอย่างไร เป็นContainsKeyวิธีการที่ใช้บางส่วนวิธีที่มีประสิทธิภาพมากกว่าการวนลูปผ่านปุ่มและตรวจสอบว่าสิ่งที่ฉันค้นหาอยู่?

ถ้าสมมติว่าฉันได้สร้างฟังก์ชันแฮชเฉพาะซึ่งสอดคล้องกับประเภทของข้อมูลที่ฉันมีและได้รับการออกแบบมาโดยเฉพาะสำหรับชุดข้อมูลนั้นใช่แล้วฟังก์ชันแฮชนั้นเร็วกว่าการวนลูปผ่านข้อมูล แต่พจนานุกรมทั่วไป เมธอด containKey นั้นไม่เฉพาะเจาะจงกับข้อมูลที่ได้รับ แต่เป็นวิธีการค้นหาทั่วไป

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


คุณกำลังเปรียบเทียบแอปเปิ้ลกับส้มที่นี่จริง ๆ ฉันคิดว่าคำหลักที่คุณกำลังมองหาคือData Structures ลิงค์ wiki นี้อาจช่วยคุณได้มากขึ้น
Ampt

คำตอบ:


23

คุณต้องขุดนิดหน่อยเพื่อดูว่าพจนานุกรมถูกนำไปใช้อย่างไรใน C # - มันไม่ชัดเจนเท่าHashMap (ตารางแฮช) หรือTreeMap (ต้นไม้เรียง) (หรือConcurrentSkipListMap - รายการข้าม )

หากคุณขุดลงในส่วน "ข้อสังเกต":

คลาส generic Dictionary จัดเตรียมการแม็พจากชุดของคีย์ไปยังชุดของค่า การเพิ่มในพจนานุกรมแต่ละรายการประกอบด้วยค่าและคีย์ที่เกี่ยวข้อง การดึงค่าโดยใช้คีย์ของมันนั้นรวดเร็วมากใกล้กับ O (1) เนื่องจากคลาส Dictionary ถูกใช้เป็นตารางแฮช

และที่นั่นเรามีมัน มันเป็นตารางแฮช โปรดทราบว่าฉันได้เชื่อมโยงบทความวิกิพีเดียไว้ที่นั่น - เป็นการอ่านที่ดี คุณอาจต้องการอ่านหัวข้อการแก้ไขการชน มันเป็นไปได้ที่จะได้รับชุดข้อมูลทางพยาธิวิทยาที่ devolves ค้นหาเพื่อ O (N) (ตัวอย่างเช่นทุกสิ่งที่คุณแทรกตรงกับค่าแฮเดียวกันหรือดัชนีในตารางแฮชด้วยเหตุผลบางอย่างและคุณจะเหลือเชิงเส้นละเอียด )

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

ในฐานะที่เป็นประสิทธิภาพของการค้นหาต่างๆ / มี?

  • การเดินรายการที่ไม่เรียงลำดับ: O (N)
  • การค้นหาแบบไบนารีของอาร์เรย์ที่เรียงลำดับ: O (บันทึก N)
  • ต้นไม้ที่เรียงลำดับ: O (บันทึก N)
  • ตารางแฮช: O (1)

สำหรับคนส่วนใหญ่ตารางแฮชเป็นสิ่งที่พวกเขาต้องการ

คุณอาจพบว่าSortedDictionaryเป็นสิ่งที่คุณต้องการแทน:

SortedDictionary<TKey, TValue>ระดับทั่วไปเป็นต้นไม้ค้นหาแบบทวิภาคกับ O (log n) การดึงที่ n คือจำนวนขององค์ประกอบในพจนานุกรม ในแง่นี้มันคล้ายกับSortedList<TKey, TValue>คลาสทั่วไป คลาสที่สองมีโมเดลวัตถุที่คล้ายกันและทั้งสองมีการดึงข้อมูล O (log n)

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

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


5
O (1) ไม่จำเป็นต้อง "เร็ว" การวนลูปในรายการอาจเร็วกว่า hashtable สำหรับขนาดคอลเลกชันที่แอปพลิเคชันกำลังเผชิญอยู่
whatsisname

5
@whatsisname ที่ไม่มีจุดฉันอ้างว่า O (1) เร็ว แน่นอนมันมีศักยภาพที่จะเป็นเร็วที่สุด การวนซ้ำคีย์ของ hashtable ช้ากว่าของ ArrayList (ยกเว้นว่าคุณกำลังใช้งานอย่างLinkedHashMapที่ Java มีให้) เป็นสิ่งสำคัญที่จะต้องทราบข้อมูลของคุณและวิธีการทำงานของมันและเลือกการเก็บรวบรวมที่เหมาะสมสำหรับข้อมูลนั้นและหากไม่มีอยู่ให้เขียน แน่นอนว่าความพยายามดังกล่าวคุ้มค่ากับเวลาจริง ๆ (ประวัติเป็นคนแรก!)

ใบเสนอราคาของคุณบอกว่า "การดึงค่าโดยใช้คีย์นั้นเร็วมากใกล้กับ O (1) เนื่องจากคลาสพจนานุกรมถูกใช้เป็นตารางแฮช" ดังนั้น OP อาจสับสนทั้งสองแนวคิด ในคำอื่น ๆ ฉันต้องการทำให้ชัดเจนว่า O ใหญ่ไม่ได้บอกเรื่องราวทั้งหมดเกี่ยวกับ "ความเร็ว"
whatsisname

3
@whatsisname ที่ส่งตรงจาก Microsoft การใช้คีย์เพื่อค้นหาค่ายกเว้นว่าคุณมี hashtable ทางพยาธิวิทยา (ซึ่งแก้ปัญหาการชนของแฮชด้วยกลไกอื่น) จะเร็วกว่าการค้นหาในต้นไม้หรือรายการที่เรียง (หรือรายการที่ไม่เรียงลำดับ) ตัวอย่างเช่น Java ใช้การวัดเชิงเส้น (ขั้นตอนที่ 1) สำหรับการแก้ปัญหาการชนกันของข้อมูลซึ่งอาจช้ากว่าในกรณีที่ตารางเต็มเกินไปหรือมีการชนกันมากเกินไป สำหรับกรณีทั่วไปมันดีพอ

เป็นตัวอย่างที่เกี่ยวข้องเมื่อเร็ว ๆ นี้ฉันปรับบางรหัสใน c ++ ซึ่งเดิมใช้ตารางแฮชสำหรับชุดข้อมูลประมาณ 20 รายการและใช้เวลาประมาณ 400ms ในการทำให้เสร็จสมบูรณ์ การสลับไปที่ต้นไม้ไบนารีนั้นนำมาซึ่งลงไปถึง 200ms เพราะต้นไม้นั้นเข้าถึงได้ง่ายกว่า แต่ฉันสามารถตัดต่อได้อีกโดยใช้อาร์เรย์ของชื่อค่าคู่และฟังก์ชั่นค้นหาแบบแก้ปัญหาซึ่งเดาได้ว่าจะเริ่มมองที่ใดโดยดูจากรูปแบบการเข้าถึงที่ผ่านมา ดังนั้นจึงเป็นเรื่องของจำนวนข้อมูลที่มีและรูปแบบชนิดใดที่มีอยู่ในการเข้าถึง (เช่นสถานที่)
จูลส์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.