Java实现单链表(步骤详解+源码)

Java实现单链表(附源码)


前言

此文章主要实现单链表的基本操作。
我也是一位学习者,如果有任何问题,欢迎私信交流学习!


提示:以下是本篇文章正文内容,下面案例可供参考

一、学习目的

  1. 理解线性表的逻辑结构;
  2. 理解单链表的存储结构特点,掌握单链表的存储分配要点;
  3. 掌握单链表的基本操作及实现,并能正确分析其时间复杂度;

二、主要内容

1.定义单链表的存储结构

首先我们需要定义两个类:结点类(Node)、单链表(SingleLinkList)
结点类主要用于存储数据和下一个结点的地址
单链表主要用于存储结点以及基本操作

代码如下(示例):

结点类(Node)

public class LinkListNode {

    private Integer data; // 结点的数据域

    private LinkListNode next; // 下一个结点
}

单链表(SingleLinkList)

public class SingleLinkList {

    private LinkListNode head;//定义单链表的头结点

    private int length;//用来记录单链表的长度

}

2.单链表的基本操作及实现

  1. 初始化单链表(无参和有参)
    我对链表的初始化有点不太理解,因为存在有参和无参构造,但是在java语言中本来就存在无参构造;
    这里就强行解释一波:
    · 无参构造理解为初始化单链表(包含头结点)
    · 有参构造理解为初始化单链表和首元结点(包含头结点和首元结点)
	/**
     * 单链表的初始化 init() 无参
     */
    public SingleLinkList(){
        this.head = new LinkListNode();
    }

    /**
     * 单链表的初始化 init() 有参
     * */
    public SingleLinkList(Integer data,LinkListNode next){
        this.head = new LinkListNode();
        LinkListNode node = new LinkListNode();
        node.setData(data);
        node.setNext(next);
        head.setNext(node);
    }

  1. 求单链表长度
    在我的单链表类中属性包含了长度,这样就可以通过空间换时间,当需要获取单链表的长度时,可以直接访问属性而无需遍历单链表 。
	/**
     * 求单链表长度
     */
    public int getLength(){
        return length;
    }
  1. 新增:默认在最后插入一个数据元素
    创建一个p指针,用于遍历单链表找到最后一个元素,然后将新结点的地址赋给最后一个结点的下一个地址。
    这种情况下是这样的:
    · 单链表:1,2,3,4,5
    · 新增:插入“99”
    · 结果:1,2,3,4,5,99
	/**
     * 新增:默认在最后插入一个数据元素;
     */
    public LinkListNode insert(Integer data){
        LinkListNode newNode = new LinkListNode(data);
        LinkListNode p = head;
        while (p.getNext()!=null){
            p = p.getNext();
        }
        p.setNext(newNode);
        length++;
        return newNode;
    }
  1. 新增:在位置i插入一个数据元素
    这个要首先判断这个位置i是否大于了单链表的长度,比如此时单链表的长度为4,输入的位置i为6,显然位置5都还没有结点,所以我默认将这个新结点添加在单链表的末尾;
    这种情况下是这样的:
    · 单链表:1,2,3,4,5
    · 新增:在第3个位置插入“99”
    · 结果:1,99,2,3,4,5
	/**
     * 新增:在位置i插入一个数据元素;
     */
    public void insertByIndex(int index,Integer data){
        // 如果位置i大于了单链表的长度 或者 位置不合理 则直接将新结点添加到最后
        if(index>length||index-1<0){
            insert(data);
            return;
        }
        index--;
        // 将指针p指向首元结点
        LinkListNode p = head;
        while (index!=0){
            p=p.getNext();
            index--;
        }
        LinkListNode newNode = new LinkListNode(data,p.getNext());
        p.setNext(newNode);
        length++;
    }
  1. 查找:按位置查找
    第一步:判定输入的位置是否大于单链表长度(大于则直接返回null)
    第二步:通过p指针移动到指定的位置,获取数据元素
	/**
     * 查找:按位置查找
     */
    public Integer getByIndex(int index){
        // 如果查找的元素大于了单链表的长度则返回null
        if(index>length){
            return null;
        }
        // 将指针p指向头结点
        LinkListNode p = head;
        while (index!=0){
            p=p.getNext();
            index--;
        }
        return p.getData();
    }
  1. 查找:按值查找
    通过移动p指针,取出每一个结点的数据元素与输入的值进行对比,如果发现数据匹配的结点,就返回结点位置;如果单链表都遍历完了还没有找到就返回0,因为我的单链表位置是从1开始计算的,返回0就表示未找到。
	/**
     * 查找:按值查找
     */
    public int getByData(Integer data){
        // 将指针p指向首元结点
        LinkListNode p = head;
        int index = 0;
        while (p.getNext()!=null){
            p=p.getNext();
            index++;
            if(p.getData().equals(data)){
                return index;
            }
        }
        if(index==length&&!p.getData().equals(data)){
            return 0;
        }
        return index;
    }
  1. 查找:遍历单链表
    创建p结点做为指针,遍历单链表。
 	/**
     * 查找:遍历单链表
     */
    public void traverse(){
        LinkListNode p = head;
        while (p.getNext()!=null){
            p = p.getNext();
            System.out.println("结点值:"+p.getData());
        }
    }
  1. 删除:按位置i删除数据元素
    第一步:判定位置i是否大于单链表的长度(是就返回null)
    第二步:将p指针移动到被删除元素的前一个位置,主要是为了断开删除元素的连接,连接下一个结点的地址。
	 /**
     * 删除:按位置i删除数据元素;
     */
    public Integer deleteByIndex(int index){
        // 如果位置i大于了单链表的长度则返回null
        if(index>length||index-1<0){
            return null;
        }
        // 提前将index-- 是为了将p指针移到被删除元素的前一个位置
        index--;
        // 将指针p指向头结点
        LinkListNode p = head;
        while (index!=0){
            p=p.getNext();
            index--;
        }
        int res = p.getNext().getData();
        p.setNext(p.getNext().getNext());
        length--;
        return res;
    }
  1. 合并链表
    直接将第二个链表的首元结点的地址赋值给第一个链表的最后一个结点的地址域。
	/**
     * 合并链表
     */
    public void marge(SingleLinkList singleLinkList){
        LinkListNode p = head;
        length=length+singleLinkList.length;
        while (p.getNext()!=null){
            p = p.getNext();
        }
        p.setNext(singleLinkList.head.getNext());
    }

