日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁 > 科技  > 軟件

一文搞定雙鏈表,讓你徹底弄懂線性表的鏈?zhǔn)綄崿F(xiàn)

來源: 責(zé)編: 時間:2023-11-08 09:11:06 348觀看
導(dǎo)讀前言前面有很詳細(xì)的講過線性表(順序表和鏈表),當(dāng)時講的鏈表以單鏈表為主,但在實際應(yīng)用中雙鏈表有很多應(yīng)用場景,例如大家熟知的LinkedList。雙鏈表與單鏈表區(qū)別單鏈表和雙鏈表都是線性表的鏈?zhǔn)綄崿F(xiàn),它們的主要區(qū)別在于節(jié)點

0tz28資訊網(wǎng)——每日最新資訊28at.com

前言

前面有很詳細(xì)的講過線性表(順序表和鏈表),當(dāng)時講的鏈表以單鏈表為主,但在實際應(yīng)用中雙鏈表有很多應(yīng)用場景,例如大家熟知的LinkedList。0tz28資訊網(wǎng)——每日最新資訊28at.com

雙鏈表與單鏈表區(qū)別

單鏈表和雙鏈表都是線性表的鏈?zhǔn)綄崿F(xiàn),它們的主要區(qū)別在于節(jié)點結(jié)構(gòu)。單鏈表的節(jié)點包含數(shù)據(jù)字段 data 和一個指向下一個節(jié)點的指針 next,而雙鏈表的節(jié)點除了 data 和 next,還包含指向前一個節(jié)點的指針 pre。這個區(qū)別會導(dǎo)致它們在操作上有些差異。0tz28資訊網(wǎng)——每日最新資訊28at.com

單鏈表:

單鏈表的一個節(jié)點,有儲存數(shù)據(jù)的data,還有后驅(qū)節(jié)點next(指針)。單鏈表想要遍歷的操作都得從前節(jié)點—>后節(jié)點0tz28資訊網(wǎng)——每日最新資訊28at.com

0tz28資訊網(wǎng)——每日最新資訊28at.com

雙鏈表:

雙鏈表的一個節(jié)點,有存儲數(shù)據(jù)的data,也有后驅(qū)節(jié)點next(指針),這和單鏈表是一樣的,但它還有一個前驅(qū)節(jié)點pre(指針)。0tz28資訊網(wǎng)——每日最新資訊28at.com

0tz28資訊網(wǎng)——每日最新資訊28at.com

雙鏈表結(jié)構(gòu)的設(shè)計

上一篇講單鏈表的時候,當(dāng)時設(shè)計一個帶頭結(jié)點的鏈表就錯過了不帶頭結(jié)點操作方式,這里雙鏈表就不帶頭結(jié)點設(shè)計實現(xiàn)。所以本文構(gòu)造的這個雙鏈表是:不帶頭節(jié)點、帶尾指針(tail)的雙向鏈表。0tz28資訊網(wǎng)——每日最新資訊28at.com

對于鏈表主體:

public class DoubleLinkedList<T> {    private Node<T> head;    private Node<T> tail;    private int size;    public DoubleLinkedList(){        this.head = null;        this.tail = null;        size = 0;    }    public void addHead(T data){}    public void add(T data, int index){}    public void addTail(T data){}    public void deleteHead(){}    public void delete(int index){}    public void deleteTail(int index){}    public T get(int index){}    public int getSize() {        return size;    }    private static class Node<T> {        T data;        Node<T> pre;        Node<T> next;        public Node() {        }        public Node(T data) {            this.data = data;        }    }}

具體操作分析

對于一個鏈表主要的操作還是增刪,查詢的話不做詳細(xì)解釋。0tz28資訊網(wǎng)——每日最新資訊28at.com

剖析增刪其實可以發(fā)現(xiàn)大概有頭插入、編號插入、末尾插入、頭刪除、編號刪除、尾刪除幾種情況。然而這幾種關(guān)于頭尾操作的可能會遇到臨界點比如鏈表為空時插入刪除、或者刪除節(jié)點鏈表為空。0tz28資訊網(wǎng)——每日最新資訊28at.com

這個操作是不帶頭結(jié)點的操作,所以復(fù)雜性會高一些!0tz28資訊網(wǎng)——每日最新資訊28at.com

頭插入

頭插入?yún)^(qū)分頭為空和頭不為空兩種情況。0tz28資訊網(wǎng)——每日最新資訊28at.com

