最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java數(shù)據(jù)結(jié)構(gòu)之鏈表實(shí)現(xiàn)(單向、雙向鏈表及鏈表反轉(zhuǎn))

 更新時(shí)間:2021年06月02日 09:47:55   作者:放肆的青春゛つ  
這篇文章主要給大家介紹了關(guān)于Java數(shù)據(jù)結(jié)構(gòu)之鏈表實(shí)現(xiàn)的相關(guān)資料,其中包括單向鏈表、雙向鏈表及鏈表反轉(zhuǎn)的實(shí)現(xiàn)代碼,需要的朋友可以參考下

前言

之前學(xué)習(xí)的順序表查詢(xún)非常快,時(shí)間復(fù)雜度為O(1),但是增刪改效率非常低,因?yàn)槊恳淮卧鰟h改都會(huì)元素的移動(dòng)??梢允褂昧硪环N存儲(chǔ)方式-鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)。

鏈表是一種物理存儲(chǔ)單元上非連續(xù)、非順序的存儲(chǔ)結(jié)構(gòu)。鏈表由一序列的結(jié)點(diǎn)(鏈表中的每一個(gè)元素成為結(jié)點(diǎn))組成。

結(jié)點(diǎn)API設(shè)計(jì)

類(lèi)名 Node
構(gòu)造方法 Node(T t,Node next) 創(chuàng)建Node對(duì)象
成員變量

T item:存儲(chǔ)數(shù)據(jù)

Node next :指向下一個(gè)結(jié)點(diǎn)

結(jié)點(diǎn)類(lèi)

public class Node<T>{
    Node next;
    private T item;
 
    public Node(Node next, T item) {
        this.next = next;
        this.item = item;
    }
}

生成鏈表

public class TestNode {
    public static void main(String[] args) {
        // 生成結(jié)點(diǎn)
        Node<Integer> one = new Node<Integer>(null,12);
        Node<Integer> two = new Node<Integer>(null,16);
        Node<Integer> three = new Node<Integer>(null,11);
        Node<Integer> four = new Node<Integer>(null,10);
        //生成鏈表
        one.next = two;
        two.next = three;
        three.next =four;
    }
}

1、單鏈表

單向鏈表是鏈表的一種,它有多個(gè)結(jié)點(diǎn)組成每個(gè)結(jié)點(diǎn)都由一個(gè)數(shù)據(jù)域一個(gè)指針組成,數(shù)據(jù)域用來(lái)存儲(chǔ)數(shù)據(jù)指針域用來(lái)指向其后結(jié)點(diǎn)。

鏈表的頭結(jié)點(diǎn)數(shù)據(jù)域不存儲(chǔ)數(shù)據(jù),指針域指向第一個(gè)真正存儲(chǔ)數(shù)據(jù)的結(jié)點(diǎn)。

單向鏈表API設(shè)計(jì)

類(lèi)名 LinkList
構(gòu)造方法 LinkList() :創(chuàng)建LinkList對(duì)象
成員變量

private Node head;記錄首結(jié)點(diǎn)

private int N; 記錄鏈表的長(zhǎng)度

成員內(nèi)部類(lèi) private class Node;結(jié)點(diǎn)類(lèi)
成員方法
public void clear() 清空鏈表
public boolean isEmpty() 判斷鏈表是否為空,是返回true
public int length() 獲取鏈表中的元素個(gè)數(shù)
public T get(int i) 讀取并返回鏈表中的第i個(gè)元素的值

public void insert(T t)

往鏈表中插入一個(gè)元素
public void insert(T t,int i) 在鏈表的第i位置插入一個(gè)值為t的數(shù)據(jù)元素
public T remove(int i) 刪除并返回刪除鏈表中的第i個(gè)數(shù)據(jù)元素
public int indexof(T t) 返回鏈表中首次出現(xiàn)的指定的數(shù)據(jù)元素的序號(hào),如不存在,則返回-1

單向鏈表Java代碼實(shí)現(xiàn)

package com.ycy.Algorithm.LinkList;
 
 
import java.util.Iterator;
 
/**
 * 鏈表的head是不可以動(dòng)的
 * @param <T>
 */
public class LinkList<T> implements Iterable<T>{
 
