日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构与算法—一文多图搞懂双链表

發布時間:2025/3/20 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构与算法—一文多图搞懂双链表 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • 前言
  • 雙鏈表介紹
    • 與單鏈表區別
    • 結構的設計
  • 具體方法的解析
    • 初始化
    • 增加
        • 空表插入
        • 頭插入
        • 尾插入
        • 編號插入
    • 刪除
        • 單節點刪除
        • 頭刪除
        • 尾刪除
        • 普通刪除
  • 代碼與測試
  • 總結與感悟

前言

前面講過線性表中順序表和鏈表的實現和性質。但是在數據結構與算法中,雙向鏈表無論在考察還是運用中都占有很大的比例,筆者旨在通過本文與讀者一起學習分享雙鏈表相關知識。

雙鏈表介紹


與單鏈表區別

邏輯上沒有區別。他們均是完成線性表的內容。主要的區別是結構上的構造有所區別。
對于單鏈表:

  • 對于一個節點,有儲存數據的data。和next后驅節點(指針)。也就是這個單鏈表想要一些遍歷的操作都得通過前節點—>后節點。

對于雙鏈表:

  • 對于一個節點,有些和單鏈表一樣有存儲數據的data,指向后方的next(指針)。它擁有單鏈表的所有操作和內容。但是他還有一個前驅節點pre(指針)。

結構的設計

  • 對于雙鏈表的結構,上圖也很清楚的。以前設計的單鏈表是帶頭節點的。帶頭節點可以方面首位的插入和刪除。而這次我們抱著學習的態度搞清鏈表故該雙鏈表是不帶頭節點的.
  • 同時,以前的單鏈表是不帶尾節點的,這次我們帶上尾節點tail。這樣我們就接觸了幾乎所有類型啦!遇到啥也不怕了。

所以我們構造的這個雙鏈表的的性質:

  • 不帶頭節點、帶尾指針(tail)、雙向鏈表。

對于node節點:

class node<T> {T data;node<T> pre;node<T> next;public node() {}public node(T data) {this.data = data;} }

對于鏈表:

public class doubleList<T> {private node<T> head;// 頭節點private node<T> tail;// 尾節點private int length;//各種方法 }

具體方法的解析

  • 其實對于一個鏈表主要的操作還是增刪。增閃的話都需要考慮是否帶頭節點。頭插、尾插、中間插。并且還要考慮其中的一些細節處理。指針的運算。防止鏈表崩掉。因為這些操作如果不當往往會對鏈表的結構和證悟性帶來致命的打擊。而像查找那些邏輯稍微簡單。也很容易排查錯誤。

初始化

  • 我們知道一個雙鏈表在最初的時候它的數據肯定是為null的。那么對于這個不帶頭節點的雙鏈表而言。它的head始終指向第一個真實有效的數據。tail也是如此。那么在最初沒數據的時候當然要head=null,并且tail=head。(tail和head需要在一個鏈上)。
public doubleList() {head = null;tail = head;length = 0;}

增加

空表插入

  • 對于空鏈表來說。增加第一個元素可以特殊考慮。因為在鏈表為空的時候head和tail均為null。但head和tail又需要實實在在指向鏈表中的真實數據(帶頭指針就不需要考慮)。所以這時候就新建一個node讓head、tail等于它
node<T> teamNode = new node(data); if (isEmpty()) {head = teamNode;tail = teamNode; }

頭插入

對于頭插入來說。步驟很簡單,只需考慮head節點的變化。

  • 新建插入節點node
  • head前驅指向node
  • node后驅指向head
  • head指向node。(這時候head只是表示第二個節點,而head需要表示第一個節點故重新賦值)
  • 尾插入

    對于尾插入來說。只需考慮尾節點tail節點的變化。

  • 新建插入節點node
  • node前驅指向tail
  • tail后驅指向node
  • tail指向node。(這時候tail只是表示倒數第二個節點,而tail需要表示最后節點故重新賦值等于node即可)
  • 編號插入

    對于編號插入來說。要考慮查找和插入兩部,而插入既和head無關也和tail無關。

  • 新建插入節點node
  • 找到欲插入node的前一個節點pre。和后一個節點after
  • node后驅指向after,after前驅指向node(次時node和后面節點的關聯已經完成,但是和前面處理分離狀態)
  • pre后驅指向node。node前驅指向pre(此時完畢)
  • 整個流程的動態圖為:

    刪除

    單節點刪除

    無論頭刪還是尾刪,遇到單節點刪除的需要將鏈表從新初始化!

    if (length == 1)// 只有一個元素 {head = null;tail = head;length--; }

    頭刪除

    頭刪除需要注意的就是刪除不為空時候頭刪除只和head節點有關

    大致分為:

  • head節點的后驅節點前驅節點改為null。(head后面本指向head但是要刪除第一個先讓后面那個和head斷絕關系)
  • head節點指向head.next.(這樣head就指向我們需要的第一個節點了。如果有需要處理內存的語言就可以把第一個被孤立的節點刪除了)
  • 尾刪除