頭為空:這種情況head和tail都指向新節(jié)點。0tz28資訊網(wǎng)——每日最新資訊28at.com

頭不為空:0tz28資訊網(wǎng)——每日最新資訊28at.com

  • 新節(jié)點的next指向head
  • head的pre指向新節(jié)點
  • head指向新節(jié)點(認(rèn)新節(jié)點為head)

0tz28資訊網(wǎng)——每日最新資訊28at.com

尾插入

尾插需要考慮tail為null和不為null的情況。流程和頭插類似,需要考慮tail指針最后的指向。0tz28資訊網(wǎng)——每日最新資訊28at.com

tail為null:此時head也為null,head和tail指向新節(jié)點。0tz28資訊網(wǎng)——每日最新資訊28at.com

tail不為null:0tz28資訊網(wǎng)——每日最新資訊28at.com

  • 新節(jié)點的pre指向tail
  • tail的next指向新節(jié)點
  • tail指向新節(jié)點

編號插入

按編號插入分情況討論,如果是頭插或者尾插就直接調(diào)用對應(yīng)的方法。普通方法的實現(xiàn)方式比較靈活,可以找到前驅(qū)節(jié)點和后驅(qū)節(jié)點,然后進(jìn)行指針插入,但是往往很多時候只用一個節(jié)點完成表示和相關(guān)操作,就非常考驗對表示的理解,這里假設(shè)只找到preNode節(jié)點。 index為0:調(diào)用頭插。0tz28資訊網(wǎng)——每日最新資訊28at.com

index為size:調(diào)用尾插0tz28資訊網(wǎng)——每日最新資訊28at.com

index在(0,size):0tz28資訊網(wǎng)——每日最新資訊28at.com

  • 找到前驅(qū)節(jié)點preNode。
  • 新節(jié)點next指向nextNode(此時用preNode.next表示)。
  • nextNode(此時新節(jié)點.next和preNode.next都可表示)的pre指向新節(jié)點。
  • preNode的next指向新節(jié)點。
  • 新節(jié)點的pre指向preNode。

0tz28資訊網(wǎng)——每日最新資訊28at.com

頭刪除

頭刪除需要注意的就是刪除不為空時候頭刪除只和head節(jié)點有關(guān)0tz28資訊網(wǎng)——每日最新資訊28at.com

head不為null:0tz28資訊網(wǎng)——每日最新資訊28at.com

  • head = head.next 表示頭指針指向下一個節(jié)點
  • head 如果不為null(有可能就一個節(jié)點),head.pre = null 斷掉與前一個節(jié)點聯(lián)系 ;head如果為null,說明之前就一個節(jié)點head和pre都指向第一個節(jié)點,此時需要設(shè)置tail為null。

0tz28資訊網(wǎng)——每日最新資訊28at.com

尾刪除

尾刪除和頭刪除類似,考慮好tail節(jié)點情況0tz28資訊網(wǎng)——每日最新資訊28at.com

如果tail不為null:0tz28資訊網(wǎng)——每日最新資訊28at.com

  • tail = tail.pre。
  • 如果tail不為null,那么tail.next = null 表示刪除最后一個,如果tail為null,說明之前head和tail都指向一個唯一節(jié)點,這時候需要head = null。

編號刪除

編號刪除和編號插入類似,先考慮是否為頭尾操作,然后再進(jìn)行正常操作。0tz28資訊網(wǎng)——每日最新資訊28at.com

index為0:調(diào)用頭刪0tz28資訊網(wǎng)——每日最新資訊28at.com

index為size:調(diào)用尾刪0tz28資訊網(wǎng)——每日最新資訊28at.com

index在(0,size):0tz28資訊網(wǎng)——每日最新資訊28at.com

  • 找到待刪除節(jié)點current。
  • 前驅(qū)節(jié)點(current.pre)的next指向后驅(qū)節(jié)點(current.next)。
  • 后驅(qū)節(jié)點的pre指向前驅(qū)節(jié)點。

0tz28資訊網(wǎng)——每日最新資訊28at.com

完整代碼

根據(jù)上面的流程,實現(xiàn)一個不帶頭結(jié)點的雙鏈表,在查找方面,可以根據(jù)靠頭近還是尾近,選擇從頭或者尾開始遍歷。0tz28資訊網(wǎng)——每日最新資訊28at.com

代碼:0tz28資訊網(wǎng)——每日最新資訊28at.com

