1. 程式人生 > >C++ std::vector中push_back操作空間溢位

C++ std::vector中push_back操作空間溢位


今天在做leetcode 705、706時候遇到一個錯誤。
題連結:https://leetcode.com/problems/design-hashmap/description/

  • [817] Design HashMap * *
    https://leetcode.com/problems/design-hashmap/description/ * *
    algorithms * Easy (48.96%) * Total Accepted: 9.2K * Total
    Submissions: 18.8K * Testcase Example:
    ‘[“MyHashMap”,“put”,“put”,“get”,“get”,“put”,“get”, “remove”,
    “get”]\n[[],[1,1],[2,2],[1],[3],[2,1],[2],[2],[2]]’ * * Design a
    HashMap without using any built-in hash table libraries. * * To be
    specific, your design should include these functions: * * *
    put(key, value) : Insert a (key, value) pair into the HashMap. If the
    value * already exists in the HashMap, update the value. * get(key):
    Returns the value to which the specified key is mapped, or -1 if *
    this map contains no mapping for the key. * remove(key) : Remove the
    mapping for the value key if this map contains the * mapping for the
    key. * * * * Example: * * * MyHashMap hashMap = new
    MyHashMap(); * hashMap.put(1, 1); * hashMap.put(2, 2);
  • hashMap.get(1); // returns 1 * hashMap.get(3); // returns -1 (not found) * hashMap.put(2, 1); // update the
    existing value * hashMap.get(2); // returns 1 *
    hashMap.remove(2); // remove the mapping for 2 *
    hashMap.get(2); // returns -1 (not found) * * * *
    Note: * * * All keys and values will be in the range of [0,
    1000000]. * The number of operations will be in the range of [1,
    10000]. * Please do not use the built-in HashMap library.

題目要求實現一個hash表
在實現過程中使用了vector<int>進行模擬,但是令人想不到的是不是時間超時,而是空間溢位。QAQ???納尼?
程式碼:

class MyHashMap {
    private:
    vector<int>m;
public:
    /** Initialize your data structure here. */
    MyHashMap() {
        for(int i=0;i<=1000000;i++)
        {
            m.push_back(-1);
        }
} /** value will always be non-negative. */ void put(int key, int value) { m[key]=value; } /** Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key */ int get(int key) { return m[key]; } /** Removes the mapping of the specified value key if this map contains a mapping for the key */ void remove(int key) { m[key]=-1; } }; /** * Your MyHashMap object will be instantiated and called as such: * MyHashMap obj = new MyHashMap(); * obj.put(key,value); * int param_2 = obj.get(key); * obj.remove(key); */


額好吧,到底怎麼回事呢?QAQ


以下引自:https://blog.csdn.net/u011417820/article/details/79959825

我們在使用 vector 時​,最常使用的操作恐怕就是插入操作了(push_back),那麼當執行該操作時,該函式都做了哪些工作呢?

該函式首先檢查是否還有備用空間,如果有就直接在備用空間上構造元素,並調整迭代器 finish,使
vector變大。如果沒有備用空間了,就擴充空間,重新配置、移動資料,釋放原空間。​

其中​判斷是否有備用空間,就是判斷 finish是否與 end_of_storage 相等.如果

finish != end_of_storage,說明還有備用空間,否則已無備用空間。

當執行 push_back 操作,該 vector 需要分配更多空間時,它的容量(capacity)會增大到原來的 m
倍。​現在我們來均攤分析方法來計算 push_back 操作的時間複雜度。

假定有 n 個元素,倍增因子為 m。那麼完成這 n 個元素往一個 vector 中的push_back​操作,需要重新分配記憶體的次數大約為
logm(n),第 i 次重新分配將會導致複製 m^i (也就是當前的vector.size() 大小)箇舊空間中元素,因此 n 次
push_back操作所花費的總時間約為 n*m/(m - 1):

也就是說push_back會檢查記憶體空間是不是夠用(有沒有備用空間),如果不夠用,則從最後一個元素開始開闢空間。

在這裡插入圖片描述


程式碼修改過後!

class MyHashMap
{
  private:
    vector<int> m;

  public:
    /** Initialize your data structure here. */
    MyHashMap()
    {
        m = std::vector<int>(1000001, -1);
    }

    /** value will always be non-negative. */
    void put(int key, int value)
    {
        m[key] = value;
    }

    /** Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key */
    int get(int key)
    {
        return m[key];
    }

    /** Removes the mapping of the specified value key if this map contains a mapping for the key */
    void remove(int key)
    {
        m[key] = -1;
    }
};

/**
 * Your MyHashMap object will be instantiated and called as such:
 * MyHashMap obj = new MyHashMap();
 * obj.put(key,value);
 * int param_2 = obj.get(key);
 * obj.remove(key);
 */

在這裡插入圖片描述
AC。