java链表的概念以及链表的模拟代码实现

目录

1、定义

2、链表结构

3、具体实现链表数据操作


1、定义

传统的数组在使用过程中依赖于索引的控制,如果想要实现内容的动态维护,难度太大。 所以呢,对于随时可能变动的结构,就需要链表了。

所谓链表实质性的本质是利用引用的逻辑关系来实现类似数据的数据处理操作,以一种保存多方数据的形式,实现数组类似的功能。

2、链表结构

可以模拟出这种结构,但是设置节点之间的关系十分麻烦,每个关联都需要手动去做,实在太费劲。应该有个类专门做这种配置引用节点之间关系事情。实际使用者不应该关注怎么操作这个Node,而是只关注数据的操作。

public class LinkDemo {
    public static void main(String args[]) {
        Node<String> n1 = new Node<String>("火车头");
        Node<String> n2 = new Node<String>("车厢1");
        Node<String> n3 = new Node<String>("车厢2");
        Node<String> n4 = new Node<String>("车厢3");
        Node<String> n5 = new Node<String>("车厢4");
        n1.setNext(n2);
        n2.setNext(n3);
        n3.setNext(n4);
        n4.setNext(n5);
        print(n1);
    }

    public static void print(Node<?> node) {
        if (node != null) {
            System.out.println(node.getData());
            print(node.getNext());
        }
    }
}

3、具体实现链表数据操作

原理自己动手写一遍代码就能搞懂的

总体就三个类,接口类、实现类还有测试类

public interface ILink<E> {
    
    //新增数据
    public void add(E e);

    //链表长度
    public int size();

    //判断链表是否为空
    public boolean isEmpty();

    //返回数据对象数组
    public Object[] toArray();

    //获取指定位置节点上的数据
    public E get(int index);

    //修改指定位置数据
    public void set(int index,E data);

    //判断链表中是否有此数据
    public boolean contains(E data);

    //移除数据
    public void remove(E data);

    //清空链表
    public void clean();
}
public class LinkImpl<E> implements ILink<E> {

    private class Node {
        private E data;
        private Node next;

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

        public void addNode(Node newNode) {
            if (this.next == null) {
                this.next = newNode;
            } else {
                this.next.addNode(newNode);
            }
        }

        public void toArrayNode() {
            LinkImpl.this.returnData[LinkImpl.this.foot++] = this.data;
            if (this.next != null) {
                this.next.toArrayNode();
            }
        }

        public E getNode(int index) {

            if (LinkImpl.this.foot++ == index) {
                return this.data;
            } else {
                return this.next.getNode(index);
            }

        }

        public void setNode(int index, E data) {

            if (LinkImpl.this.foot++ == index) {
                this.data = data;
            } else {
                this.next.setNode(index, data);
            }

        }

        public boolean containsNode(E data) {
            if (this.data.equals(data)) {
                return true;
            } else {
                if (this.next == null) {
                    return false;
                } else {
                    return this.next.containsNode(data);
                }
            }

        }

        public void removeNode(Node pervious, E data) {
            if (this.data.equals(data)) {
                pervious.next = this.next;
            } else {
                if (this.next != null) {
                    this.next.removeNode(this, data);
                }
            }
        }


    }

    private Node root;
    private int count;
    private int foot;
    private Object[] returnData;

    @Override
    public void add(E e) {
        if (e == null) {
            return;
        }

        Node newNode = new Node(e);
        if (this.root == null) {
            this.root = newNode;
        } else {
            this.root.addNode(newNode);
        }
        this.count++;
    }

    @Override
    public int size() {
        return this.count;
    }

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

    @Override
    public Object[] toArray() {

        if (this.isEmpty()) {
            return null;
        }
        this.foot = 0;
        this.returnData = new Object[this.count];
        this.root.toArrayNode();
        return this.returnData;
    }

    @Override
    public E get(int index) {
        if (index >= this.count) {
            return null;
        }
        this.foot = 0;
        return this.root.getNode(index);
    }

    @Override
    public void set(int index, E data) {
        if (index >= this.count) {
            return;
        }
        this.foot = 0;
        this.root.setNode(index, data);
    }

    @Override
    public boolean contains(E data) {
        if (data == null) {
            return false;
        }
        return this.root.containsNode(data);
    }

    @Override
    public void remove(E data) {
        if (this.contains(data)) {
            if (this.root.data.equals(data)) {
                this.root = this.root.next;
            } else {
                this.root.next.removeNode(this.root, data);
            }
            this.count--;
        }
    }

    @Override
    public void clean() {
        this.root = null;
        this.count = 0;
    }
}
public class LinkDemo {
    public static void main(String args[]) {

        ILink<String> all = new LinkImpl<>();

        System.out.println(all.size());
        System.out.println(all.isEmpty());
        all.add("hello");
        System.out.println(all.size());
        all.add("KOBE");
        all.add("james");
        System.out.println(all.size());
        System.out.println(all.isEmpty());

        Object[] result = all.toArray();
        for (Object a : result) {
            System.out.println(a);
        }

        System.out.println(all.get(0));
        all.set(1, "jordan");
        System.out.println(all.get(1));
        System.out.println(all.contains("龙哥"));
        all.remove("hello");
        Object[] result1 = all.toArray();
        for (Object a : result1) {
            System.out.println(a);
        }

        all.clean();
        System.out.println(all.toArray());
    }

}

这里面有好几个方法用到了内部类Node,个人觉得非常巧妙,经常手动实现一下这个代码,能帮助我们体会内部类的好处,以及加深对递归、链表概念的理解

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

阿星_Alex

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

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

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

打赏作者

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

抵扣说明:

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

余额充值