JAVA從零開始實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)五:雙向鏈表

相較于單鏈表與循環(huán)鏈表,雙向鏈表增加了prior指針
在進(jìn)行增加、插入、刪除時(shí)需要處理兩個(gè)指針
完整的MyDoubleLinkedList類

/**
 * Created by FireFlies on 2018/4/4.
 * 雙向鏈表曹宴,同時(shí)具有兩個(gè)指針next與prior
 * add
 * insert
 * delete操作改變
 */

public class MyDoubleLinkedList {

    public Node header = null;// 頭結(jié)點(diǎn)
    int size = 0;// 表示數(shù)組大小的指標(biāo)

    /**
     * 用來存放數(shù)據(jù)的結(jié)點(diǎn)型內(nèi)部類
     * 一個(gè)結(jié)點(diǎn):數(shù)據(jù)域與指針域
     */
    class Node {
        Object o;// 結(jié)點(diǎn)中存放的數(shù)據(jù)(數(shù)據(jù)域)
        Node next;// 用來指向該結(jié)點(diǎn)的下一個(gè)結(jié)點(diǎn)(指針域)
        Node prior;//用來指向該結(jié)點(diǎn)的上一個(gè)結(jié)點(diǎn)(指針域)

        public Node() {}
        public Node(Object o) {
            this.o = o;
        }
    }

    /**
     * 增操作一:直接在末尾增加
     * 思路:
     * 若size為0,則直接為header賦值new Node
     * 若size不為0歉提,獲取鏈表最后一個(gè)節(jié)點(diǎn)笛坦,將此節(jié)點(diǎn)的next賦值為new Node
     * size ++
     */
    public boolean add(Object o) {
        if (size == 0) {
            header = new Node(o);
            header.next = header;
            header.prior = header;
        } else {
            Node temp = this.getNode(size -1);
            Node newNode = new Node(o);
            //四步完成指針替換
            newNode.prior = temp;
            newNode.next = header;
            header.prior = newNode;
            temp.next = newNode;
        }
        size++;// 當(dāng)前大小自增加1
        return true;
    }

    /**
     * 增操作二:指定index增加
     * 思路:
     * 首先驗(yàn)證index有效性能
     * 若為0区转,實(shí)例化newNode,newNode.next賦值為header版扩,header賦值為newNode(三步)废离;
     * 若不為0,實(shí)例化newNode并獲取index-1位置對(duì)應(yīng)的Node temp礁芦,之后進(jìn)行指針替換蜻韭。
     * size++
     */
    public boolean insert(int index, Object o) {
        // 先判斷索引正確性
        validateIndex(index);

        if (index == 0){
            Node newNode = new Node(o);
            newNode.next = header;
            newNode.prior = header.prior;
            header = newNode;
        }else{
            Node newNode = new Node(o);
            Node temp = this.getNode(index-1);

            newNode.next = temp.next;
            newNode.prior = temp;
            temp.next.prior = newNode;
            temp.next = newNode;
        }
        size++;
        return true;
    }

    /**
     * 刪操作一
     * 思路:
     * 先驗(yàn)證index有效性
     * 若index為0,直接將header賦值為header.next
     * 若index不為0柿扣,將index-1處節(jié)點(diǎn)的next賦值為index處節(jié)點(diǎn)的next
     */

    public boolean delete(int index){
        // 先判斷索引正確性
        validateIndex(index);

        if(index == 0){
            header.next.prior = header.prior;
            header = header.next;
        }else{
            this.getNode(index).prior.next = this.getNode(index).next;
            this.getNode(index).next.prior = this.getNode(index).prior;
        }
        size--;
        return true;
    }

    /**
     * 刪操作二:直接刪除元素
     * 思路:直接從0開始遍歷鏈表,類似于查找操作
     * 當(dāng)發(fā)現(xiàn)某次獲取到的數(shù)據(jù)與要?jiǎng)h除數(shù)據(jù)相同肖方,則記錄索引位置,并執(zhí)行delete操作
     */