    private Node head;//頭結(jié)點(diǎn),鏈表的head是不可以動(dòng)的
    private int N;//結(jié)點(diǎn)個(gè)數(shù)
    public LinkList() {
        this.head = new Node(null,null);
        N = 0;
    }
    /**
     * 結(jié)點(diǎn)內(nèi)部類(lèi)
     */
    private class Node{
        //存儲(chǔ)數(shù)據(jù)
        T item;
        //下一個(gè)結(jié)點(diǎn)
        Node next;
        public Node(T item,Node next) {
            this.item = item;
            this.next = next;
        }
 
    }
    /**
     * 清空鏈表
     */
    public void clear(){
        head.item=null;
        head.next=null;// 頭節(jié)點(diǎn)next為null就是空鏈表
        this.N=0;
    }
    /**
     * 判斷鏈表是否為空
     */
    public boolean isEmpty(){
        return this.N==0;
    }
    /**
     * 獲取鏈表的長(zhǎng)度
     */
    public int length(){
        return this.N;
    }
    /**
     * 讀取鏈表第i位置的元素值并返回
     */
    public T get(int i){
        //非法性檢查
        if(i<0 || i > this.N){
            throw new RuntimeException("位置不合法");
        }
        // n也是指向頭結(jié)點(diǎn)
        Node n = head;
        for(int index=0; index<i; index++){
            n = n.next;
        }
        return n.item;
    }
    /**
     * 往鏈表中插入數(shù)據(jù)t
     */
    public void insert(T t){
        // head不可以移動(dòng),不然就無(wú)法在找到鏈表
        // 定義一個(gè)臨時(shí)的Node也指向head的指針就可以通過(guò)移動(dòng)該指針就可以
        Node n = head;
        // 獲取尾節(jié)點(diǎn)
        while(true){
            // 當(dāng)剛好就一個(gè)節(jié)點(diǎn)時(shí)(頭節(jié)點(diǎn))
            if(n.next == null){
                break;
            }
            n = n.next;
        }
        //當(dāng)為空表時(shí),就可以插入
        Node node = new Node(t, null);
        n.next =node;
        this.N ++;
    }
 
    /**
     * 在第i位置上插入數(shù)據(jù)t
     */
    public void insert(T t,int i){
        // 非法性檢查
        if(i < 0 || i > this.N){
            throw  new RuntimeException("插入位置❌");
        }
        Node pre = head;
        for(int index=0;index <= i-1; index++){
            pre = pre.next;
        }
        Node current = pre.next;
        //先鏈接后面結(jié)點(diǎn)
        Node newNode = new Node(t,null);
        pre.next = newNode;
        newNode.next = current;
        this.N++;
    }
    /**
     * 移除并返回第i位置的元素值
     */
    public  T remove(int i){
        // 非法性檢查
        if(i < 0 || i >this.N){
            throw  new RuntimeException("刪除位置有誤");
        }
        Node n =head;
        for(int index=0;index <= i-1;index ++){
             n = n.next;
        }
        //要?jiǎng)h除的節(jié)點(diǎn)
        Node curr = n.next;
        n.next = curr.next;
        this.N--;//結(jié)點(diǎn)個(gè)數(shù)減一
        return curr.item;
    }
    //查找元素t在鏈表中第一次出現(xiàn)的位置
    public int indexof(T t){
        Node n = head;
        for(int i = 0; n.next != null;i++){
            n =n.next;
            if(n.item.equals(t)){
                return i;
            }
        }
        return -1;
    }
 
    @Override
    public Iterator iterator() {
        return new Iterator() {
            Node n =head;
            @Override
            public boolean hasNext() {
                return n.next !=null;
            }
            @Override
            public Object next() {
                //下移一個(gè)指針
                n = n.next;
                return n.item;
            }
        };
    }
}

 補(bǔ)充一點(diǎn)鏈表的賦值給新的鏈表后,兩個(gè)鏈表是會(huì)相會(huì)影響的,說(shuō)白了就是把地址賦值給它了,他們操作是同一塊內(nèi)存的同一個(gè)對(duì)象。Node n = head;把head賦值給n,現(xiàn)在對(duì)n操作也是會(huì)影響head的

其中提供遍歷方式,實(shí)現(xiàn)Iterable接口。

測(cè)試代碼:

public class test {
    public static void main(String[] args) {
        LinkList<Integer>linkList = new LinkList<>();
        linkList.insert(1);
        linkList.insert(2);
        linkList.insert(4);
        linkList.insert(3);
        linkList.insert(1,2);
        for (Integer i : linkList) {
            System.out.print(i+" ");
        }
    }
}

運(yùn)行結(jié)果:

D:\Java\jdk-12.0.2\bin\java.exe "-javaagent:D:\IDEA\IntelliJ IDEA 2019.1\lib\idea_rt.jar=3542:D:\IDEA\IntelliJ IDEA 2019.1
1 2 1 4 3 

學(xué)習(xí)完鏈表還是需要加以練習(xí)的,可以在LeetCode上刷題加深理解。

2、雙向鏈表

頭插法:新增節(jié)點(diǎn)總是插在頭部

便于理解可以畫(huà)圖表示

頭插法:原圖,node是待插入的結(jié)點(diǎn).

插入后圖:

關(guān)鍵性代碼:

