我正在研究Straustrup的hash_map实现。这将直截了当地说明他是如何实施的
template<class Key, class T, class H = Hash<Key>, class EQ = equal_to<Key>, class A = allocator<T> >
class hash_map
{
private: // representation
struct Entry {
key_type key;
mapped_type val;
Entry* next; // hash overflow link
bool erased;
Entry(key_type k, mapped_type v, Entry* n)
: key(k), val(v), next(n), erased(false) { }
};
vector<Entry> v; // the actual entries
vector<Entry*> b; // the hash table: pointers into v
// ...
private:
float max_load; // keep v.size()<=b.size()*max_load
float grow; // when necessary, resize(bucket_count()*grow)
size_type no_of_erased; // number of entries in v occupied by erased elements
Hasher hash; // hash function
key_equal eq; // equality
const T default_value; // default value used by []
};
这是operator []
的实现template<class Key, class T, class H = Hash<Key>, class EQ = equal_to<Key>, class A = allocator<T> >
mapped_type& hash_map::operator[](const key_type& k)
{
size_type i = hash(k)%b.size(); // hash
for(Entry* p = b[i]; p; p = p->next) // search among entries hashed to i
if (eq(k,p->key)) { // found
if (p->erased) { // re-insert
p->erased = false;
no_of_erased--;
return p->val = default_value;
}
return p->val;
}
// not found:
if (b.size()*max_load < v.size()) { // if ‘‘too full’’
resize(b.size()*grow); // grow
return operator[](k); // rehash
}
v.push_back(Entry(k,default_value,b[i])); // add Entry
b[i] = &v.back(); // point to new element
return b[i]->val;
}
所以,让我们想象有3个元素映射到散列i
,但它们都不对应新密钥k
,那么我们应该在列表中添加另一个条目{{ 1}},对吗?相反,代码会在b[i]
向量中创建另一个Entry
,并将v
替换为该条目的地址(从而丢失旧的3个条目)。
我是否遗漏了某些内容,或者确实存在问题?
P.S。我正在研究&#34; C ++编程语言&#34;作者:Bjarne Straustrup,第三版。该功能在第500页。
答案 0 :(得分:2)
哈希条目形成链表。插入新条目时,它将被赋予条目列表的前一个头部(可能为null):
Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Index: 62523, Size: 7524
at java.util.ArrayList.rangeCheck(ArrayList.java:653)
at java.util.ArrayList.get(ArrayList.java:429)
at GoodsView$GoodsViewTableModel.getPosition(Main.java:205)
at GoodsView$GoodsViewTableModel.getValueAt(Main.java:178)
at javax.swing.table.TableRowSorter$TableRowSorterModelWrapper.getValueAt(TableRowSorter.java:269)
at javax.swing.DefaultRowSorter.compare(DefaultRowSorter.java:955)
at javax.swing.DefaultRowSorter.access$100(DefaultRowSorter.java:112)
at javax.swing.DefaultRowSorter$Row.compareTo(DefaultRowSorter.java:1376)
at javax.swing.DefaultRowSorter$Row.compareTo(DefaultRowSorter.java:1366)
at java.util.Arrays.binarySearch0(Arrays.java:2439)
at java.util.Arrays.binarySearch(Arrays.java:2379)
at javax.swing.DefaultRowSorter.insertInOrder(DefaultRowSorter.java:1000)
at javax.swing.DefaultRowSorter.rowsInserted0(DefaultRowSorter.java:1058)
at javax.swing.DefaultRowSorter.rowsInserted(DefaultRowSorter.java:868)
at javax.swing.JTable.notifySorter(JTable.java:4270)
at javax.swing.JTable.sortedTableChanged(JTable.java:4118)
at javax.swing.JTable.tableChanged(JTable.java:4395)
at javax.swing.table.AbstractTableModel.fireTableChanged(AbstractTableModel.java:296)
at javax.swing.table.AbstractTableModel.fireTableRowsInserted(AbstractTableModel.java:231)
at GoodsView$GoodsViewTableModel.addPositions(Main.java:215)
at GoodsView$2.process(Main.java:113)
at javax.swing.SwingWorker$3.run(SwingWorker.java:414)
at sun.swing.AccumulativeRunnable.run(AccumulativeRunnable.java:112)
at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.run(SwingWorker.java:832)
at sun.swing.AccumulativeRunnable.run(AccumulativeRunnable.java:112)
at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.actionPerformed(SwingWorker.java:842)
at javax.swing.Timer.fireActionPerformed(Timer.java:313)
at javax.swing.Timer$DoPostEvent.run(Timer.java:245)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.swing.DefaultRowSorter.getViewToModelAsInts(DefaultRowSorter.java:742)
at javax.swing.DefaultRowSorter.sort(DefaultRowSorter.java:572)
at javax.swing.DefaultRowSorter.shouldOptimizeChange(DefaultRowSorter.java:1025)
at javax.swing.DefaultRowSorter.rowsInserted(DefaultRowSorter.java:867)
at javax.swing.JTable.notifySorter(JTable.java:4270)
at javax.swing.JTable.sortedTableChanged(JTable.java:4118)
at javax.swing.JTable.tableChanged(JTable.java:4395)
at javax.swing.table.AbstractTableModel.fireTableChanged(AbstractTableModel.java:296)
at javax.swing.table.AbstractTableModel.fireTableRowsInserted(AbstractTableModel.java:231)
at GoodsView$GoodsViewTableModel.addPositions(Main.java:215)
at GoodsView$2.process(Main.java:113)
at javax.swing.SwingWorker$3.run(SwingWorker.java:414)
at sun.swing.AccumulativeRunnable.run(AccumulativeRunnable.java:112)
at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.run(SwingWorker.java:832)
at sun.swing.AccumulativeRunnable.run(AccumulativeRunnable.java:112)
at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.actionPerformed(SwingWorker.java:842)
at javax.swing.Timer.fireActionPerformed(Timer.java:313)
at javax.swing.Timer$DoPostEvent.run(Timer.java:245)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
请参阅那里的v.push_back(Entry(k,default_value,b[i])); // add Entry
然后在b[i]
字段中创建该条目的链接。然后,我们移动列表next
的头部以指向新条目;
b[i]