    public boolean remove(Object o){
        boolean flag = true;
        Node temp = header;
        for(int count = 0;count<size;count++) {
            if (temp.o.equals(o)) {
                this.delete(count);
                flag = false;
            }
            temp = temp.next;
        }
        if(flag){
            System.out.println("Element not found: "+o.toString());
            return false;
        }
        return true;
    }

    /**
     * 改操作
     * 思路:
     * 首先驗(yàn)證index有效性
     * 直接獲取index處節(jié)點(diǎn)temp
     * 取temp的屬性e未状,直接賦值為新的e
     * 設(shè)置第N個(gè)結(jié)點(diǎn)的值
     *
     */
    public boolean set(int index, Object o) {
        // 先判斷索引正確性
        validateIndex(index);
        //Node<E> newNode = new Node<E>(e);
        // 得到第x個(gè)結(jié)點(diǎn)
        Node temp = getNode(index);
        temp.o = o;
        return true;
    }

    /**
     * 查操作:
     * 先驗(yàn)證index有效性
     * 思路:
     * 必須從頭結(jié)點(diǎn)開始查起
     * 實(shí)例化Node對(duì)象temp俯画,并賦值為header,意為從頭結(jié)點(diǎn)開始查起
     * 聲明count計(jì)數(shù)器并從0開始娩践,當(dāng)count活翩!=index烹骨,則temp = temp.next,一直查下去翻伺,計(jì)數(shù)器增1
     * 直到count = index停止查找,取temp.e的值并返回沮焕。
     *
     */
    public Object get(int index) {
        // 先判斷索引正確性
        validateIndex(index);
        Node tem = header;
        int count = 0;
        while (count != index) {
            tem = tem.next;
            count++;
        }
        Object o = tem.o;
        return o;
    }

    /**
     * 查操作:
     * 先驗(yàn)證index有效性
     * 思路:
     * 必須從頭結(jié)點(diǎn)開始查起
     * 實(shí)例化Node對(duì)象temp吨岭,并賦值為header,意為從頭結(jié)點(diǎn)開始查起
     * 聲明count計(jì)數(shù)器并從0開始峦树,當(dāng)count辣辫!=index,則temp = temp.next,一直查下去魁巩,計(jì)數(shù)器增1
     * 直到count = index停止查找急灭,返回temp節(jié)點(diǎn)。
     *
     */
    private Node getNode(int index) {
        // 先判斷索引正確性
        validateIndex(index);
        Node temp = header;
        int count = 0;
        while(count!=index){
            temp = temp.next;
            count++;
        }
        return temp;
    }

    /**
     * 合并操作:
     * 合并兩個(gè)循環(huán)鏈表
     * 思路:
     * 將鏈表1的尾指針指向鏈表2的頭結(jié)點(diǎn)谷遂,鏈表2的尾指針指向鏈表1的頭結(jié)點(diǎn)
     */
    public MyDoubleLinkedList combine(MyDoubleLinkedList anotherList){
        if(this.size()!=0&&anotherList.size()!=0){
            this.getNode(size - 1).next = anotherList.getNode(0);
            anotherList.getNode(anotherList.size() - 1).next = this.getNode(0);
            size += anotherList.size();
        }else if(this.size()==0&&anotherList.size()!=0){
            return anotherList;
        }else if(anotherList.size()==0&&this.size()!=0){
            System.out.println("Your anotherList is empty!");
        }
        return this;
    }


    public int size() {
        return this.size;
    }


    /**
     *  驗(yàn)證當(dāng)前下標(biāo)是否合法葬馋,如果不合法,拋出運(yùn)行時(shí)異常
     */
    private void validateIndex(int index) {
        if (index < 0 || index > size) {
            throw new RuntimeException("數(shù)組index錯(cuò)誤:" + index);
        }
    }

    public void print(){
        System.out.print("[");
        for(int i =0;i<this.size();i++){
            System.out.print(this.get(i).toString() +" ");
        }
        System.out.print("]");
    }

}

測(cè)試類

import org.omg.CORBA._IDLTypeStub;

/**
 * Created by FireFlies on 2018/4/3.
 */
