java实现单链表的常用操作(逆序、插入、遍历等)

java实现单链表的常用操作(逆序、插入、遍历等)

简介:

  1. 分为四个类,节点类(Node),链表类(LinkNode),工具类(Tool),主类
  2. 链表类的方法:
    • 构造方法3个
    • 成员方法1:获得链表长度
    • 成员方法2:判断链表是否为空
    • 成员方法3:获得第n个节点的值
    • 成员方法4:遍历输出链表值
  3. 工具类的方法:
    1. 构造方法
    2. 成员方法:链表逆序
    3. 成员方法:链表指定位置插入
    4. 成员方法:链表指定位置逆序
    5. 成员方法:链表中间位置逆序
  4. 主类附有案例

一、节点类

  • 因为暂时没有学习泛型,这里节点内数据设为int类型


public class Node {
    /*
        链表节点应具备的属性:
            1,节点的属性包括 节点数据 和 下一个节点的地址
            2. 没有学泛型,这里节点内容数据设为int,而非引用类型
     */
    private int number;  // 本节点的值
    Node nextNode;  // 指针-->指向下一个节点

    public Node(int number, Node nextNode) {  
        this.nextNode = nextNode;
        this.number = number;
    }
    public Node() {
        this(0, null);   // 由于是int数值->设置0, 如果是引用类型设置为null
    }

    public int getInt() {
        return number;
    }
}

二、链表类

  • 我理解的单链表:
    在这里插入图片描述


public class LinkNode {
    Node head;
    /*
        链表:
            1. head是一个在链表外的Node对象,头节点不算在链表内,且头节点不算在长度内
            2. 链表其实是多个Node类型的数据链接一起
            3. 链表的最后一个节点的nextNode属性为null
     */

    // 构造方法一:链表为空链表,只有一个头节点
    // 因为是int类型, 头指针指向节点其实有默认值0
    public LinkNode() {
        head = new Node();
    }

    // 构造方法二:数组传值,形成单链表
    // 以数组形式传值. 这里是int数组
    // 没有考虑传值数组内值为空的情况(因为为Int类型)
    public LinkNode(int[] arr) {
        this();
        Node rear = head;   // 尾指针,便于数组传值
        for (int i = 0; i < arr.length; i++) {
            // rear.toNextNode() = new Node(arr[i], null);
            // 一开始把nextNode设为private, 但这样会报错???
            rear.nextNode = new Node(arr[i], null);
            rear = rear.nextNode;
        }
    }

    // 构造方法三:链表内有一个Node节点
    public LinkNode(int m) {
        head = new Node(0, null);
        head.nextNode = new Node(m, null);
    }

    public boolean isEmpty() {
        return head.nextNode == null;
    }

    // 遍历链表,直到rear指针指向null
    public int LinkLength() {
        Node rear = head;
        int length = 0;
        while (rear.nextNode != null) {
            length++;
            rear = rear.nextNode;
        }
        return length;
    }

    // 获得第n个节点的值,同样需要遍历
    /*
        假设需要获得第2个节点的值,需要把rear指针指向第二个节点
        即需要遍历2次 --> 获得第n个节点的值需要遍历n次
     */
    public int getInfo(int n) {
        Node rear = head;
        for (int i = 0; i < n; i++) {
            rear = rear.nextNode;
        }
        return rear.getInt();
    }

    // 输出单向链表
    public void showAllNum() {
        Node rear = head;
        for (int i = 1; i <= this.LinkLength(); i++) {
            System.out.print(this.getInfo(i) + "\t");
        }
        System.out.println("");
    }



}

三、工具类

  • 链表逆序示例(以链表长度为3的链表,数值分别为1,2,3示例):
    在这里插入图片描述

  • 单链表插入图示:
    在这里插入图片描述

  • 该类的代码:


public class LinkTool {

    private LinkNode linkNode;


    // 链表逆序
    public void linkInverse(LinkNode linkNode) {
        if (linkNode.isEmpty()) {
            throw new RuntimeException("目前为空链表!");
        }
        if (linkNode.LinkLength() == 1) {
            return;
        }
        Node temp = null;
        Node point = linkNode.head.nextNode;
        Node save = point;
        while (point != null) {
            save = point.nextNode;
            point.nextNode = temp;
            temp = point;
            point = save;
        }
        linkNode.head.nextNode = temp;
    }

