ฉันมีคำถามเกี่ยวกับhash_map
และmap
ใน C ++ ฉันเข้าใจว่าmap
อยู่ใน STL แต่hash_map
ไม่ใช่มาตรฐาน อะไรคือความแตกต่างระหว่างทั้งสอง?
ฉันมีคำถามเกี่ยวกับhash_map
และmap
ใน C ++ ฉันเข้าใจว่าmap
อยู่ใน STL แต่hash_map
ไม่ใช่มาตรฐาน อะไรคือความแตกต่างระหว่างทั้งสอง?
คำตอบ:
มีการใช้งานในรูปแบบที่แตกต่างกันมาก
hash_map
( unordered_map
ใน TR1 และ Boost ใช้สิ่งเหล่านี้แทน) ใช้ตารางแฮชที่มีการแฮชคีย์ไปยังสล็อตในตารางและค่าจะถูกเก็บไว้ในรายการที่เชื่อมโยงกับคีย์นั้น
map
ถูกนำไปใช้เป็นต้นไม้ค้นหาไบนารีที่สมดุล (โดยปกติจะเป็นต้นไม้สีแดง / ดำ)
unordered_map
ควรจะให้ประสิทธิภาพที่ดีขึ้นเล็กน้อยสำหรับการเข้าถึงองค์ประกอบที่รู้จักกันของคอลเลกชัน แต่map
จะมีลักษณะที่เป็นประโยชน์เพิ่มเติม (เช่นมันจะถูกเก็บไว้ในเรียงลำดับซึ่งจะช่วยให้การสำรวจเส้นทางตั้งแต่ต้นจนจบ) unordered_map
จะเร็วกว่าในการแทรกและลบมากกว่าไฟล์map
.
hash_map
เป็นส่วนขยายทั่วไปที่มาจากการใช้งานไลบรารีจำนวนมาก นั่นคือเหตุผลว่าทำไมจึงถูกเปลี่ยนชื่อเป็นunordered_map
เมื่อเพิ่มลงในมาตรฐาน C ++ เป็นส่วนหนึ่งของ TR1 โดยทั่วไปแผนที่จะใช้กับต้นไม้ไบนารีที่สมดุลเช่นต้นไม้สีแดง - ดำ (การใช้งานแตกต่างกันไปแน่นอน) hash_map
และunordered_map
โดยทั่วไปจะใช้กับตารางแฮช ดังนั้นจึงไม่มีการรักษาคำสั่งซื้อ unordered_map
แทรก / ลบ / แบบสอบถามจะเป็น O (1) (เวลาคงที่) โดยที่แผนที่จะเป็น O (บันทึก n) โดยที่ n คือจำนวนรายการในโครงสร้างข้อมูล ดังนั้นจะเร็วขึ้นและถ้าคุณไม่สนใจเกี่ยวกับลำดับของรายการที่ควรจะต้องการมากกว่าunordered_map
map
บางครั้งคุณต้องการรักษาความสงบเรียบร้อย (เรียงลำดับโดยคีย์) และนั่นmap
จะเป็นทางเลือก
ความแตกต่างที่สำคัญบางประการอยู่ในข้อกำหนดด้านความซับซ้อน
map
ต้องใช้O(log(N))
เวลาสำหรับการแทรกและพบว่าการดำเนินงานที่มีการดำเนินการเป็นต้นไม้แดงดำโครงสร้างข้อมูล
unordered_map
ต้องใช้เวลาเฉลี่ยของO(1)
สำหรับใส่และพบ O(N)
แต่ได้รับอนุญาตให้มีช่วงเวลาที่เลวร้ายที่สุดกรณีของ เนื่องจากมีการใช้โครงสร้างข้อมูลHash Table
โดยปกติแล้วunordered_map
จะเร็วขึ้น แต่ขึ้นอยู่กับคีย์และฟังก์ชันแฮชที่คุณจัดเก็บอาจแย่ลงมาก
ข้อมูลจำเพาะ C ++ ไม่ได้บอกว่าคุณต้องใช้อัลกอริทึมอะไรสำหรับคอนเทนเนอร์ STL อย่างไรก็ตามมันมีข้อ จำกัด บางประการเกี่ยวกับประสิทธิภาพของมันซึ่งจะออกกฎการใช้ตารางแฮชสำหรับmap
และคอนเทนเนอร์ที่เชื่อมโยงอื่น ๆ (มักใช้กับต้นไม้สีแดง / ดำ) ข้อ จำกัด เหล่านี้ต้องการประสิทธิภาพในกรณีที่แย่ที่สุดที่ดีกว่าสำหรับคอนเทนเนอร์เหล่านี้มากกว่าที่ตารางแฮชจะสามารถส่งมอบได้
หลายคนต้องการตารางแฮชจริงๆดังนั้นคอนเทนเนอร์แบบเชื่อมโยง STL ที่ใช้แฮชจึงเป็นส่วนขยายที่ใช้กันทั่วไปมาหลายปีแล้ว ดังนั้นพวกเขาจึงเพิ่มunordered_map
มาตรฐาน C ++ ในเวอร์ชันที่ใหม่กว่า
map
โดยทั่วไปแล้ว btree ที่สมดุลนั้นเกิดจากการใช้operator<()
เป็นตัวกำหนดตำแหน่ง
map
ถูกนำมาใช้จากbalanced binary search tree
(โดยปกติ a rb_tree
) เนื่องจากสมาชิกทั้งหมดในbalanced binary search tree
ถูกจัดเรียงดังนั้นจึงเป็นแผนที่
hash_map
ถูกนำมาใช้จากhashtable
เนื่องจากสมาชิกทั้งหมดในhashtable
ไม่ถูกเรียงลำดับดังนั้นสมาชิกในhash_map(unordered_map)
จึงไม่ถูกจัดเรียง
hash_map
ไม่ใช่ไลบรารีมาตรฐาน c ++ แต่ตอนนี้เปลี่ยนชื่อเป็นunordered_map
(คุณสามารถคิดได้ว่าเปลี่ยนชื่อแล้ว) และกลายเป็นไลบรารีมาตรฐาน c ++ ตั้งแต่ c ++ 11 ดูคำถามนี้ความแตกต่างระหว่าง hash_map และ unordered_map? สำหรับรายละเอียดเพิ่มเติม
ด้านล่างฉันจะให้อินเทอร์เฟซหลักจากซอร์สโค้ดเกี่ยวกับวิธีการใช้งานแผนที่สองประเภท
โค้ดด้านล่างเป็นเพียงการแสดงให้เห็นว่าแผนที่เป็นเพียงส่วนห่อหุ้มของbalanced binary search tree
ฟังก์ชันเกือบทั้งหมดเป็นเพียงการเรียกใช้balanced binary search tree
ฟังก์ชัน
template <typename Key, typename Value, class Compare = std::less<Key>>
class map{
// used for rb_tree to sort
typedef Key key_type;
// rb_tree node value
typedef std::pair<key_type, value_type> value_type;
typedef Compare key_compare;
// as to map, Key is used for sort, Value used for store value
typedef rb_tree<key_type, value_type, key_compare> rep_type;
// the only member value of map (it's rb_tree)
rep_type t;
};
// one construct function
template<typename InputIterator>
map(InputIterator first, InputIterator last):t(Compare()){
// use rb_tree to insert value(just insert unique value)
t.insert_unique(first, last);
}
// insert function, just use tb_tree insert_unique function
//and only insert unique value
//rb_tree insertion time is : log(n)+rebalance
// so map's insertion time is also : log(n)+rebalance
typedef typename rep_type::const_iterator iterator;
std::pair<iterator, bool> insert(const value_type& v){
return t.insert_unique(v);
};
hash_map
:hash_map
ถูกนำมาใช้จากhashtable
โครงสร้างที่มีลักษณะดังนี้:
ในโค้ดข้างล่างนี้ฉันจะให้ส่วนหลักของแล้วให้hashtable
hash_map
// used for node list
template<typename T>
struct __hashtable_node{
T val;
__hashtable_node* next;
};
template<typename Key, typename Value, typename HashFun>
class hashtable{
public:
typedef size_t size_type;
typedef HashFun hasher;
typedef Value value_type;
typedef Key key_type;
public:
typedef __hashtable_node<value_type> node;
// member data is buckets array(node* array)
std::vector<node*> buckets;
size_type num_elements;
public:
// insert only unique value
std::pair<iterator, bool> insert_unique(const value_type& obj);
};
เช่นเดียวกับmap's
สมาชิกเท่านั้นคือrb_tree
ที่สมาชิกเพียงอย่างเดียวคือhash_map's
hashtable
เป็นรหัสหลักด้านล่าง:
template<typename Key, typename Value, class HashFun = std::hash<Key>>
class hash_map{
private:
typedef hashtable<Key, Value, HashFun> ht;
// member data is hash_table
ht rep;
public:
// 100 buckets by default
// it may not be 100(in this just for simplify)
hash_map():rep(100){};
// like the above map's insert function just invoke rb_tree unique function
// hash_map, insert function just invoke hashtable's unique insert function
std::pair<iterator, bool> insert(const Value& v){
return t.insert_unique(v);
};
};
ภาพด้านล่างนี้แสดงเมื่อ hash_map มี 53 ที่เก็บข้อมูลและแทรกค่าบางอย่างซึ่งเป็นโครงสร้างภายใน
ภาพด้านล่างแสดงความแตกต่างระหว่าง map และ hash_map (unordered_map) ภาพมาจากHow to choose between map and unordered_map? :
ฉันไม่รู้ว่าอะไรให้ แต่ hash_map ใช้เวลามากกว่า 20 วินาทีในการล้าง () 150K คีย์จำนวนเต็มและค่าลอย ฉันแค่วิ่งและอ่านรหัสของคนอื่น
นี่คือวิธีการรวม hash_map
#include "StdAfx.h"
#include <hash_map>
ฉันอ่านที่นี่ https://bytes.com/topic/c/answers/570079-perfomance-clear-vs-swap
บอกว่า clear () เป็นลำดับของ O (N) สำหรับฉันแล้วมันแปลกมาก แต่นั่นคือวิธีที่เป็นอยู่