/* * 不帶頭節(jié)點的 */package code.linearStructure;/** * @date 2023.11.02 * @author bigsai * @param <T> */public class DoubleLinkedList<T> {    private Node<T> head;    private Node<T> tail;    private int size;    public DoubleLinkedList() {        this.head = null;        this.tail = null;        size = 0;    }    // 在鏈表頭部添加元素    public void addHead(T data) {        Node<T> newNode = new Node<>(data);        if (head == null) {            head = newNode;            tail = newNode;        } else {            newNode.next = head;            head.pre = newNode;            head = newNode;        }        size++;    }    // 在指定位置插入元素    public void add(T data, int index) {        if (index < 0 || index > size) {            throw new IndexOutOfBoundsException("Index is out of bounds");        }        if (index == 0) {            addHead(data);        } else if (index == size) {            addTail(data);        } else {            Node<T> newNode = new Node<>(data);            Node<T> preNode = getNode(index-1);            //step 1 2 新節(jié)點與后驅(qū)節(jié)點建立聯(lián)系            newNode.next = preNode;            preNode.next.pre = newNode;            //step 3 4 新節(jié)點與前驅(qū)節(jié)點建立聯(lián)系            preNode.next = newNode;            newNode.pre = preNode;            size++;        }    }    // 在鏈表尾部添加元素    public void addTail(T data) {        Node<T> newNode = new Node<>(data);        if (tail == null) {            head = newNode;            tail = newNode;        } else {            newNode.pre = tail;            tail.next = newNode;            tail = newNode;        }        size++;    }    // 刪除頭部元素    public void deleteHead() {        if (head != null) {            head = head.next;            if (head != null) {                head.pre = null;            } else { //此時說明之前head和tail都指向唯一節(jié)點,鏈表刪除之后head和tail都應(yīng)該指向null                tail = null;            }            size--;        }    }    // 刪除指定位置的元素    public void delete(int index) {        if (index < 0 || index >= size) {            throw new IndexOutOfBoundsException("Index is out of bounds");        }        if (index == 0) {            deleteHead();        } else if (index == size - 1) {            deleteTail();        } else {            Node<T> current = getNode(index);            current.pre.next = current.next;            current.next.pre = current.pre;            size--;        }    }    // 刪除尾部元素    public void deleteTail() {        if (tail != null) {            tail = tail.pre;            if (tail != null) {                tail.next = null;            } else {//此時說明之前head和tail都指向唯一節(jié)點,鏈表刪除之后head和tail都應(yīng)該指向null                head = null;            }            size--;        }    }    // 獲取指定位置的元素    public T get(int index) {        if (index < 0 || index >= size) {            throw new IndexOutOfBoundsException("Index is out of bounds");        }        Node<T> node = getNode(index);        return node.data;    }    // 獲取鏈表的大小    public int getSize() {        return size;    }    private Node<T> getNode(int index) {        if (index < 0 || index >= size) {            throw new IndexOutOfBoundsException("Index is out of bounds");        }        if (index < size / 2) {            Node<T> current = head;            for (int i = 0; i < index; i++) {                current = current.next;            }            return current;        } else {            Node<T> current = tail;            for (int i = size - 1; i > index; i--) {                current = current.pre;            }            return current;        }    }    private static class Node<T> {        T data;        Node<T> pre;        Node<T> next;        public Node(T data) {            this.data = data;        }    }}

結(jié)語

在插入刪除的步驟,很多人可能因為繁瑣的過程而弄不明白,這個操作的寫法可能是多樣的,但本質(zhì)操作都是一致的,要保證能成功表示節(jié)點并操作,這個可以畫個圖一步一步捋一下,看到其他不同版本有差距也是正常的。0tz28資訊網(wǎng)——每日最新資訊28at.com

還有很多人可能對一堆next.next搞不清楚,那我教你一個技巧,如果在等號右側(cè),那么它表示一個節(jié)點,如果在等號左側(cè),那么除了最后一個.next其他的表示節(jié)點。例如node.next.next.next可以看成(node.next.next).next。0tz28資訊網(wǎng)——每日最新資訊28at.com

在做數(shù)據(jù)結(jié)構(gòu)與算法鏈表相關(guān)題的時候,不同題可能給不同節(jié)點去完成插入、刪除操作。這種情況操作時候要謹(jǐn)慎先后順序防止破壞鏈表結(jié)構(gòu)。0tz28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-17665-0.html一文搞定雙鏈表,讓你徹底弄懂線性表的鏈?zhǔn)綄崿F(xiàn)

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: Spring Boot中實現(xiàn)購物車相關(guān)邏輯及示例代碼

