牛客網 C 面試寶典 基礎知識(4)容器和演算法

2021-10-05 09:47:28 字數 4136 閱讀 1202

感覺牛客網的整理有丟丟凌亂

● 請你來說一下map和set有什麼區別,分別又是怎麼實現的?

map和set都是c++的關聯容器,其底層實現都是紅黑樹(rb-tree)。

map和set區別在於:

(2)set的迭代器是const的,不允許修改元素的值;map允許修改value,但不允許修改key。其原因是因為map和set是根據關鍵字排序來保證其有序性的,如果允許修改key的話,那麼首先需要刪除該鍵,然後調節平衡,再插入修改後的鍵值,調節平衡,如此一來,嚴重破壞了map和set的結構,導致iterator失效,不知道應該指向改變前的位置,還是指向改變後的位置。所以stl中將set的迭代器設定成const,不允許修改迭代器的值;而map的迭代器則不允許修改key值,允許修改value值。

(3)map支援下標操作,set不支援下標操作。map可以用key做下標,map的下標運算子[ ]將關鍵碼作為下標去執行查詢

(4)set適用:有序無重複的集合,map適用:有序鍵值對不重複的對映

● 請你來介紹一下stl的allocator參考

我不知道的東西太多了,,,

new將記憶體分配和物件構造組合在了一起,

delete將物件析構和記憶體釋放組合在了一起.

標準庫中allocator的類,允許我們將分配和初始化分離。使用allocator通常會提供更好的效能和更靈活的記憶體管理能力。

stl allocator將兩個階段操作區分開來:記憶體配置有allocate()負責,記憶體釋放由deallocate()負責;

物件構造由construct()負責,物件析構由destroy()負責。

● 請你來說一說stl迭代器刪除元素

參考1參考2

1.對於序列容器vector,deque來說,刪除當前的iterator會使後面所有元素的iterator都失效。這是因為vector,deque使用了連續分配的記憶體,刪除乙個元素導致後面所有的元素會向前移動乙個位置。不過erase方法可以返回下乙個有效的iterator。

2.對於關聯容器map set來說,使用了erase(iterator)後,當前元素的迭代器失效,但是其結構是紅黑樹,刪除當前元素的,不會影響到下乙個元素的迭代器,只要在erase時,遞增當前的iterator即可。

3.對於list來說,它使用了不連續分配的記憶體,並且它的erase方法也會返回下乙個有效的iterator,因此上面兩種正確的方法都可以使用。

list是由雙向鍊錶實現的,因此記憶體空間是不連續的。

● 請你說一說stl中map資料存放形式參考

map: map內部實現了乙個紅黑樹(紅黑樹是非嚴格平衡二叉搜尋樹),紅黑樹具有自動排序的功能,因此map內部的所有元素都是有序的,紅黑樹的每乙個節點都代表著map的乙個元素。因此,對於map進行的查詢,刪除,新增等一系列的操作都相當於是對紅黑樹進行的操作。map中的元素是按照二叉搜尋樹儲存的,使用中序遍歷可將鍵值按照從小到大遍歷出來。

unordered_map: unordered_map內部實現了乙個雜湊表,因此其查詢速度非常的快(也叫雜湊表,通過把關鍵碼值對映到hash表中乙個位置來訪問記錄,查詢的時間複雜度可達到o(1),其在海量資料處理中有著廣泛應用)。因此,其元素的排列順序是無序的。

● 請你講講stl有什麼基本組成

stl主要由:以下幾部分組成:

容器、迭代器、仿函式、演算法、分配器、介面卡

分配器給容器分配儲存空間

演算法通過迭代器獲取容器中的內容

仿函式可以協助演算法完成各種操作

介面卡是用來修改其他元件介面的stl元件

● 請你說說stl中map與unordered_map

● 請你說一說vector和list的區別,應用,越詳細越好

參考

區別vector

list

底層結構

動態順序表——陣列,在記憶體中是一段連續的空間。

雙向鍊錶,在記憶體中不是一段連續的空間

隨機訪問

vector支援隨機訪問,可以利用下標精準定位到乙個元素上,訪問某個元素的時間複雜度是o(1)。

list不支援隨機訪問,時間複雜度是o(n)。