尾插法:新增節(jié)點(diǎn)總是插在尾部

原圖如下: 

 

插入結(jié)點(diǎn)后圖如下:

關(guān)鍵性代碼:

中間任意位置插入

插入之前的原圖: 

 

插入到鏈表中間位置:

關(guān)鍵性代碼:

代碼演示:

class MyLinkedList {
    Node head;//定義雙向鏈表的頭節(jié)點(diǎn)
    Node last;//定義雙向鏈表的尾節(jié)點(diǎn)
 
    //打印雙向鏈表
    public void disPlay() {
        Node cur = this.head;
        while (cur != null) {
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
        System.out.println();
    }
 
    //求雙向鏈表的長(zhǎng)度(之后addIndex代碼會(huì)用到)
    public int size() {
        int count = 0;
        Node cur = this.head;
        while (cur != null) {
            count++;
            cur = cur.next;
        }
        return count;
    }
 
    //頭插法
    public void addFirst(int data) {
        Node node = new Node(data);//定義一個(gè)用作插入的節(jié)點(diǎn)
        //1.假設(shè)雙向鏈表為空
        if (this.head == null) {
            this.head = node;
            this.last = node;
        } else {
            //2.雙向鏈表不為空的情況下
            //不懂請(qǐng)看上面的圖解,就很簡(jiǎn)單了
            node.next = this.head;
            this.head.prev = node;
            this.head = node;
        }
    }
 
    //尾插法(與頭插法類(lèi)似)
    public void addLast(int data) {
        //定義一個(gè)用作插入的節(jié)點(diǎn)
        Node node = new Node(data);
        //1.假設(shè)雙向鏈表為空
        if (this.head == null) {
            this.head = node;
            this.last = node;
        } else {
            //2.雙向鏈表不為空的情況下
            //不懂請(qǐng)看上面的圖解,就很簡(jiǎn)單了
            last.next = node;
            node.prev = last;
            last = node;
        }
    }
 
    //在任意位置插入
    public void addIndex(int index, int data) {//形參index為插入元素位置,data為插入的數(shù)值
        //定義一個(gè)用作插入的節(jié)點(diǎn)
        Node node = new Node(data);
        Node cur = this.head;//定義一個(gè)cur用作遍歷雙向鏈表
        //1、判斷插入位置的合法性
        if (index < 0 || index > size()) {
            System.out.println("插入位置不合法!??!");
            return;
        }
        //2、假設(shè)插入位置為頭結(jié)點(diǎn)的情況下,即就是頭插法
        if (index == 0) {
            addFirst(data);//調(diào)用頭插法代碼
            return;
        }
        //3、假設(shè)插入位置為尾結(jié)點(diǎn)的情況下,即就是尾插法
        if (index == size()) {
            addLast(data);//調(diào)用尾插法代碼
            return;
        }
        //4、在中間任意位置的情況下
        while (index != 0) {
            cur = cur.next;
            index--;
        }
        //不懂請(qǐng)看上面的圖解,就很簡(jiǎn)單了
        //核心代碼
        node.next = cur;
        node.prev = cur.prev;
        cur.prev = node;
        node.prev.next = node;
    }
}
 
//雙向鏈表的節(jié)點(diǎn)結(jié)構(gòu)
class Node {
    int val;
    Node prev;
    Node next;
 
    Node(int val) {
        this.val = val;
    }
}

3、鏈表反轉(zhuǎn)

public void reverse(){
        if(N==0){
        //當(dāng)前是空鏈表,不需要反轉(zhuǎn)
            return;
        }
        reverse(head.next);
}
    /**
     * @param curr 當(dāng)前遍歷的結(jié)點(diǎn)
     * @return 反轉(zhuǎn)后當(dāng)前結(jié)點(diǎn)上一個(gè)結(jié)點(diǎn)
     */
public Node reverse(Node curr){
        //已經(jīng)到了最后一個(gè)元素
        if(curr.next==null){
        //反轉(zhuǎn)后,頭結(jié)點(diǎn)應(yīng)該指向原鏈表中的最后一個(gè)元素
          head.next=curr;
          return curr;
        }
       //當(dāng)前結(jié)點(diǎn)的上一個(gè)結(jié)點(diǎn)
       Node pre=reverse(curr.next);
       pre.next=curr;
       //當(dāng)前結(jié)點(diǎn)的下一個(gè)結(jié)點(diǎn)設(shè)為null
       curr.next=null;
       //返回當(dāng)前結(jié)點(diǎn)
       return curr;
}

總結(jié)

到此這篇關(guān)于Java數(shù)據(jù)結(jié)構(gòu)之鏈表實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Java數(shù)據(jù)結(jié)構(gòu)鏈表內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot3整合SpringSecurity6快速入門(mén)示例教程

