1. 程式人生 > >資料結構與演算法(2)- vector概念介紹

資料結構與演算法(2)- vector概念介紹

宣告:雖然本系列部落格與具體的程式語言無關。但是本文作者對c++相對比較熟悉,其次是java,所以難免會有視角上的偏差。舉例也大多是和這兩門語言相關。

Vector的出現主要是為了解決陣列的靜態空間的問題。所謂靜態空間指的是一旦配置就不能改變。當然如果你硬要重新配置也是可以的,自己重新申請一塊空間,然後把資料搬過去。而vector是動態空間,它的內部機制會自行擴充空間以容納新元素。 可以用水桶裝水的例子來示意的感性認識一下。如圖1所示,不斷向水桶中裝水,那麼裝滿了之後怎麼辦呢。如果是陣列的做法,那麼就需要自己搬一個更大的桶,把水裝進去。而如果是,vector的做法,那麼桶就可以自己隨著水的增多而變大哦。而且是水剛要滿時,水桶就自動變大。C++ vector自動增大至兩倍的容量。陣列的做法與vector的做法分別如圖2和圖3。

圖1 裝水
圖2 裝水-array

 

圖3 裝水-vector

那麼問題來了,怎麼能實現這種容量自增長呢,或者能夠從外部看上去是自增長呢?這時候就體現出面向物件的好處了我們可以構建一個類出來,這個類呢能夠幫助我們監測物件的容量,容量不夠的時候就自增容量至兩倍。這是容易做到的。可以通過一個私有的變數size就可以做到,每次先新增一個元素就增加1。當size與當前的容量一樣大的時候就擴容,並將資料拷貝到新的容器中,然後該釋放舊空間就釋放之類的。因為類的封裝,我們看不到這些內容,從外部看上去就實現了這種自增長容量的容器了。但是其原理必定也需要新構造一個空間出來。

圖4 vector


接來下介紹兩個概念:size,capacity。Begin和end之間的大小就是size,也就是當前的使用容量,可以理解成當前的水位;而capacity是當前所申請的空間大小,可以理解為水桶的容量。那麼當size==capacity的時候,就要capacity=capacity*2+1就可以了。當然實際操作起來並不是這麼簡單,不能把capacity*2+1就不管了,因為capacity也只是一個私有成員變數而已,咱們可不能自欺欺人。要做到實際建立這麼大的空間就需要空間分配啊,元素的搬移啊,實操起來還是比較麻煩的。這部分內容可參考《STL原始碼剖析》4.2小節。另外一個問題是,如果我們不斷放水,當水量小到一定程度是,是不是大桶就是一種資源的浪費了呢?對應到程式上來就是空間的浪費。這時候可以換個小桶。那麼換多小的桶呢,一個自然的想法是1/2大小的,這樣與自增的大小就對應起來了。實際上在某些輸入情況下這是會產生效能問題的。比如在資料size 為1/2capacity時不斷插入然後刪除,那麼就會不停的換大桶小桶。在C++ stl中,選用1/4大小。

小祕密:下一篇將講解C++中的vector以及java中的vector與arrayList。

See you next time. Happy Coding!!!

我的GitHub