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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

(数据结构与算法)单链表与双链表增删改查的实现。

發布時間:2025/3/20 编程问答 12 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (数据结构与算法)单链表与双链表增删改查的实现。 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 鏈表介紹
    • 1. 單鏈表應用實例
      • 1.1 實現思路
      • 1.2 代碼實現
    • 2.單鏈表常見面試題
      • 2.1 求單鏈表中有效節點的個數
      • 2.2 查找單鏈表中倒數第K個節點
      • 2.3 單鏈表的反轉
      • 2.4 逆序打印單鏈表
      • 2.5 合并兩個單鏈表,合并后依然有序
    • 3. 雙鏈表應用實例
      • 3.1 單鏈表缺點
      • 3.2 實現思路
      • 3.3 代碼實現

鏈表介紹

鏈表是有序的列表,但是它在內存中是如下存儲的:

  • 鏈表是以節點的方式來存儲,是鏈式存儲
  • 每個節點包含data域,next域:指向下一個節點
  • 鏈表的各個節點不一定是連續存儲
  • 鏈表分帶頭節點的鏈表和沒有頭結點的鏈表

單鏈表(帶頭節點)邏輯結構示意圖如下:

1. 單鏈表應用實例

使用帶頭的單向鏈表實現 -帶編號的英雄人物的增刪改查操作。

1.1 實現思路

1.add方法添加英雄時,直接添加到鏈表尾部


2.addByOrder方法添加英雄時,根據英雄編號將英雄插入到指定的位置

3.update方法修改節點功能。
1)通過遍歷根據no找到該節點,沒找到就后移temp=temp.next
2)替換name和nickName
4.刪除節點

1.2 代碼實現