3.完整代码

结点类:LinkListNode

package experiment_01;

public class LinkListNode {

    private Integer data; // 结点的数据域

    private LinkListNode next; // 下一个结点

    public LinkListNode(){
    }

    public LinkListNode(Integer data){
        this.data = data;
        this.next = null;
    }
    public LinkListNode(Integer data,LinkListNode next){
        this.data = data;
        this.next = next;
    }

    public Integer getData() {
        return data;
    }

    public void setData(Integer data) {
        this.data = data;
    }

    public LinkListNode getNext() {
        return next;
    }

    public void setNext(LinkListNode next) {
        this.next = next;
    }


}

单链表类:SingleLinkList

public class SingleLinkList {

    private LinkListNode head;//定义单链表的头结点

    private int length;//用来记录单链表的长度

    /**
     * 单链表的初始化 init() 无参
     */
    public SingleLinkList(){
        this.head = new LinkListNode();
    }

    /**
     * 单链表的初始化 init() 有参
     * */
    public SingleLinkList(Integer data,LinkListNode next){
        this.head = new LinkListNode();
        LinkListNode node = new LinkListNode();
        node.setData(data);
        node.setNext(next);
        head.setNext(node);
    }

    /**
     * 求单链表长度
     */
    public int getLength(){
        return length;
    }

    /**
     * 新增:默认在最后插入一个数据元素;
     */
    public LinkListNode insert(Integer data){
        LinkListNode newNode = new LinkListNode(data);
        LinkListNode p = head;
        while (p.getNext()!=null){
            p = p.getNext();
        }
        p.setNext(newNode);
        length++;
        return newNode;
    }

    /**
     * 新增:在位置i插入一个数据元素;
     */
    public void insertByIndex(int index,Integer data){
        // 如果位置i大于了单链表的长度 或者 位置不合理 则直接将新结点添加到最后
        if(index>length||index-1<0){
            insert(data);
            return;
        }
        index--;
        // 将指针p指向首元结点
        LinkListNode p = head;
        while (index!=0){
            p=p.getNext();
            index--;
        }
        LinkListNode newNode = new LinkListNode(data,p.getNext());
        p.setNext(newNode);
        length++;
    }

    /**
     * 查找:按位置查找
     */
    public Integer getByIndex(int index){
        // 如果查找的元素大于了单链表的长度则返回null
        if(index>length){
            return null;
        }
        // 将指针p指向头结点
        LinkListNode p = head;
        while (index!=0){
            p=p.getNext();
            index--;
        }
        return p.getData();
    }

    /**
     * 查找:按值查找
     */
    public int getByData(Integer data){
        // 将指针p指向首元结点
        LinkListNode p = head;
        int index = 0;
        while (p.getNext()!=null){
            p=p.getNext();
            index++;
            if(p.getData().equals(data)){
                return index;
            }
        }
        if(index==length&&!p.getData().equals(data)){
            return 0;
        }
        return index;
    }

    /**
     * 查找:遍历单链表
     */
    public void traverse(){
        LinkListNode p = head;
        while (p.getNext()!=null){
            p = p.getNext();
            System.out.println("结点值:"+p.getData());
        }
    }

