大家好,今天和大家分享一個自定義隊列的實現,這也是很多面試中,容易問到,或者直接讓大家寫的一個題目。圍繞這個題目,那麼我們首先需要分析如何實現,那就要結合隊列的特點。隊列這種數據結構的特點我想大家肯定隨口都能說得出來,那就是“先進先出” 。 那麼我們如何設計一個先進先出的數據結構呢,首先能夠確定的是,它屬於一個線性結構,那麼線性結構的實現,其實我們可用的選擇就比較多,比如數組, 比如鏈表。 在這兩個的基礎上,再來想如何設計一個隊列,隊列的話,無外乎兩種常用的操作,一個是入隊,一個是出隊。 既然是先進先出的,那麼入隊的時候,肯定要把元素放到集合的末尾,同理,出隊的時候,要把集合的頭部(也就是第一個元素) 返回。所以明確了這樣的需求,實現起來就好辦了,同時我們還可以維護一個隊列的長度。
那如果使用數組實現的話,我們就實現設置一個數組對象作爲成員變量,而數組的長度我們可以設置一個隨機值,當然可以通過構造方法的方式,傳進來在初始化數組的長度。那如果進隊的時候 , 我們只需要把數組的最後一個元素設置爲傳進來的數據即可。而使用數組最麻煩的就是出隊,因爲出隊的時候我們需要返回第一個元素, 但是需要注意的是,出隊的時候,我們需要把出隊的元素移除掉,所以當我們把數組第一個元素移除掉的時候,隊列不可一日無頭, 所以可能我們需要把從第二個元素到最後一個元素都向前移動一個位置,這種情況如果數組中數據比較多的話就比較耗費性能了,所以數組實現隊列並不是一個特別好的方案,當然是可以實現的。
那麼怎麼樣能在移動元素的時候,不調動或影響其他元素呢,這時候其實就比較容易想到鏈表,鏈表都維護了一個指向下一個元素的指針,沒有絕對的位置(不像數組中的角標那麼絕對) ,鏈表移除元素的時候,只需要把對應的指針一修改就可以 了,所以相對還是比較容易的。其實最簡單的隊列實現方式,就是我們完全可以在隊列中使用一個LinkedList來存放元素,入隊直接addLast,出隊直接removeFirst , 單面試的時候如果這麼寫,不免有作弊嫌疑。因爲我們都是調用的現成的方法,根本沒有寫出實現的核心所在。所以接下來我們來自己使用鏈表的方式來實現一個隊列。 所以程序中有兩個部分,一部分是鏈表,一部分是隊列。鏈表怎麼實現呢。其實就是一個對象中引用了一個叫做next的本身對象。然後我們在實現相應的入隊,出隊的方法即可。
接下來請看代碼:
/**
* 使用鏈表實現
*/
public class Queue2<T> {
// 這裏的Node使用的是內部類實現的鏈表,Node中有一個next的Node實現了指向下一個元素
Node<T> first; //維護隊列的頭元素,用於出隊,出隊返回頭,將後一個節點置爲頭
Node<T> last; //維護隊列的尾元素,用於入隊,入隊加入到此元素後
int size;
// 入隊
public void put(T data){
Node<T> node = new Node(data);
//代表此時隊列爲空
if(first == null && last == null){
first=node;
last = node;
}else{
//隊列不爲空:
last.next = node;
last = node;
}
size++;
}
/**
* 出隊
* 從頭部獲取一個元素
* @return
*/
public T pop(){
if(size == 0){
return null;
}
Node<T> temp = first;
first = first.next;
size--;
return temp.t;
}
/**
* 使用內部類自定義一個節點
* @param <T>
*/
class Node<T>{
/**
* 代表當前節點中的數據
*/
T t;
/**
* 代表下一個節點
*/
Node next;
public Node(T t){
this.t = t;
}
public String toString(){
return t.toString();
}
}
public void printAll(){
Node temp = first;
while(temp.next != null){
System.out.println(temp);
temp = temp.next;
}
System.out.println(temp);
}
public static void main(String[] args) {
Queue2<String> queue2 = new Queue2<>();
queue2.put("a");
queue2.put("b");
queue2.put("c");
queue2.put("d");
queue2.printAll();
System.out.println(queue2.size);
System.out.println(queue2.pop());
System.out.println(queue2.pop());
System.out.println(queue2.size);
System.out.println(queue2.pop());
System.out.println(queue2.pop());
System.out.println(queue2.pop());
System.out.println(queue2.size);
}
}
好了,這就是自己實現的一簡單隊列,使用LinkedList的實現方式如果有興趣的同學,可以訪問我的github,相關代碼都已提交,上面還有springboot整合dubbo,redis,rocketmq,quartz,nacos的案例,歡迎訪問交流:https://github.com/lsqingfeng/action/