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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

浅谈:数据结构之单链表,java代码演示单链表

發布時間:2024/4/15 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浅谈:数据结构之单链表,java代码演示单链表 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

單鏈表

本文是觀看尚硅谷韓老師視頻學習總結,部分來源網絡.

單鏈表介紹

鏈表是一種物理存儲單元上非連續、非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。鏈表由一系列結點(鏈表中每一個元素稱為結點)組成,結點可以在運行時動態生成。每個結點包括兩個部分:一個是存儲數據元素的數據域,另一個是存儲下一個結點地址的指針域。

單向鏈表只有一個指針域,在整個節點中數據域用來存儲數據元素,指針域用于指向下一個具有相同結構的節點。


  單向鏈表中,每個節點的數據域都是通過一個 Object 類的對象引用來指向數據元素的,與數組類似,單向鏈表中的節點也具有一個線性次序,即如果節點 a1 的 next 引用指向節點 a2,則 a1 就是 a2 的直接前驅,a2 是 a1 的直接后續。只能通過前驅節點找到后續節點,而無法從后續節點找到前驅節點。
特點:
  數據元素的存儲對應的是不連續的存儲空間,每個存儲結點對應一個需要存儲的數據元素。每個結點是由數據域和指針域組成。 元素之間的邏輯關系通過存儲節點之間的鏈接關系反映出來。
  邏輯上相鄰的節點物理上不必相鄰。
缺點:
1、比順序存儲結構的存儲密度小 (每個節點都由數據域和指針域組成,所以相同空間內假設全存滿的話順序比鏈式存儲更多)。
2、查找結點時鏈式存儲要比順序存儲慢(每個節點地址不連續、無規律,導致按照索引查詢效率低下)。
優點:
1、插入、刪除靈活 (不必移動節點,只要改變節點中的指針,但是需要先定位到元素上)。
2、有元素才會分配結點空間,不會有閑置的結點。

單鏈表Java代碼模擬詳解,演示單鏈表的增刪改查

分析

按照節點的循序添加分析

按照節點的順序插入一個節點分析

按照節點數刪除某個節點分析圖(修改了思路也類似,找到修改的節點,改變其屬性即可)

代碼(詳細解釋在代碼注釋中)