    尾刪除需要注意的就是刪除不為空時候尾刪除只和tail節點有關。記得在普通鏈表中,我們刪除尾節點需要找到尾節點的前驅節點。需要遍歷整個表。而雙向鏈表可以直接從尾節點遍歷到前面。

    刪除的時tail所在位置的點。也就是tail所在節點要斷絕和雙鏈表的關系。

  • tail.pre.next=null尾節點的前一個節點(pre)的后驅節點等于null
  • tail=tail.pre尾節點指向它的前驅節點,此時尾節點由于步驟1next已經為null。完成刪除
  • 普通刪除

    普通刪除需要重點掌握,因為前兩個刪除都是普通刪除的一個特例而已。(普通刪除要確保不是頭刪除和尾刪除)

  • 找打將刪除節點的前驅節點team(team.next是要刪除的節點)
  • team.next.next.pre=team.(欲被刪除節點的后一個節點的前驅指向team,雙向鏈表需要處理pre和next。這步處理了pre)
  • team.next=team.next.next;此時team.next也跳過被刪除節點。
  • 完成刪除

    整個流程的動態圖為:
  • 代碼與測試


    代碼:

    package LinerList;/** 不帶頭節點的*/ public class doubleList<T> { class node<T> {T data;node<T> pre;node<T> next;public node() {}public node(T data) {this.data = data;} }private node<T> head;// 頭節點 private node<T> tail;// 尾節點 private int length;public doubleList() {head = null;tail = head;length = 0; }boolean isEmpty() {return length == 0 ? true : false; }void addfirst(T data) {node<T> teamNode = new node(data);if (isEmpty()) {head = teamNode;tail = teamNode;} else {teamNode.next = head;head = teamNode;}length++; }void add(T data)// 尾節點插入 {node<T> teamNode = new node(data);if (isEmpty()) {head = teamNode;tail = teamNode;} else {tail.next = teamNode;teamNode.pre=tail;tail = teamNode;}length++; }int length(){return length;} T getElum(int index)//為了簡單統一從頭找 {node<T> team=head;for(int i=0;i<index;i++)//不帶頭節點 遍歷次數-1{team=team.next;}return team.data; } void add(int index, T data)// 編號插入 {if (index == 0) {addfirst(data);} else if (index == length) {add(data);} else {// 重頭戲node teampre = head;// 為插入的前qufor (int i = 0; i < index -1; i++)// 無頭節點,index-1位置找到前驅節點{teampre = teampre.next;}node<T> team = new node(data);// a c 中插入B 找打ateam.next = teampre.next;// B.next=cteampre.next.pre = team;// c.pre=Bteam.pre = teampre;// 關聯a Bteampre.next = team;length++;} } void deletefirst()// 頭部刪除 {if (length == 1)// 只有一個元素{head = null;tail = head;length--;} else {head = head.next;length--;} }void deletelast() {if(length==1){head=null;tail=head;length--;}else {tail.pre.next=null;tail=tail.pre;length--;} }void delete(int index){if(index==0)deletefirst();else if (index==length-1) {deletelast();}else {//刪除 為了理解統一從頭找那個節點 node<T>team=head;for(int i=0;i<index-1;i++){team=team.next;}//team 此時為要刪除的前節點 a c 插入B a為teamteam.next.next.pre=team;//c的前驅變成ateam.next=team.next.next;//a的后驅變成clength--;}}void set(int index,T data){node<T>team=head;for(int i=0;i<index-1;i++){team=team.next;}team.data=data;} @Override public String toString() {node<T> team = head;String vaString = "";while (team != null) {vaString += team.data + " ";team = team.next;}return vaString; } }

    測試:

    package LinerList;public class test {public static void main(String[] args) throws Exception { // TODO Auto-generated method stubSystem.out.println("線性表測試:");doubleList<Integer> list = new doubleList<Integer>();list.add(66);list.addfirst(55);list.add(1, 101);list.add(-22);list.add(555);list.addfirst(9999);System.out.println(list.toString() + " lenth " + list.length());// 9999 55 101 66 -22 555// System.out.println(list.getElum(0)+" "+list.getElum(2)+" "+list.getElum(4));list.deletefirst();System.out.println(list.toString() + " lenth " + list.length());// 55 101 66 -22 555 lenth 5list.delete(1);System.out.println(list.toString() + " length " + list.length());// 55 66 -22 555 length 4list.delete(1);System.out.println(list.toString() + " length " + list.length());// 55 -22 555 length 3list.deletelast();System.out.println(list.toString() + " lenth " + list.length());// 55 -22 lenth 2list.deletelast();System.out.println(list.toString() + " lenth " + list.length());// 55 lenth 1list.deletelast();System.out.println(list.toString() + " lenth " + list.length());// lenth 0System.err.println("歡迎關注公眾號:bigsai");}}

    結果圖

    總結與感悟

    插入、刪除順序問題

    • 很多人其實不清楚插入、刪除正確的順序是什么。其實這點沒有必然的順序,要根據題意所給的條件完成相同的結果即可!
    • 還有就是你可能會搞不清一堆next.next這些問題。這時候建議你畫個圖。你也可以先建一個節點,用變量名完成操作,可能會更容易一些。比如刪除操作,你找到pre節點(刪除前的節點)。你可以node delete=pre.next,node next=delete.next。這樣你直接操作pre。delete。next三個節點會更簡單。
    • 但是很多題目只給你一個node。你這時候要分析next(pre)。改變順序。因為只有一個節點,你改變next(pre)很可能導致你遍歷不到那個節點。所以這種情況要好好思考(可以參考筆者的代碼實現)。
    • 至于有些語言需要刪除內存的。別忘記刪除。(java大法好)

    其他操作問題:

    • 對于其他操作,相比增刪要容易理解,可以參考代碼理解。
    • 雙向鏈表可以對很多操作進行優化。這里只是突出實現并沒有寫的太多。比如查找時候可以根據長度判斷這個鏈表從頭查找還是從尾查找。

    另外,代碼寫的可能不是太好,鏈表也沒考慮線程安全問題。算法效率可能不太優。如果有什么改進或者漏洞還請大佬指出!

    最后(last but not least)

    • 喜歡的感覺可以的煩請大家動動小手關注一下把,關注后回復: 數據結構 有精心準備的系列。個人公眾號交流:bigsai
    • 歡迎交友!

    總結

    以上是生活随笔為你收集整理的数据结构与算法—一文多图搞懂双链表的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 国产精品第8页 | 日韩欧美国产成人 | 黄色羞羞网站 | 西西大胆午夜视频 | 久久激情五月 | 日韩欧美在线一区二区三区 | 欧美顶级黄色大片免费 | 波多野结衣一区二区三区免费视频 | 一级黄av| 国产精品久久综合 | 国产黄色免费视频 | 女人一级一片30分 | 69网站在线观看 | 香蕉视频在线播放 | 黑森林av | 中国女人黄色大片 | 精品在线视频一区二区三区 | 久久亚洲a v | 国产亚洲精品久久久久久打不开 | 欧美jizzhd精品欧美18 | 日本精品视频在线播放 | 天天爽夜夜爽夜夜爽精品视频 | 欧美群妇大交乱 | 色综合五月婷婷 | 天堂素人 | 五月天视频网站 | 正在播放国产精品 | 精品熟妇一区二区三区 | 色欧美在线 | 成人夜夜 | 又黄又爽的免费视频 | 狠狠操在线| 91免费网站入口 | 91黄色小视频 | 国产午夜精品久久久久久久久久 | 自拍偷拍视频在线观看 | 国产91精品一区二区麻豆亚洲 | 国产电影一区二区三区 | 久久免费视频观看 | 黑人黄色录像 | gv天堂gv无码男同在线观看 | 欧美国产在线观看 | 99免费在线视频 | 天天色天天色天天色 | 91精品婷婷国产综合久久竹菊 | 欧美性生交xxxxx久久久缅北 | 久久调教视频 | 果冻传媒18禁免费视频 | 在线国产福利 | 久久青草免费视频 | 91视频99 | 久久成人激情 | 一级黄色片免费播放 | 国产三级高清 | 五月激情av | 草1024榴社区成人 | 国产夜夜夜| 狠狠干夜夜 | 黄色av观看 | 操出白浆视频 | 欧美精品人妻一区二区 | 亚洲成人免费影院 | 妺妺窝人体色777777 | 另类小说久久 | 福利一区三区 | 亚洲一区二区三区四区五区六区 | 狠狠躁夜夜躁人爽 | av三级网站| 国产精品久久久久久久久岛 | 黄色大片91 | 申鹤乳液狂飙 | 久久免费视频观看 | 国产精品久久久久影院色老大 | 免费av日韩 | 中国免费毛片 | 久久亚洲国产精品 | 不卡一区在线观看 | 亚洲综合天堂 | 97久久人澡人人添人人爽 | 国产精品视频自拍 | 999国内精品永久免费视频 | 光棍影院手机版在线观看免费 | 午夜一区二区三区 | 日本在线观看一区二区 | 国产做爰全过程免费视频 | 中文字幕在线观看视频www | 日韩欧美亚洲一区二区 | 色屁屁一区二区三区 | 国产精品爽爽 | 狠狠操在线 | 一区二区三区视频在线观看 | 日韩一区二区三区免费在线观看 | 四虎网站最新网址 | 日本不卡高清视频 | 中文字幕永久在线观看 | 在线观看麻豆视频 | 91国内视频| 香蕉91视频 | 国产一区高清 |