【整理自用】一些數據結構題目、思路

Vector動態實現

思想:

  1. vector在定義時預留了一部分內存空間來用於存儲新增的元素。
  2. 當添加元素時,如果vector空間大小不足,則會以原大小的兩倍另外配置一塊較大的新空間,然後將原空間內容拷貝過來,在新空間的內容末尾添加元素,並釋放原空間。
  3. vector的空間動態增加大小,並不是在原空間之後的相鄰地址增加新空間,因爲vector的空間是線性連續分配的,不能保證原空間之後有可供配置的空間。因此,對vector的任何操作,一旦引起空間的重新配置,指向原vector的所有迭代器就會失效。

部分可借鑑的代碼:
建立動態數組時使用模板類:

template<typename T>  
class Vector{  
public:  
//構造函數,複製構造函數以及析構函數  
Vector(int size=0):theSize(size),theCapacity(0+5)
{  
    objects=new T[theCapacity];  
}  
Vector(const Vector& rhs):objects(NULL)
{  
    operator=(rhs);  
}  
~Vector()
{  
    delete[] objects;  
}  

// 重載=號操作符  
const Vector& operator=(const Vector& rhs)
{  
    theCapacity=rhs.theCapacity;  
    theSize=rhs.theSize;  
    objects=new objects[this->theCapacity];  
    for(int i=0;i<this->theSize;i++)  
    objects[i]=rhs.objects[i];  
    return *this;  
}  

//內存空間不足時,以原大小的兩倍另外配置一塊較大的新空間。
//然後將原空間內容拷貝過來,在新空間的內容末尾添加元素,並釋放原空間。
void resize(int newSize)
{  
    if(newSize>theCapacity)  
        reserve(newSize*2+1);  
    theSize=newSize;  
}  
//調整預留的空間,也就是實際上申請的內存的大小  
void reserve(int newCapacity)
{  
    if(newCapacity<theSize)  
        return;  
    T* oldObject=objects;  
    objects=new T[newCapacity];  
    theCapacity=newCapacity;  
    for(int i=0;i<theSize;i++)  
        objects[i]=oldObject[i];  
    delete objects;  
}  

//重載[]操作符  
T& operator[](int index)
{  
    return *(objects+index);  
}  
//成員常數函數
const T& operator[](int index)const
{  
    return *(objects+index);  
}   

//幾個get函數,均爲const成員,保證const對象也能調用  
bool isEmpty() const
{  
    return getSize()==0;  
}  
int capacity() const
{  
    return theCapacity;  
}  
int size() const
{  
    return theSize;  
}  

//push和pop操作  
void push_back(T t)
{  
    if(theSize==theCapacity)  
        reserve(theCapacity*2+1);  
    objects[theSize++]=t;  
}  
void pop_back()
{  
    theSize--;  
}  
T& back()
{  
    return objects[theSize-1];  
}  
const T& back()const
{  
    return objects[theSize-1];  
}  

// 迭代器  
typedef T* iterater;  
typedef const T* const_iterater;  

//begin end 等操作  
iterater begin()
{  
    return objects;  
}  
const_iterater begin() const
{  
    return objects;  
}  
iterater end()
{  
    return (objects+theSize);  
}  
const_iterater end() const
{  
    return (objects+theSize);  
}   
private:  
    T* objects;  
    int theSize;  
    int theCapacity;  
}

哈希表

在有網絡的情況下,可以看以下幾篇文章,相對淺顯易懂講述了關於哈希表的知識:
1. 淺談算法和數據結構(11):哈希表
2. 爲什麼哈希表能夠加快查找效率?
3. 哈希函數以及衝突解決常見方法
4. 舉例子說明

下面是簡單理解,具體還是需要看上述整理的工具書:
哈希表就是一種鍵-值(key-indexed)對應存儲數據的結構(類似map,我們只要輸入待查找的值即key,即可查找到其對應的值。

哈希的思路:
如果所有的鍵都是整數,那麼就可以使用一個簡單的無序數組來實現:將鍵作爲索引,值即爲其對應的值,這樣就可以快速訪問任意鍵的值。這是對於簡單的鍵的情況,我們將其擴展到可以處理更加複雜的類型的鍵。

哈希查找步驟:
1. 使用哈希函數將被查找的鍵轉換爲數組的索引。理想的情況下,不同的鍵會被轉換爲不同的索引值,但是有些情況下我們需要處理多個鍵被哈希到同一個索引值的情況。
2. 處理哈希碰撞衝突。

哈希函數
哈希函數的構造方法很多,最好的情況是:關鍵字經過哈希函數得到一個隨機的地址,以便使一組關鍵字的哈希地址均勻分佈在整個地址空間中,從而減少衝突。通常若所給關鍵字不是自然數,將其轉換爲自然數。
衝突解決
當產生衝突時,進行二次計算。如:直接定址法建立一個數組,當哈希函數計算不同鍵對應於同一地址時,線性順延查找到空位爲止。
查找效率
由於查找關鍵字對應值的時候,是可以通過預先設計的哈希函數計算找到對應地址的,因此查找的效率可以達到O(1)。即使存在哈希碰撞,由於也是可以通過計算或者預先定義的線性表長度二次計算找到,相較於直接查找效率已經是大幅提高了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章