package com.fs.demo_2020_07_12_LinkedList;/*** 單鏈表 演示**/ public class SingleLinkedListDemo {public static void main(String[] args) {//測試鏈表//先創建節點Node node1 = new Node(1, "節點一");Node node2 = new Node(2, "節點二");Node node3 = new Node(3, "節點三");Node node4 = new Node(4, "節點四");//創建鏈表,將節點(安裝順序)添加進去SingleLinkedList singleLinkedList = new SingleLinkedList();//按照循序添加節點到單項鏈表 // singleLinkedList.add(node1); // singleLinkedList.add(node2); // singleLinkedList.add(node3); // singleLinkedList.add(node4); // singleLinkedList.add(node4);添加多個同樣的節點會無限循環下去,因為next指向的是同一個節點//根據節點數的大小將節點插入指定位置singleLinkedList.addByOrder(node1);singleLinkedList.addByOrder(node4);singleLinkedList.addByOrder(node2);singleLinkedList.addByOrder(node3);//顯示一下singleLinkedList.showLinkedList();System.out.println("--------測試修改節點---------");//測試修改節點Node newNode = new Node(2, "小付");singleLinkedList.updateByNum(newNode);System.out.println("修改后的鏈表顯示如下");singleLinkedList.showLinkedList();//正常顯示,說明根據節點num找到,修改成功System.out.println("---------測試刪除節點---------------");//測試刪除節點singleLinkedList.delNode(2);System.out.println("刪除后鏈表顯示如下");singleLinkedList.showLinkedList();} }//創建一個類來模擬單鏈表 class SingleLinkedList{//先初始化一個頭節點,頭節點不動,不存放具體信息private Node headNode = new Node(0,"頭結點");/*一 按照循序添加節點到單項鏈表思路:找到當前鏈表的最后節點將最后這個節點next指向新的節點*/public void add(Node node){//拿到初始化的頭結點,作為輔助遍歷tempNode temp = headNode;//遍歷鏈表while (true){//由圖解得知,單鏈表當遍歷到最后一個節點后,next存儲的值為null.因為沒有下一個節點可以存儲了if (temp.next==null){//那就停止循環break;}//如果沒有找到最后,那就將temp后移一個節點temp = temp.next;}//循環結束后,所明temp到達最后一個節點了,那么就在最后一個節點后添加數據,將temp的next存儲添加的節點值//將最后這個節點指向新的節點temp.next = node;}/*二 根據節點數的大小將節點插入指定位置*/public void addByOrder(Node node){//同樣,讓頭結點作為我們輔助遍歷Node temp = headNode;//創建一個標記,默認為falseboolean flag = false;while (true){if (temp.next==null){//說明已經到最后一個節點,說明就插入到最后一個的后面,循環結束break;}//若插入的節點數小于遍歷當前temp的節點數,那么就插入在當前節點數的后面,找到插入位置,循環結束if (temp.next.num>node.num){break;//若當前節點數等于插入的節點數,說明在鏈表中已經存在這個節點,所以無需添加//那么就改變標記true,停止循環}else if (temp.next.num == node.num){flag = true;break;}//每次循環將當前節點向后移temp = temp.next;}//循環結束后要么是找到了插入的位子,要么就是找到了相同的節點if (flag){//說明找到了相同的節點,就打印說明System.out.println("準備插入的節點數:"+node.num+"已經存在,不能在次插入~~~");}else {//將temp.next接在node.nextnode.next = temp.next;//說明找到了插入的節點位置的,就是在temp后面temp.next = node;}}/*三 修改節點信息,根據num來修改,但是num不能修改,只能修改num節點的name*/public void updateByNum(Node newNode){//還是先判斷鏈表是否為空,判斷頭部節點的下一位是否為空if (headNode.next==null){System.out.println("鏈表為空~~~");return;}//找到需要修改的節點,根據num號//定義一個輔助節點,這次就不是頭結點了,因為頭結點不能更改Node temp = headNode.next;//立一個flag,表示是否找到這個節點boolean flag = false;while (true){if (temp == null){break;//說明已經遍歷完了}if (temp.num == newNode.num){//說明找到flag = true;break;}//每次循環指針指向下一個temp = temp.next;}//根據flag來判斷是否找到要修改的節點if (flag){//說明找到temp.name = newNode.name;}else {//沒有找到System.out.println("沒有找到編號為:"+newNode.num+"的節點~~~");}}/*刪除節點思路:比較的是temp.next.num 與需要刪除的節點的num比較*/public void delNode(int num){//同樣,標志是否摘掉帶刪除的節點Node temp = headNode;//立flagboolean flag = false;while (true){if (temp == null){//已經到達最后的節點break;}if (temp.next.num == num){//說明找到了刪除節點的前一個節點tempflag = true;break;}temp = temp.next;//循環后移}//判斷flagif (flag){//說明找到.可以刪除/*temp.next = temp.next.next;因為上面是找到了要刪除的前一個節點,所以我們只需要將當前節點的next賦值為下下個節點,那么就達到了有個節點沒有連接上,就會等待java垃圾回收假設我們需要刪除2,那么上面的邏輯是temp.next.num = 2 的時候,flag為true那么temp就是節點1,那么節點1的next設置為下下一個那么就是節點三,那么就變相的將節點2移除鏈表*/temp.next = temp.next.next;}else {System.out.println("您需要刪除的節點:"+num+"在鏈表中不存在~~~");}}/*顯示鏈表,遍歷查看*/public void showLinkedList(){//判斷鏈表否為空if (headNode.next == null){System.out.println("鏈表為空,請添加后查看~~~");return;}//同樣,頭結點不能動,作為輔助遍歷,從頭節點的下一位開始顯示,頭節點不顯示Node temp = headNode.next;while (true){//判斷是否到最后一個節點了if (temp == null){break;}//輸出節點信息System.out.println(temp);//將temp后移temp = temp.next;}}}//創建一個類類模擬節點 class Node{public int num;//當前節點數public String name;//給當前節點取個名字,模擬節點存儲的數據public Node next;//當前節點存儲的下一個節點信息//提供構造方法來初始化這個節點信息public Node(int num, String name) {this.num = num;this.name = name;}@Overridepublic String toString() {return "Node{" +"num=" + num +", name='" + name + '\'' +'}';} }

運行結果控制臺顯示

---------添加4個節點(1,2,3,4)------------ Node{num=1, name='節點一'} Node{num=2, name='節點二'} Node{num=3, name='節點三'} Node{num=4, name='節點四'} --------測試修改節點2的數據--------- 修改后的鏈表顯示如下 Node{num=1, name='節點一'} Node{num=2, name='小付'} Node{num=3, name='節點三'} Node{num=4, name='節點四'} ---------測試刪除節點2--------------- 刪除后鏈表顯示如下 Node{num=1, name='節點一'} Node{num=3, name='節點三'} Node{num=4, name='節點四'}

單鏈表的試題案列

/*** 試題,在不改變鏈表結構的情況下逆序打印輸出* @param headNode 給一個頭結點*/public static void reversePrint(Node headNode){//判斷是否有下一個if (headNode.next == null){return;}//定一個變量的獲取Node temp = headNode.next;//創建一個棧來實現Stack<Node> nodes = new Stack<>();//循環壓棧while (temp!=null){nodes.push(temp);//后移temp,這樣就可以壓入下一個節點了temp = temp.next;}//將棧中的節點彈棧取出while (nodes.size()>0){//stack棧的特點就是先進后出System.out.println(nodes.pop());}}/*** 試題:將鏈表反轉* @param headNode 給定一個鏈表的頭節點,讓鏈表反轉*/public static void reverseLinkedList(Node headNode){//先判斷鏈表是否為空,或者只有一個節點,那么就無需返轉headNode.next.next 說明只有一個節點if (headNode.next == null || headNode.next.next == null){return;}//定義一個輔助指針,幫助我們遍歷原來的鏈表Node temp = headNode.next;//將頭結點的下一個節點給這個臨時節點Node next = null;//定義一個節點,來暫時保存下一個節點,Node reverseHead = new Node(0,"反轉節點");//創建一個新的頭結點,來接反轉后的節點//遍歷原來的鏈表,沒遍歷一個節點,將其取出,并放在新的reverseHead 的最前端while (temp!=null){//當頭結點的下一個節點不為null的時候,遍歷next = temp.next;//先將temp的下一個節點暫時保存在next中,方便后面使用temp.next = reverseHead.next;//將temp的下一個節點指向新的鏈表的最前端reverseHead.next = temp;//在將temp連接到新的鏈表上temp = next;//讓temp后移}//在將headNode指向reverseHead,實現單鏈表反轉headNode.next = reverseHead.next;}/*** 試題:查找單鏈表中倒數第幾個節點* @param headNode 頭結點* @param index 要查找的倒數第幾個節點* @return 查找出來返回的節點*/public static Node findNodeByIndex(Node headNode, int index){//先判斷頭結點是否為空,為空就返回nullif (headNode.next == null){return null;}//調用剛剛寫的方法獲取到鏈表的有效個數int length = getLength(headNode);//先對傳入的index做判斷,判斷數據是否子啊合理范圍內if (index <=0 || index > length){//index<=0 不能找倒數-1 或者倒數0 個節點吧//index>length 假設有效節點就3個,不能找倒數第4個節點吧return null;//滿足條件就返回null}//定義零時Node為頭結點的下一個,for循環定位倒數的indexNode temp = headNode.next;//那么當前temp為節點1//循環遍歷有效個數//假設length = 3 ,(節點順序為1,2,3)我們要找的是倒數第1個,那么循環遍歷2次,//為什么:i=0的時候,temp.next = 2, i = 1的時候,temp.next = 3,//i = 2 的時候,for循環結束,返回temp,那么temp = 3,所以倒數第一個節點為節點3for(int i = 0 ; i < length - index; i++){//每次循環,就讓temp指向下一個節點temp = temp.next;}//返回查找的節點return temp;}/*** 試題:獲取單鏈表的節點個數,不統計頭節點* @param headNode 把鏈表的頭節點傳遞給方法* @return 返回鏈表有效節點的個數*/public static int getLength(Node headNode){//先判斷頭結點的next是否為空,為空則表示鏈表為空if (headNode.next==null){System.out.println("鏈表為空,無有效個數~~~");}//定義一個變量來統計個數int length = 0;//代碼走到這里說明有下一個節點,定義一個節點來保存下一個節點Node temp = headNode.next;// 循環 判斷temp是否為nullwhile (temp!=null){//說明為有效數據length++;//在將temp指向下一個節點temp = temp.next;}//返回最后的值return length;}

測試結果

反轉單鏈表圖解

在不改變單鏈表的結構倒序打印圖解

總結

以上是生活随笔為你收集整理的浅谈:数据结构之单链表,java代码演示单链表的全部內容,希望文章能夠幫你解決所遇到的問題。

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