public class MyDoubleLinkedListTest {
    public static void main(String[] args) {
        MyDoubleLinkedList myDoubleLinkedList = new MyDoubleLinkedList();

        //增操作一測(cè)試,添加三個(gè)整數(shù)元素
        System.out.println("\n增操作一測(cè)試:");
        myDoubleLinkedList.add(new Integer(1));
        myDoubleLinkedList.add(new Integer(2));
        myDoubleLinkedList.add(new Integer(3));
        myDoubleLinkedList.print();

        //增操作二測(cè)試肾扰,在第二個(gè)位置增加整數(shù)4
        myDoubleLinkedList.insert(3,new Integer(4));
        myDoubleLinkedList.insert(0,new Integer(0));
        System.out.println("\n增操作二測(cè)試:");
        myDoubleLinkedList.print();

        //刪操作一測(cè)試畴嘶,刪除第一、三個(gè)位置的元素
        myDoubleLinkedList.delete(2);
        myDoubleLinkedList.delete(0);
        System.out.println("\n刪操作一測(cè)試:");
        myDoubleLinkedList.print();

        //刪操作二測(cè)試集晚,刪除元素“4”
        System.out.println("\n刪操作二測(cè)試(刪除元素4):");
        myDoubleLinkedList.remove(new Integer(4));
        myDoubleLinkedList.print();

        //刪操作二測(cè)試窗悯,刪除元素“6”
        System.out.println("\n刪操作二測(cè)試(刪除元素6):");
        myDoubleLinkedList.remove(new Integer(6));
        myDoubleLinkedList.print();

        //改操作測(cè)試,將第二個(gè)位置的元素改為整數(shù)5
        myDoubleLinkedList.set(1,new Integer(5));
        System.out.println("\n改操作測(cè)試:");
        myDoubleLinkedList.print();

        //查操作測(cè)試偷拔,取第一個(gè)位置的元素
        System.out.println("\n查操作測(cè)試:");
        System.out.println(myDoubleLinkedList.get(0).toString());

        //合并操作測(cè)試蒋院,合并兩個(gè)循環(huán)鏈表
        System.out.println("\n合并操作測(cè)試:");
        MyDoubleLinkedList anotherList = new MyDoubleLinkedList();
        anotherList.add(7);
        anotherList.add(8);
        anotherList.add(9);
        myDoubleLinkedList.combine(anotherList);
        myDoubleLinkedList.print();
    }
}

測(cè)試結(jié)果


image.png

到現(xiàn)在感覺腦子不太夠用了亏钩。。代碼也不知道有沒有錯(cuò)誤悦污,希望看過的老鐵們多提提意見哈~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末铸屉,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子切端,更是在濱河造成了極大的恐慌彻坛,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件踏枣,死亡現(xiàn)場(chǎng)離奇詭異昌屉,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)茵瀑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門间驮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人马昨,你說我怎么就攤上這事竞帽。” “怎么了鸿捧?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵屹篓,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我匙奴,道長(zhǎng)堆巧,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任泼菌,我火速辦了婚禮谍肤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘哗伯。我一直安慰自己荒揣,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布焊刹。 她就那樣靜靜地躺著系任,像睡著了一般。 火紅的嫁衣襯著肌膚如雪伴澄。 梳的紋絲不亂的頭發(fā)上赋除,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音非凌,去河邊找鬼举农。 笑死,一個(gè)胖子當(dāng)著我的面吹牛敞嗡,可吹牛的內(nèi)容都是我干的颁糟。 我是一名探鬼主播航背,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼棱貌!你這毒婦竟也來了玖媚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤婚脱,失蹤者是張志新(化名)和其女友劉穎今魔,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體障贸,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡错森,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了篮洁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涩维。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖袁波,靈堂內(nèi)的尸體忽然破棺而出瓦阐,到底是詐尸還是另有隱情,我是刑警寧澤篷牌,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布睡蟋,位于F島的核電站,受9級(jí)特大地震影響娃磺,放射性物質(zhì)發(fā)生泄漏薄湿。R本人自食惡果不足惜叫倍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一偷卧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吆倦,春花似錦听诸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至须妻,卻和暖如春仔蝌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背荒吏。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工敛惊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人绰更。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓瞧挤,卻偏偏與公主長(zhǎng)得像锡宋,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子特恬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355