package com.zkn.newlearn.collection;
/**
*
* @author zkn 2016-06-25
* LinkedList的內(nèi)部數(shù)據(jù)結(jié)構(gòu)是雙向鏈表,
* 所以定義一個內(nèi)部類与涡,用來表示一個節(jié)點(diǎn)峭梳,
* 這個節(jié)點(diǎn)包括三個屬性,
* 1虱而、一個用來表示當(dāng)前元素
* 2筏餐、一個用來表示上一個元素
* 3、一個用來表示下一個元素
* 還需要兩個屬性節(jié)點(diǎn)用來保存鏈表的頭和尾
*/
public class ImitateLinkedListTest02<E> {
/**
* 表示頭部
*/
private Node<E> first;
/**
* 表示尾部
*/
private Node<E> last;
/**
* size的大小
*/
private int size;
/**
* 元素的個數(shù)
*/
public int size(){
return size;
}
/**
* add的方法
* @param e
*/
public void add(E e){
//說明這個時候還沒有進(jìn)行過add操作牡拇,即鏈表中沒有元素
if(last == null){
//創(chuàng)建一個新的節(jié)點(diǎn)
//對于第一個節(jié)點(diǎn)魁瞪,它的上一個元素為不存在所以為null,下一個元素同樣為null
Node<E> newNode = new Node<E>(e,null,null);
//在這個鏈表中惠呼,第一個元素為當(dāng)前要插入的節(jié)點(diǎn)导俘,最后一個元素同樣為當(dāng)前要插入的節(jié)點(diǎn)
first = newNode;
last = newNode;
}else{
//對于鏈表中已經(jīng)存在元素節(jié)點(diǎn)的情況
//創(chuàng)建出來一個新的節(jié)點(diǎn)
//對于這種鏈表中已經(jīng)有幾點(diǎn)存在的情況,它的上一個節(jié)點(diǎn)為最后一個元素剔蹋,下一個節(jié)點(diǎn)為null
Node<E> newNode = new Node<E>(e,last,null);
//當(dāng)前的最后一個元素的下一個節(jié)點(diǎn)應(yīng)該指向當(dāng)前要插入的這個節(jié)點(diǎn)旅薄。
//當(dāng)前最后一個元素的下一個節(jié)點(diǎn)指向當(dāng)前要插入的節(jié)點(diǎn),當(dāng)前要插入的節(jié)點(diǎn)的上一個元素指向當(dāng)前的最后一個元素
//這樣正好構(gòu)成了一個雙向鏈表
last.next = newNode;
//最后泣崩,要把最后一個元素節(jié)點(diǎn)變?yōu)楫?dāng)前插入的元素節(jié)點(diǎn)
last = newNode;
}
size++;
}
/**
* 根據(jù)元素位置取元素的值
* 從這個例子中就可以看出來少梁,為什么LinkedList獲取元素比較慢洛口,因為每次取出元素都有進(jìn)行一次循環(huán)!?Α5谘妗!
* @param size
* @return
*/
public E get(int index){
checkSize(index);
//獲取元素的值
//如果索引小于當(dāng)前元素個數(shù)的一半妨马,就從頭部開始循環(huán)挺举,否則從尾部開始循環(huán)
if(index < (size >> 1)){
//把頭給節(jié)點(diǎn),便于下面遞歸循環(huán)
Node<E> node = first;
for(int i=0;i<index;i++){
//循環(huán)遞歸
node = node.next;
}
//返回節(jié)點(diǎn)中的元素
return node.item;
}else{
//把尾給節(jié)點(diǎn)身笤,便于下面遞歸循環(huán)
Node<E> node = last;
for(int i=size-1;i>index;i--){
node = node.prev;
}
return node.item;
}
}
/**
* 獲取第一個元素
* @return
*/
public E getFirst(){
if(first == null)
return null;
return first.item;
}
/**
* 獲取最后一個元素
* @return
*/
public E getLast(){
if(last == null)
return null;
return last.item;
}
/**
* 移除對象
* @return
*/
public boolean remove(Object obj){
//分兩種情況來處理
//如果obj == null
if(obj == null){
for(Node<E> x = first;x != null;x = x.next){
if(x.item == null){
removeElement(x);
return true;
}
}
}else{
for(Node<E> x = first;x != null;x = x.next){
if(obj.equals(x.item)){
removeElement(x);
return true;
}
}
}
return false;
}
private E removeElement(Node<E> node) {
E itemElement = node.item;
//用來保存prev節(jié)點(diǎn)豹悬,防止后面 當(dāng)node節(jié)點(diǎn)是最后一個節(jié)點(diǎn)的時候, node.prev=null液荸,last為null
Node<E> prevNode = node.prev;
//說明node為first節(jié)點(diǎn)
if(node.prev == null){
//first節(jié)點(diǎn)的時候需要把node.next變?yōu)閒irst
first = node.next;
}else{
//如果node不是first節(jié)點(diǎn)瞻佛,則把他的上個節(jié)點(diǎn)的指向變成當(dāng)前node的下一個節(jié)點(diǎn)
//然后把這個節(jié)點(diǎn)的上個節(jié)點(diǎn)的變?yōu)閚ull 相當(dāng)于打斷節(jié)點(diǎn)的左面
node.prev.next = node.next;
node.prev = null;
}
//如果node為last節(jié)點(diǎn)
if(node.next == null){
//說明node的上一個節(jié)點(diǎn)為last節(jié)點(diǎn)
last = prevNode;
}else{
//說明如果node不是last幾點(diǎn),則把node節(jié)點(diǎn)的指向的下一個元素的上一個節(jié)點(diǎn)變?yōu)楫?dāng)前node的上一個節(jié)點(diǎn)
//然后把當(dāng)前node節(jié)點(diǎn)的next變?yōu)閚ull 相當(dāng)于打斷節(jié)點(diǎn)的右面
node.next.prev = prevNode;
node.next = null;
}
node.item = null;
size --;
return itemElement;
}
/**
* 檢查元素是否合法
* @param size2
*/
private void checkSize(int index) {
if(index >= size || index < 0){
throw new IllegalArgumentException("輸入的參數(shù)不合法娇钱,請輸入合法的參數(shù)");
}
}
/**
* 雙向鏈表的節(jié)點(diǎn)
* @author zkn
*
* @param <E>
*/
private static class Node<E>{
//當(dāng)前元素
E item;
//上一個
Node<E> prev;
//下一個
Node<E> next;
public Node(E item, Node<E> prev, Node<E> next) {
this.item = item;
this.prev = prev;
this.next = next;
}
}
public static void main(String[] args){
ImitateLinkedListTest02<String> linkedList = new ImitateLinkedListTest02<String>();
linkedList.add("張三");
linkedList.add("李四");
linkedList.add("馬六");
linkedList.add("王五");
linkedList.remove("馬六1");
System.out.println(linkedList.size());
System.out.println(linkedList.getFirst());
System.out.println(linkedList.getLast());
for(int i=0;i<linkedList.size;i++){
System.out.print(linkedList.get(i)+"->");
}
System.out.println("");
}
}
LinkedList源碼淺析
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
- 文/潘曉璐 我一進(jìn)店門常挚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人稽物,你說我怎么就攤上這事奄毡。” “怎么了贝或?”我有些...
- 文/不壞的土叔 我叫張陵吼过,是天一觀的道長。 經(jīng)常有香客問我咪奖,道長盗忱,這世上最難降的妖魔是什么? 我笑而不...
- 正文 為了忘掉前任羊赵,我火速辦了婚禮售淡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘慷垮。我一直安慰自己揖闸,他們只是感情好,可當(dāng)我...
- 文/花漫 我一把揭開白布料身。 她就那樣靜靜地躺著汤纸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪芹血。 梳的紋絲不亂的頭發(fā)上贮泞,一...
- 文/蒼蘭香墨 我猛地睜開眼狡恬,長吁一口氣:“原來是場噩夢啊……” “哼珠叔!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起弟劲,我...
- 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
- 正文 我和宋清朗相戀三年庸追,在試婚紗的時候發(fā)現(xiàn)自己被綠了霍骄。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
- 正文 年R本政府宣布,位于F島的核電站豺总,受9級特大地震影響车伞,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜喻喳,卻給世界環(huán)境...
- 文/蒙蒙 一另玖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦谦去、人聲如沸慷丽。這莊子的主人今日做“春日...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽要糊。三九已至,卻和暖如春妆丘,著一層夾襖步出監(jiān)牢的瞬間锄俄,已是汗流浹背。 一陣腳步聲響...
- 正文 我出身青樓药有,卻偏偏與公主長得像毅戈,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子塑猖,可洞房花燭夜當(dāng)晚...
推薦閱讀更多精彩內(nèi)容
- LinkedList簡介 LinkedList是基于雙向鏈表(從源碼中可以很容易看出)實現(xiàn)的竹祷,除了可以當(dāng)作鏈表來操...
- 從類的定義淺析 首先從繼承父類來看: ArrayList & Vector 都繼承了AbstractList 抽象...
- 接觸了一段時間RxJava蜡励,對它的原理還是有些模糊令花,打算看下它的源碼。 支持原創(chuàng)凉倚,轉(zhuǎn)載請注明出處兼都。 RxJava構(gòu)...
- Android 淺析 ButterKnife (二) 源碼解析 前言 Linus Benedict Torvald...
- 引入 上一篇文章DAGScheduler源碼淺析主要從提交Job的流程角度介紹了DAGScheduler源碼中的重...