問:請使用 LinkedList 模擬一個堆?;蜿犃械臄?shù)據(jù)結(jié)構(gòu)?
答:首先堆棧是先進后出,隊列是先進先出,LinkedList 不但實現(xiàn)了 List 接口還實現(xiàn)了 Deque 雙端隊列接口,接著給出實現(xiàn)如下。
public class Queue {
private LinkedList link;
public Queue() {
link = new LinkedList();
}
public void push(Object obj) {
link.addLast(obj);
}
public Object pop() {
return link.removeFirst(); //隊列
// return link.removeLast(); //堆棧
}
public boolean isEmpty() {
return link.isEmpty();
}
}
問:談?wù)勀憷斫獾?LinkedList 工作原理和實現(xiàn)?
答:LinkedList 是以雙向鏈表實現(xiàn),鏈表無容量限制(但是雙向鏈表本身需要消耗額外的鏈表指針空間來操作),其內(nèi)部主要成員為 first 和 last 兩個 Node 節(jié)點,在每次修改列表時用來指引當前雙向鏈表的首尾部位,所以 LinkedList 不僅僅實現(xiàn)了 List 接口,還實現(xiàn)了 Deque 雙端隊列接口(該接口是 Queue 隊列的子接口),故 LinkedList 自動具備雙端隊列的特性,當我們使用下標方式調(diào)用列表的 get(index)、set(index, e) 方法時需要遍歷鏈表將指針移動到位進行訪問(會判斷 index 是否大于鏈表長度的一半決定是首部遍歷還是尾部遍歷,訪問的復(fù)雜度為 O(N/2)),無法像 ArrayList 那樣進行隨機訪問。(如果 i> 數(shù)組大小的一半,會從末尾移起),只有在鏈表兩頭的操作(譬如 add()、addFirst()、removeLast() 或用在 iterator() 上的 remove() 操作)才不需要進行遍歷尋找定位。
問:簡單談?wù)?ArrayList、LinkedList、List 的區(qū)別?
答:List 是集合列表接口,ArrayList 和 LinkedList 都是 List 接口的實現(xiàn)類。ArrayList 是動態(tài)數(shù)組順序表,順序表的存儲地址是連續(xù)的,所以查找比較快,但是插入和刪除時由于需要把其它的元素順序移動,所以比較耗時。LinkedList 是雙向鏈表的數(shù)據(jù)結(jié)構(gòu),同時實現(xiàn)了雙端隊列 Deque 接口,鏈表節(jié)點的存儲地址是不連續(xù)的,每個存儲地址通過指針關(guān)聯(lián),在查找時需要進行指針遍歷節(jié)點,所以查找比較慢,而在插入和刪除時比較快。