Java实现自定义链表

与C语言比起来,Java实现链表不用考虑复杂的指针关系,一切皆对象,所以相对来说比较简单。
PS:以下代码均采用递归实现,不考虑效率,旨在理解结构。


1.入门级

首先实现一个节点类:

package jimo.love;

public class Node {
    private String data;//数据
    private Node next;//指向下一个节点

    public Node(String data){
        this.data = data;
    }

    public void setNext(Node next){
        this.next = next;
    }
    public Node getNext(){
        return this.next;
    }

    public String getData() {
        return data;
    }

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

然后在主方法中生成节点,完成连接关系,并打印出来,看代码有解释:

package jimo.love;

public class Test {

    public static void main(String[] args) {

        //1.准备所有数据
        Node head = new Node("头节点");
        Node n1 = new Node("n1");
        Node n2 = new Node("n2");

        head.setNext(n1);
        n1.setNext(n2);

        //2.取出所有数据
        //方法一:
        Node curNode = head;
        while(curNode!=null){
            System.out.println(curNode.getData());
            curNode = curNode.getNext();
        }

        //方法二,递归方式:
        print(head);
    }

    //采用递归方式
    public static void print(Node curNode){
        if(curNode==null){
            return ;
        }
        System.out.println(curNode.getData());
        print(curNode.getNext());
    }
}

代码中用了两种方式取数据,看执行结果:
1

可以看到Main方法里写的东西太多了,还要设置数据,输出数据。
但面向对象的思想让我们不需要关注太多的东西和具体的实现。
所以我们需要一个工具类,我们只关注存数据和取数据,并不关心怎么存,怎么取。

2.中级

我们增加一个Link类用于业务操作:

public class Link {

    private Node head;
    public void add(String data){
        Node newNode = new Node(data);
        if(this.head==null){
            this.head = newNode;//头节点
        }else{
            //头插法
//          newNode.setNext(this.head.getNext());
//          this.head.setNext(newNode);

            //尾插法
            this.head.addNode(newNode);
        }
    }
    public void print(){
        if(this.head!=null){
            this.head.printNode();
        }
    }
}

其中的addNode和printNode方法来自Node类:

//递归添加节点
    public void addNode(Node node){
        if(this.next==null){
            this.next = node;
        }else{
            this.next.addNode(node);
        }
    }

    //递归打印节点
    public void printNode(){
        System.out.println(this.data);
        if(this.next!=null){
            this.next.printNode();
        }
    }

在主函数里:

        Link link = new Link();
        link.add("1");
        link.add("2");
        link.add("3");
        link.print();

2

3.高级

在可用链表中,你不可能直接操作节点类吧,像这样:

Node n = new Node("n");

所以,我们要让Node类只能被Link类使用,具体方法是将Node类声明为Link类的私有内部类

4.终极

一个链表不可能只有一个add方法吧,接下来就完善方法:

1.size():取得元素个数

在Link类中声明属性count:

private int count = 0;

在add函数里自加:

this.count++;//增加完就++

返回size:

    //取得数量
    public int size(){
        return this.count;
    }

测试:

        Link link = new Link();
        link.add("1");
        link.add("2");
        link.add("3");
        link.add(null);
        System.out.println(link.size());

可以看到我添加了一个null元素,但也添加进去了,添不添加取决于自己4,我这里不让添加,所以在add函数里修改:

        if(null==data){
            return ;
        }

2.isEmpty():判断链表是否为空:

    public boolean isEmpty(){
        return 0==this.count;
    }

3.contains(data):判断数据是否存在:
在Link类中:

    //根据内容查询数据
    public boolean contains(String data){
        if(null==data||null==this.head){
            return false;
        }else{
            return this.head.containNode(data);
        }
    }

在Node类中:

        public boolean containNode(String data){
            if(data.equals(this.data)){
                return true;
            }else{
                if(null!=this.next){
                    return this.next.containNode(data);
                }else{
                    return false;//递归结束条件
                }
            }
        }

4.get(int index):根据索引查找数据:

在Link类添加属性:

private int index = 0;

在Node类添加方法:

        public String getNode(int index){
            //注意Link.this.index
            if(Link.this.index++==index){
                return this.data;
            }else{
                return this.next.getNode(index);
            }
        }

注意:Link.this.index是内部类获得外部类属性的方法。

在Link类添加方法:

    //通过索引查找内容
    public String get(int index){
        if(index >= this.count){
            return null;
        }
        this.index = 0;//每次从头向后查询
        return this.head.getNode(index);
    }

注意:查找时索引从0开始,当然可以改成从1开始。

5.set(int index,data):根据索引修改内容:

其实和查找一样,只是操作不同方而已:

在Node类:

        public void setNode(int index,String data){
            if(Link.this.index++==index){
                this.data = data;
            }else{
                this.next.setNode(index, data);
            }
        }

在Link类:

    //根据索引修改内容
    public void set(int index,String data){
        if(index >= this.count){
            return ;
        }else{
            this.head.setNode(index,data);
        }
    }

6.remove(data):删除一个元素:

这也是相对来说最复杂的部分,不过也很简单。

在Node类:

        //对非根节点的删除
        public void removeNode(Node preNode,String data){
            if(data.equals(this.data)){
                preNode.next = this.next;
            }else{
                this.next.removeNode(this, data);
            }
        }

在Link类,要判断是否是根节点:

    //删除
    public void remove(String data){
        if(this.contains(data)){
            //删除根节点
            if(data.equals(this.head.data)){
                this.head = this.head.next;
            }else{  //非根节点
                this.head.next.removeNode(this.head, data);
            }
            this.count--;//别忘了
        }
    }

7.toArray():转化成数组:

在Link类添加一个属性:private String[] retArray;

在Node类:

        public void toArrayNode(){
            Link.this.retArray[Link.this.index++] = this.data;
            if(null!=this.next){
                this.next.toArrayNode();
            }
        }

在Link类:

    public String[] toArray(){
        if(null == this.head){
            return null;
        }
        this.index = 0;
        this.retArray = new String[this.count];
        this.head.toArrayNode();
        return this.retArray;
    }

5.总结

以上代码不能够用于实战开发,只是为了理解引用关系的传递,后续的改进可以添加更多的方法,不用递归,加入泛型,做出和List一样的效果。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值