package com.zh.LinkedList;public class SingleLinkedListDemo01 {public static void main(String[] args) {//測試HeroNode hero1 = new HeroNode(1,"伊澤瑞爾","冒險家");HeroNode hero2 = new HeroNode(2,"拉克絲","光輝女郎");HeroNode hero3 = new HeroNode(3,"亞索","疾風劍豪");HeroNode hero4 = new HeroNode(4,"盧錫安","圣槍游俠");SingleLinkedList list = new SingleLinkedList(); // list.add(hero1); // list.add(hero2); // list.add(hero3); // list.add(hero4); // list.listTraverse();list.addByOrder(hero1);list.addByOrder(hero4);list.addByOrder(hero3);list.addByOrder(hero2);list.listTraverse();HeroNode heroNew = new HeroNode(2,"佐伊","暮光星靈");list.update(heroNew);System.out.println("-------------------修改后------------------");list.listTraverse();list.delete(1);System.out.println("-------------------刪除后------------------");list.listTraverse();} }//創建鏈表 class SingleLinkedList{//創建一個頭節點,頭節點不能動,不存放具體的數據HeroNode head = new HeroNode(0,"","");/*當不考慮編號順序時1.找到當前鏈表的最后節點2.將最后這個節點的next指向新的節點*/public void add(HeroNode heroNode){//因為頭節點不能動,所以創建一個輔助節點tempHeroNode temp = head;while (true){//找到鏈表的最后節點if (temp.next==null){break;}else {//如果沒有找到鏈表的最后,后移一位temp = temp.next;}}//將最后這個節點的next指向新的節點temp.next=heroNode;}//按英雄編號來添加public void addByOrder(HeroNode heroNode){HeroNode temp = head;boolean flag = false;//判斷添加的節點是否存在while (true){if (temp.next==null){//鏈表為空break;}if (temp.next.no > heroNode.no){//如果temp指向的下一個節點編號大于添加的編號,說明新節點位于temp與temp.next之間break;}else if (temp.next.no == heroNode.no){//說明添加的節點編號已經存在flag = true;break;}//節點后移temp = temp.next;}if (flag){System.out.println("要添加的節點已存在,編號為"+heroNode.no);}else {//插入到鏈表中,將新節點的next指向temp.next,temp.next指向新節點heroNode.next = temp.next;temp.next = heroNode;}}//鏈表節點修改public void update(HeroNode heroNode){//判斷是否為空if (head.next==null){System.out.println("鏈表為空");return;}//根據no找到要修改的節點//定義輔助變量HeroNode temp = head.next;boolean flag = false;//表示是否找到該節點while (true){if (temp==null){//已經遍歷完break;}if (temp.no == heroNode.no){flag = true;break;}//沒找到就后移temp = temp.next;}if (flag) {temp.name = heroNode.name;temp.nickName = heroNode.nickName;}else {System.out.println("沒有找到編號為"+ heroNode.no+"的節點,不能進行修改");}}//刪除節點public void delete(int no){HeroNode temp = head;boolean flag = false;if (head.next==null){System.out.println("鏈表為空");}while (true){if (temp.next==null){//已經遍歷完break;}if (temp.next.no==no){flag = true;break;}temp = temp.next;}if (flag){temp.next = temp.next.next;}else {System.out.println("沒有找到編號為"+no+"的節點,無法刪除");}}//鏈表遍歷public void listTraverse(){//創建一個輔助節點遍歷HeroNode temp = head.next;//判斷鏈表是否為空if (temp==null){System.out.println("鏈表為空");return;}else {while (true){//判斷鏈表是否到最后if (temp == null){break;}else{//輸出節點信息System.out.println(temp);//將節點后移temp=temp.next;}}}} } //單鏈表的英雄節點 class HeroNode{public int no;//序號public String name;public String nickName;public HeroNode next;//指向下一個節點public HeroNode(int no, String name, String nickName) {this.no = no;this.name = name;this.nickName = nickName;}@Overridepublic String toString() {return "HeroNode{" +"no=" + no +", name='" + name + '\'' +", nickName='" + nickName + '\'' +'}';} }

2.單鏈表常見面試題

2.1 求單鏈表中有效節點的個數

/**獲取單鏈表有效節點的個數** @param head* @return*/public int getLength(HeroNode head){int length = 0;HeroNode temp = head;if (head.next==null){return 0;}while (temp.next!=null){length++;temp = temp.next;}return length;}

2.2 查找單鏈表中倒數第K個節點

/*** 查找鏈表中倒數第K個節點* @param head* @param index* @return*/public HeroNode findLastIndexNode(HeroNode head,int index){//index表示倒數第index個節點//獲取鏈表長度int length = getLength(head);HeroNode temp = head.next;if (head.next==null){return null;}//從第一個開始遍歷length - index就可以得到倒數第index個節點int signal = length - index;if (index <= 0 || index > length){return null;}for (int i = 0; i <signal ; i++) {temp=temp.next;}return temp;}

2.3 單鏈表的反轉

思路:

  • 定義一個新的頭結點reverseHead.
  • 遍歷原來的鏈表,每遍歷一個節點就將其取出,放在新鏈表最前端
  • 原來鏈表的head.next = reverseHead
  • /*** 單鏈表的反轉* @param head*/public void reverseList(HeroNode head){//如果鏈表為空或只有一個節點,那么直接返回if (head.next==null || head.next.next==null){return;}//創建一個新的頭結點HeroNode reverseHead = new HeroNode(0,"","");HeroNode cur = head.next;HeroNode next = null;while (cur!=null){next =cur.next;//保存當前節點的下一個節點//將cur的下一個節點指向鏈表的最前端cur.next = reverseHead.next;//將cur連接到cur的下一個節點和頭結點之間。reverseHead.next = cur;//后移cur = next;}//將頭結點指向反轉后的頭結點,實現反轉head.next = reverseHead.next;}

    2.4 逆序打印單鏈表

    要求:反向遍歷,用棧實現

    /*** 單鏈表逆序輸出(用棧實現)* @param head*/public void reversePrint(HeroNode head){if (head.next==null){return;}HeroNode cur = head.next;Stack<HeroNode> stack = new Stack<>();while (cur!=null){stack.add(cur);//將鏈表的節點壓入棧cur = cur.next;}while (stack.size()>0){System.out.println(stack.pop());//先進后出輸出}}

    2.5 合并兩個單鏈表,合并后依然有序

    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {if (l1 == null) return l2;if (l2 == null) return l1;ListNode head = null;if (l1.val <= l2.val){head = l1;head.next = mergeTwoLists(l1.next, l2);} else {head = l2;head.next = mergeTwoLists(l1, l2.next);}return head; }

    3. 雙鏈表應用實例

    3.1 單鏈表缺點

    管理單向鏈表的缺點分析:

  • 單向鏈表,查找的只能是一個方向,而雙向鏈表可以向前或者向后查找
  • 單向鏈表不能自我刪除,需要靠輔助節點,而雙向鏈表,則可以自我刪除,所以前面單鏈表刪除,總是找到temp,temp是待刪除節點的前一個節點。
  • 下面用雙鏈表來實現上面的增刪改查功能。

    3.2 實現思路

    遍歷:和單鏈表一樣,但是既可以向前遍歷也可以向后遍歷
    添加(默認添加到雙向鏈表最后): 先找到雙向鏈表最后的一個節點

    temp.next = heroNode heroNode.pre = temp;

    修改 :和單鏈表思路一樣
    刪除:因為是雙向鏈表,所以可以自我刪除,直接找到要刪除的節點

    temp.pre.next = temp.next; temp.next.pre = temp.pre;

    3.3 代碼實現

    public class DoubleLinkedListDemo {public static void main(String[] args) {HeroNode2 hero1 = new HeroNode2(1,"伊澤瑞爾","冒險家");HeroNode2 hero2 = new HeroNode2(2,"拉克絲","光輝女郎");HeroNode2 hero3 = new HeroNode2(3,"亞索","疾風劍豪");HeroNode2 hero4 = new HeroNode2(4,"盧錫安","圣槍游俠");HeroNode2 hero2New = new HeroNode2(2,"佐伊","暮光星靈");DoubleLinkedList list = new DoubleLinkedList();//添加節點list.add(hero1);list.add(hero2);list.add(hero3);list.add(hero4);System.out.println("----------------遍歷-----------------");list.traverse();System.out.println("----------------修改后-----------------");list.update(hero2New);list.traverse();System.out.println("----------------刪除后-----------------");list.del(3);list.traverse();}} class DoubleLinkedList{//創建一個頭節點,頭節點不能動,不存放具體的數據private HeroNode2 head = new HeroNode2(0,"","");public void setHead(HeroNode2 head) {this.head = head;}public HeroNode2 getHead() {return head;}/*** 在鏈表的最后添加節點*/public void add(HeroNode2 heroNode){//頭結點不能動,創建一個輔助節點HeroNode2 temp = head;//找到最后一個節點while (temp.next!=null){temp = temp.next;}//將新節點添加到節點的最后temp.next = heroNode;heroNode.pre = temp;}/*** 遍歷鏈表*/public void traverse(){if (head.next == null){System.out.println("鏈表為空");return;}HeroNode2 temp = head.next;while (temp!=null){System.out.println(temp);temp=temp.next;}}/*** 修改鏈表節點*/// 修改一個節點的內容, 可以看到雙向鏈表的節點內容修改和單向鏈表一樣// 只是 節點類型改成 HeroNode2public void update(HeroNode2 newHeroNode) {// 判斷是否空if (head.next == null) {System.out.println("鏈表為空~");return;}// 找到需要修改的節點, 根據no編號// 定義一個輔助變量HeroNode2 temp = head.next;boolean flag = false; // 表示是否找到該節點while (true) {if (temp == null) {break; // 已經遍歷完鏈表}if (temp.no == newHeroNode.no) {// 找到flag = true;break;}temp = temp.next;}// 根據flag 判斷是否找到要修改的節點if (flag) {temp.name = newHeroNode.name;temp.nickName = newHeroNode.nickName;} else { // 沒有找到System.out.printf("沒有找到 編號 %d 的節點,不能修改\n", newHeroNode.no);}}/*** 刪除節點*/public void del(int no) {// 判斷當前鏈表是否為空if (head.next == null) {// 空鏈表System.out.println("鏈表為空,無法刪除");return;}HeroNode2 temp = head.next; // 輔助變量(指針)boolean flag = false; // 標志是否找到待刪除節點的while (true) {if (temp == null) { // 已經到鏈表的最后break;}if (temp.no == no) {flag = true;break;}temp = temp.next; // temp后移,遍歷}// 判斷flagif (flag) { // 找到// 可以刪除// temp.next = temp.next.next;[單向鏈表]temp.pre.next = temp.next;// 這里我們的代碼有問題?// 如果是最后一個節點,就不需要執行下面這句話,否則出現空指針if (temp.next != null) {temp.next.pre = temp.pre;}} else {System.out.printf("要刪除的 %d 節點不存在\n", no);}} } class HeroNode2{public int no;//序號public String name;public String nickName;public HeroNode2 next;//指向下一個節點public HeroNode2 pre;//指向前一個節點public HeroNode2(int no, String name, String nickName) {this.no = no;this.name = name;this.nickName = nickName;}@Overridepublic String toString() {return "HeroNode{" +"no=" + no +", name='" + name + '\'' +", nickName='" + nickName + '\'' +'}';} }

    總結

    以上是生活随笔為你收集整理的(数据结构与算法)单链表与双链表增删改查的实现。的全部內容,希望文章能夠幫你解決所遇到的問題。

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