插入vector一次性分配好記憶體,不夠時才進行2倍擴容

考慮插入的位置和是否擴容

在新增資料的時候,就要分配一塊更大的記憶體,vector是以2倍的方式擴容的,將原來的資料複製過來,釋放之前的記憶體,在插入新增的元素;

list每次插入新節點都會進行記憶體申請。

不需要搬移元素,只需要改變插入或刪除位置的前後兩個節點的指向即可,時間複雜度為o(1)。

刪除考慮刪除的位置——記憶體拷貝

不需要搬移元素,只需要改變插入或刪除位置的前後兩個節點的指向即可,時間複雜度為o(1)。

● 請你來說一下stl中迭代器的作用,有指標為何還要迭代器

1、迭代器

iterator(迭代器)用於提供一種方法順序訪問乙個聚合物件中各個元素, 而又不需暴露該物件的內部表示。或者這樣說可能更容易理解:iterator模式是運用於聚合物件的一種模式,通過運用該模式,使得我們可以在不知道物件內部表示的情況下,按照一定順序(由iterator提供的方法)訪問聚合物件中的各個元素。

2、迭代器和指標的區別

迭代器不是指標,是類模板,表現的像指標。他只是模擬了指標的一些功能,通過過載了指標的一些操作符,->、*、++、--等。

迭代器封裝了指標,是乙個可遍歷stl( standard template library)容器內全部或部分元素」的物件

迭代器返回的是物件引用而不是物件的值,所以cout只能輸出迭代器使用*取值後的值而不能直接輸出其自身。

● 請你說一說epoll原理

linux完全的知識盲區,,,參考

1. epoll_create:建立乙個epoll物件(在epoll檔案系統中給這個控制代碼分配資源);

2. 呼叫epoll_ctl:可以向epoll控制代碼新增或者刪除要監聽的檔案控制代碼

3.epoll_wait:等待事件發生了

● n個整數的無序陣列,找到每個元素後面比它大的第乙個數,要求時間複雜度為o(n)

參考 需要借用乙個棧stack

vectorfunc(vectornum){

if(num.size()==0) return num;

vectorres(num.size());

stacks;

int i=0;

while(i● 請你回答一下stl裡resize和reserve的區別參考

resize():改變當前容器內含有元素的數量

eg: vectorv; v.resize(len);v的size變為len,如果原來v的size小於len,那麼容器新增(len-size)個元素,元素的值為預設為0.當v.push_back(3);之後,則是3是放在了v的末尾,即下標為len,此時容器是size為len+1;

reserve():改變當前容器的最大容量,它不會生成元素,只是確定這個容器允許放入多少物件如果reserve(len)的值大於當前的capacity(),那麼會重新分配一塊能存len個物件的空間,然後把之前v.size()個物件通過copy construtor複製過來,銷毀之前的記憶體;

牛客網 C 面試寶典 基礎知識(3)

如果同時定義了兩個函式,乙個帶const,乙個不帶,會有問題嗎?不會,這相當於函式的過載。請你來說一說隱式型別轉換參考 對於內建型別,低精度的變數給高精度變數賦值會發生隱式型別轉換 可以用單個形參來呼叫 的建構函式定義了從 形參型別 到 該類型別 的乙個隱式轉換。說說你了解的型別轉換 const c...

C 面試寶典 C 基礎知識

1.c 和c的區別 設計思想上 c 是物件導向的語言,而c是面向過程的結構化程式設計語言 語法上 c 具有封裝 繼承 多型三種特性 c 相比於c,增加多許多態別安全的功能,比如強制轉換 c 支援正規化,比如模板類 函式模板等 2.野指標是什麼?3.說一下static關鍵字的作用?1.全域性靜態變數 ...

牛客網 C 面試寶典 作業系統(2)

1 互斥鎖和讀寫鎖區別 互斥鎖 mutex,用於保證在任何時刻,都只能有乙個執行緒訪問該物件。當獲取鎖操作失敗時,執行緒會進入睡眠,等待鎖釋放時被喚醒。讀寫鎖 rwlock,分為讀鎖和寫鎖。處於讀操作時,可以允許多個執行緒同時獲得讀操作。但是同一時刻只能有乙個執行緒可以獲得寫鎖。其它獲取寫鎖失敗的執...