下一篇: RabbitMQ發(fā)送和接收消息的幾種方式

標(biāo)簽:
  • 熱門焦點
  • 2023年Q2用戶偏好榜:12+256G版本成新主流

    3月份的性能榜、性價比榜和好評榜之后,就要輪到2023年的第二季度偏好榜了,上半年的新機(jī)潮已經(jīng)過去,最明顯的肯定就是大內(nèi)存和存儲的機(jī)型了,另外部分中端機(jī)也取消了屏幕塑料支架
  • 從 Pulsar Client 的原理到它的監(jiān)控面板

    背景前段時間業(yè)務(wù)團(tuán)隊偶爾會碰到一些 Pulsar 使用的問題,比如消息阻塞不消費了、生產(chǎn)者消息發(fā)送緩慢等各種問題。雖然我們有個監(jiān)控頁面可以根據(jù) topic 維度查看他的發(fā)送狀態(tài),
  • 之家push系統(tǒng)迭代之路

    前言在這個信息爆炸的互聯(lián)網(wǎng)時代,能夠及時準(zhǔn)確獲取信息是當(dāng)今社會要解決的關(guān)鍵問題之一。隨著之家用戶體量和內(nèi)容規(guī)模的不斷增大,傳統(tǒng)的靠"主動拉"獲取信息的方式已不能滿足用
  • 梁柱接棒兩年,騰訊音樂闖出新路子

    文丨田靜 出品丨牛刀財經(jīng)(niudaocaijing)7月5日,企鵝FM發(fā)布官方公告稱由于業(yè)務(wù)調(diào)整,將于9月6日正式停止運營,這意味著騰訊音樂長音頻業(yè)務(wù)走向消亡。騰訊在長音頻領(lǐng)域還在摸索。為
  • 一條抖音4億人圍觀 ! 這家MCN比無憂傳媒還野

    作者:Hiu 來源:互聯(lián)網(wǎng)品牌官01 擦邊少女空降熱搜,幕后推手曝光被網(wǎng)友譽為&ldquo;純欲天花板&rdquo;的女網(wǎng)紅井川里予,近期因為一組哥特風(fēng)照片登上熱搜,引發(fā)了一場互聯(lián)網(wǎng)世界關(guān)于
  • 東方甄選單飛:有些鳥注定是關(guān)不住的

    文/彭寬鴻編輯/羅卿東方甄選創(chuàng)始人俞敏洪帶隊的&ldquo;7天甘肅行&rdquo;直播活動已在近日順利收官。成立后一年多時間里,東方甄選要脫離抖音自立門戶的傳聞不絕于耳,&ldquo;7
  • 微博大門常打開,迎接海外畫師漂洋東渡

    作者:互聯(lián)網(wǎng)那些事&ldquo;起猛了,我能看得懂日語了&rdquo;。&ldquo;為什么日本人說話我能聽懂?&rdquo;&ldquo;中文不像中文,日語不像日語,但是我竟然看懂了&rdquo;&hellip;&hell
  • 消息稱小米汽車開始篩選交付中心:需至少120個車位

    IT之家 7 月 7 日消息,日前,有微博簡介為“汽車行業(yè)從業(yè)者、長三角一體化擁護(hù)者”的微博用戶 @長三角行健者 發(fā)文表示,據(jù)經(jīng)銷商集團(tuán)反饋,小米汽車目前
  • iQOO Neo8 Pro真機(jī)諜照曝光:天璣9200+和V1+旗艦雙芯加持

    去年10月,iQOO推出了iQOO Neo7系列機(jī)型,不僅搭載了天璣9000+,而且是同價位唯一一款天璣9000+直屏旗艦,一經(jīng)上市便受到了用戶的廣泛關(guān)注。在時隔半年后,
Top 主站蜘蛛池模板: 班玛县| 文登市| 格尔木市| 都江堰市| 高邮市| 保康县| 北宁市| 精河县| 全南县| 刚察县| 莱芜市| 德格县| 五峰| 蓬安县| 陇西县| 东阿县| 漳浦县| 巫溪县| 民丰县| 泾源县| 澄江县| 丹棱县| 资溪县| 宁德市| 山东省| 旌德县| 余姚市| 麻阳| 察雅县| 广东省| 友谊县| 银川市| 惠东县| 闵行区| 香河县| 孝昌县| 松潘县| 巴南区| 图片| 天等县| 邯郸市|