    /**
     * 删除:按位置i删除数据元素;
     */
    public Integer deleteByIndex(int index){
        // 如果位置i大于了单链表的长度则返回null
        if(index>length||index-1<0){
            return null;
        }
        // 提前将index-- 是为了将p指针移到被删除元素的前一个位置
        index--;
        // 将指针p指向头结点
        LinkListNode p = head;
        while (index!=0){
            p=p.getNext();
            index--;
        }
        int res = p.getNext().getData();
        p.setNext(p.getNext().getNext());
        length--;
        return res;
    }

    /**
     * 合并链表
     */
    public void marge(SingleLinkList singleLinkList){
        LinkListNode p = head;
        length=length+singleLinkList.length;
        while (p.getNext()!=null){
            p = p.getNext();
        }
        p.setNext(singleLinkList.head.getNext());
    }
}

测试类:LinkListTest

import java.util.Scanner;

public class LinkListTest {

    public static void main(String[] args){
        // 初始化单链表
        SingleLinkList singleLinkList = new SingleLinkList();

        // 在链表尾部新增结点
        singleLinkList.insert(15);
        singleLinkList.insert(16);
        singleLinkList.insert(17);
        singleLinkList.insert(18);

        Scanner scanner = new Scanner(System.in);
        int operation = 0;
        printList(singleLinkList);
        while (operation!=-1) {
            System.out.println("请选择一个操作:\n 1、遍历输出单链表 \n 2、根据位置查找结点的值 \n 3、根据值查找结点的位置 " +
                    "\n 4、在指定位置插入一个数据元素 \n 5、根据位置删除结点 \n 6、合并一个链表给你看看就行 \n 7、退出程序");
            operation = scanner.nextInt();
            switch (operation) {
                case 1:
                    // 遍历输出单链表
                    printList(singleLinkList);
                    break;
                case 2:
                    System.out.println("请问你要查找第几个结点的值?");
                    int index = scanner.nextInt();
                    System.out.println("第" + index + "个结点的值:" + singleLinkList.getByIndex(index));
                    break;
                case 3:
                    System.out.println("请问你要查找值为多少的结点位置?");
                    Integer data = scanner.nextInt();
                    System.out.println("值为" + data + "的结点位置:" + singleLinkList.getByData(data));
                    break;
                case 4:
                    System.out.println("请问你要在第几个位置插入结点?");
                    index = scanner.nextInt();
                    System.out.println("请问你要插入值为多少的结点?");
                    data = scanner.nextInt();
                    singleLinkList.insertByIndex(index, data);
                    break;
                case 5:
                    System.out.println("请问你要删除哪个位置的结点?");
                    index = scanner.nextInt();
                    singleLinkList.deleteByIndex(index);
                    break;
                case 6:
                    SingleLinkList singleLinkList2 = new SingleLinkList();
                    singleLinkList2.insert(1);
                    singleLinkList2.insert(2);
                    singleLinkList2.insert(3);
                    singleLinkList.marge(singleLinkList2);
                    break;
                default:
                    System.exit(0);
            }
        }
    }

    public static void printList(SingleLinkList singleLinkList){
        System.out.println("单链表的长度:"+singleLinkList.getLength());
        singleLinkList.traverse();
    }

}

希望大家可以一次性运行成功喔!

总结

对不起了大家,今天没时间写了,下次补上。

  • 11
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论
Java实现OPC UA的步骤如下: 第一步,首先需要引入OPC UA的Java开发库。目前市场上有很多供应商提供的OPC UA开发库,选择适合自己的库进行引用。这些库通常包含了OPC UA的客户端和服务器代码。 第二步,编写OPC UA客户端代码。OPC UA客户端主要用于与OPC UA服务器进行通信。通过在Java程序中引入OPC UA库提供的相关类和接口,可以创建一个OPC UA客户端实例。然后,通过该实例可以实现与服务器的连接、节点浏览、读写数据等功能。 第三步,编写OPC UA服务器代码。OPC UA服务器主要用于提供OPC UA服务,允许客户端与其进行通信。类似地,通过引入OPC UA库提供的相关类和接口,可以创建一个OPC UA服务器实例。然后,可以定义自己的节点和数据模型,并实现相应的方法用于处理客户端请求。 第四步,配置OPC UA服务器。将OPC UA服务器配置为可以被客户端访问,可以通过修改配置文件或者在代码中设置服务器的IP地址和端口号来实现。 第五步,测试和调试。在完成客户端和服务器的编写后,可以通过启动客户端和服务器来对其进行测试和调试。通过客户端可以访问服务器的节点并读写数据,通过服务器可以查看客户端请求并进行相应的响应。 总结起来,Java实现OPC UA的过程涉及到引入OPC UA库、编写客户端和服务器代码、配置服务器以及测试和调试。通过这些步骤,可以实现Java程序与OPC UA服务器的交互,实现数据的读写和通信。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PRINT!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值