    // 链表指定第n个和第n+1个节点逆序
    public void nodeInverse(LinkNode linkNode, int n) {
        Node front = linkNode.head;
        Node middle;
        Node behind;
        // 空链表
        if (linkNode.isEmpty()) {
            throw new RuntimeException("空链表不可逆转!");
        }
        // 长度为1的链表逆序
        if (linkNode.LinkLength() == 1) {
            System.out.println("节点长度为1, 无法逆转");
            return;
        }
        // n的范围
        if (n >= linkNode.LinkLength() || n <= 0) {
            throw new RuntimeException("节点位置错误,应大于等于1并小于等于链表长度减一!");
        }
        for (int i = 0; i < n - 1; i++) {
            front = front.nextNode;
        }
        middle = front.nextNode;
        behind = middle.nextNode;
        middle.nextNode = behind.nextNode;
        front.nextNode = behind;
        behind.nextNode = middle;
    }

    // 删除第n个节点
    public void linkDel(int n) {

    }

    // 把节点插入到第n个位置
    public void nodeInsert(Node insertNode, LinkNode linkNode, int n) {
        if (n >= 1 && n <= linkNode.LinkLength() + 1) {
            Node point = linkNode.head;
            Node temp;
            for (int i = 0; i < n - 1; i++) {
                point = point.nextNode;
            }
            temp = point.nextNode;
            point.nextNode = insertNode;
            insertNode.nextNode = temp;
        } else {
            throw new RuntimeException("插入位置错误!");
        }
    }

    // 中间两个节点逆序
    public void middleInverse(LinkNode linkNode) {
        int middlePosition = linkNode.LinkLength() / 2;
        this.nodeInverse(linkNode, middlePosition);
    }

}

四、主类示例

  • 运行结果:
    在这里插入图片描述

  • 主类代码:


public class Start {
    public static void main(String[] args) {
        // LinkNode基础操作
        int arr[] = {1, 2, 3};
        LinkNode linkNode = new LinkNode(arr);
        // 链表长度
        System.out.println("链表的长度为:" + linkNode.LinkLength());
        // 从链表中获取数据
        System.out.println("第2个元素为:" + linkNode.getInfo(2));
        // 显示链表数据
        System.out.println("====该链表的全部数字====");
        linkNode.showAllNum();
        // 使用LinkTool进行逆序
        LinkTool tool = new LinkTool();
        try {
            tool.linkInverse(linkNode);
        } catch (Exception e) {
            e.getMessage();
        }
        System.out.println("====该链表逆转后的全部数字====");
        linkNode.showAllNum();
        // 使用LinkTool进行插入操作
        Node insertNode1 = new Node(10, null);
        try {
            tool.nodeInsert(insertNode1, linkNode, 3);
        } catch (Exception e) {
            e.getMessage();
        }
        System.out.println("====把10插入第3个位置====");
        linkNode.showAllNum();
        Node insertNode2 = new Node(10, null);
        try {
            tool.nodeInsert(insertNode2, linkNode, 1);
        } catch (Exception e) {
            e.getMessage();
        }
        System.out.println("====把10插入第1个位置====");
        linkNode.showAllNum();
        Node insertNode3 = new Node(5, null);
        try {
            tool.nodeInsert(insertNode3, linkNode, linkNode.LinkLength() + 1);
        } catch (Exception e) {
            e.getMessage();
        }
        System.out.println("====把5插入尾部====");
        linkNode.showAllNum();
        // 指定位置进行逆转
        try {
            tool.nodeInverse(linkNode, 2);
        } catch (Exception e) {
            e.getMessage();
        }
        System.out.println("====第2个节点和第3个节点逆转====");
        linkNode.showAllNum();
        try {
            tool.nodeInverse(linkNode, 1);
        } catch (Exception e) {
            e.getMessage();
        }
        System.out.println("====第1个节点和第2个节点逆转====");
        linkNode.showAllNum();
        try {
            tool.nodeInverse(linkNode, linkNode.LinkLength() - 1);
        } catch (Exception e) {
            e.getMessage();
        }
        System.out.println("====最后两个节点逆转====");
        linkNode.showAllNum();
        // 中间两个节点逆转
        try {
            tool.middleInverse(linkNode);
        }catch (Exception e) {
            e.getMessage();
        }
        System.out.println("====中间节点逆转====");
        linkNode.showAllNum();
    }
}

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值