    SpringBoot3整合SpringSecurity6快速入門(mén)示例教程

    SpringSecurity 是Spring大家族中一名重要成員,是專(zhuān)門(mén)負(fù)責(zé)安全的框架,本文給大家介紹SpringBoot3整合SpringSecurity6快速入門(mén)示例教程,感興趣的朋友一起看看吧
    2025-04-04
  • springboot整合springsecurity與mybatis-plus的簡(jiǎn)單實(shí)現(xiàn)

    springboot整合springsecurity與mybatis-plus的簡(jiǎn)單實(shí)現(xiàn)

    Spring Security基于Spring開(kāi)發(fā),項(xiàng)目中如果使用Spring作為基礎(chǔ),配合Spring Security做權(quán)限更加方便,而Shiro需要和Spring進(jìn)行整合開(kāi)發(fā)。因此作為spring全家桶中的Spring Security在java領(lǐng)域很常用
    2021-10-10
  • SpringBoot中自定義參數(shù)綁定步驟詳解

    SpringBoot中自定義參數(shù)綁定步驟詳解

    這篇文章主要介紹了SpringBoot中自定義參數(shù)綁定步驟詳解,非常不錯(cuò),具有參考借鑒價(jià)值 ,需要的朋友可以參考下
    2018-02-02
  • java網(wǎng)上商城開(kāi)發(fā)之郵件發(fā)送功能(全)

    java網(wǎng)上商城開(kāi)發(fā)之郵件發(fā)送功能(全)

    這篇文章主要介紹了java網(wǎng)上商城開(kāi)發(fā)之郵件發(fā)送功能,第一部分介紹了環(huán)境配置,第二部分則介紹了具體實(shí)現(xiàn)代碼,感興趣的小伙伴們可以參考一下
    2016-03-03
  • Java源碼解析之Iterable接口

    Java源碼解析之Iterable接口

    遍歷集合我相信大部分coder都會(huì)遇到,也經(jīng)常使用,而Java給我們提供了多種選擇,接下來(lái)就讓我們一起來(lái)看看吧,需要的朋友可以參考下
    2021-05-05
  • 使用IDEA搭建SSM框架的詳細(xì)教程(spring + springMVC +MyBatis)

    使用IDEA搭建SSM框架的詳細(xì)教程(spring + springMVC +MyBatis)

    這篇文章主要介紹了使用IDEA搭建SSM框架的詳細(xì)教程 spring + springMVC +MyBatis,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-05-05
  • 史上最全的java隨機(jī)數(shù)生成算法分享

    史上最全的java隨機(jī)數(shù)生成算法分享

    這篇文章主要介紹了史上最全的java隨機(jī)數(shù)生成算法,我分享一個(gè)最全的隨機(jī)數(shù)的生成算法,最代碼的找回密碼的隨機(jī)數(shù)就是用的這個(gè)方法
    2014-01-01
  • SpringBoot工程打包與運(yùn)行的實(shí)現(xiàn)詳解

    SpringBoot工程打包與運(yùn)行的實(shí)現(xiàn)詳解

    本文主要介紹了SpringBoot工程的打包與運(yùn)行的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • 使用SpringAop動(dòng)態(tài)獲取mapper執(zhí)行的SQL,并保存SQL到Log表中

    使用SpringAop動(dòng)態(tài)獲取mapper執(zhí)行的SQL,并保存SQL到Log表中

    這篇文章主要介紹了使用SpringAop動(dòng)態(tài)獲取mapper執(zhí)行的SQL,并保存SQL到Log表中問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Java定時(shí)任務(wù)取消的示例代碼

    Java定時(shí)任務(wù)取消的示例代碼

    java定時(shí)任務(wù)如何取消,并比如,我之前想每周二晚上6點(diǎn)自動(dòng)生成一條devops流水線(xiàn),現(xiàn)在我想停掉,下面給大家分享java定時(shí)任務(wù)取消的示例代碼,演示如何創(chuàng)建一個(gè)每周二晚上6點(diǎn)自動(dòng)生成一條devops流水線(xiàn)的定時(shí)任務(wù),感興趣的朋友一起看看吧
    2024-02-02

最新評(píng)論

车致| 泸州市| 三都| 佳木斯市| 天祝| 东平县| 淮阳县| 雷州市| 宽城| 焦作市| 隆尧县| 桦甸市| 宣恩县| 西盟| 广州市| 沅江市| 隆子县| 嘉定区| 黔东| 尖扎县| 静安区| 大厂| 民乐县| 阳高县| 乐都县| 陇南市| 兴仁县| 济南市| 平遥县| 剑河县| 桐庐县| 离岛区| 北海市| 长沙市| 凉山| 吉安市| 梧州市| 鄂托克旗| 贵州省| 乐亭县| 龙南县|