Java写数据结构--单向无头非循环链表

什么是链表?

链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的

从上图可以看出来,链式结构在逻辑上是连续的,但是在物理上不一定连续

链式中的节点一般都是在堆中申请出来的

从堆上申请出来的空间,是按照一定策略来分配的,两次申请出来的空间可能连续,也可能不连续

 链表分了很多种:

不带头 单向  非循环 链表

不带头 单项  循环   链表

不带头 双向 非循环 链表

不带头 双向 循环  链表

带头 单向  非循环 链表

带头 单项  循环   链表

带头 双向 非循环 链表

带头 双向 循环  链表

一共八种,本篇文章主要说到不带头 单项 非循环链表 这种也是最常见的

本篇文章主要对下列接口中的方法进行实现,文章末有全部代码

public interface Ilist {
    //头插法
    public void addFirst(int date);
    //尾插法
    public void addLast(int date);
    //任意位置插入,第一个节点为0号下标
    public void addIndex(int index, int date);
    //删除第一次出现值为key的节点
    public void remove(int key);
    //判断链表中是否存在值为key的节点
    public boolean contains(int key);
    //删除所有值为key的节点
    public void removeAllKey(int key);
    //获得链表的长度
    public int size();
    //清空链表
    public void clear();
    //显示链表
    public void disPlay();
}

先创建一个链表类实现Ilist接口

public class MySingleList implements Ilist{
    //内部类
    static class ListNode{
        public int val;
        public ListNode next;

        public ListNode(int val) {
            this.val = val;
        }
    }
    //链表的头
    public ListNode head;

    //创建链表
    public void creatList(){
        ListNode node1 = new ListNode(5);
        ListNode node2 = new ListNode(6);
        ListNode node3 = new ListNode(8);
        ListNode node4 = new ListNode(10);
        ListNode node5 = new ListNode(15);

        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;
        this.head = node1;
    }

    @Override
    public void addFirst(int date) {
        
    }

    @Override
    public void addLast(int date) {

    }

    @Override
    public void addIndex(int index, int date) {

    }

    @Override
    public void remove(int key) {

    }

    @Override
    public boolean contains(int key) {
        return false;
    }

    @Override
    public void removeAllKey(int key) {

    }

    @Override
    public int size() {
        return 0;
    }

    @Override
    public void clear() {

    }

    @Override
    public void disPlay() {

    }

    
   
}

接下来对重写的方法由简单到复杂一一实现

完成disPlay方法

 @Override
    public void disPlay() {
        ListNode cur = head;
        while(cur != null){
            System.out.print(cur.val + " ");
            cur = cur.next;
        }

为了防止调用完一次函数head的指向会发生变化,所以要对head临时拷贝一份

完成size方法

@Override
public int size() {
    int len = 0;
    ListNode cur = head;
    while(cur != null){
        len++;
        cur = cur.next;
    }
    return len;
}

下面是cur的指向轨迹

实现addFirst方法

@Override
    public void addFirst(int date) {
         //创建出新的节点
        ListNode node = new ListNode(date);
        node.next = head;
        head = node;
}

测试一下

public class Test {
    public static void main(String[] args) {
        MySingleList mySingleList = new MySingleList();
        mySingleList.creatList();

        int ret = mySingleList.size();
        System.out.println(ret);

        mySingleList.disPlay();
        System.out.println();

        mySingleList.addFirst(8);
        mySingleList.disPlay();
        System.out.println();
    }
}

 

addLast也是同理

 @Override
    public void addLast(int date) {
        ListNode node = new ListNode(date);
        ListNode cur = head;
        while(cur.next != null){
            cur = cur.next;
        }
        cur.next = node;
    }

测试一下

public class Test {
    public static void main(String[] args) {
        MySingleList mySingleList = new MySingleList();
        mySingleList.creatList();

        int ret = mySingleList.size();
        System.out.println(ret);

        mySingleList.disPlay();
        System.out.println();

        mySingleList.addFirst(8);
        mySingleList.disPlay();
        System.out.println();

        mySingleList.addLast(20);
        mySingleList.disPlay();
        System.out.println();
}
}

实现addIndex方法

@Override
    public void addIndex(int index, int date) {
        int len = size();
        if(index < 0 || index > len){
            System.out.println("index位置不合法");
            return;
        }
        if(index == 0){
            addFirst(date);
        }
        if (index == len){
            addLast(date);
        }
        ListNode cur = head;
        while( index - 1 != 0 ){
            cur = cur.next;
            index--;
        }
        ListNode node = new ListNode(date);
        node.next = cur.next;
        cur.next = node;
    }

因为是单向链表,cur要指向index下标的前一个位置的节点,对index前面那个节点的next修改,进行插入

测试一下

public class Test {
    public static void main(String[] args) {
        MySingleList mySingleList = new MySingleList();
        mySingleList.creatList();

        int ret = mySingleList.size();
        System.out.println(ret);

        mySingleList.disPlay();
        System.out.println();

        mySingleList.addFirst(8);
        mySingleList.disPlay();
        System.out.println();

        mySingleList.addLast(20);
        mySingleList.disPlay();
        System.out.println();

        mySingleList.addIndex(2,66);
        mySingleList.disPlay();
        System.out.println();
}
}

实现contains方法

@Override
    public boolean contains(int key) {
        ListNode cur = head;
        while(cur != null){
            if(cur.val == key){
                return true;
            }
            cur = cur.next;
        }
        return false;
    }

这个很好理解

测试↓

public class Test {
    public static void main(String[] args) {
        MySingleList mySingleList = new MySingleList();
        mySingleList.creatList();

        int ret = mySingleList.size();
        System.out.println(ret);

        mySingleList.disPlay();
        System.out.println();

        mySingleList.addFirst(8);
        mySingleList.disPlay();
        System.out.println();

        mySingleList.addLast(20);
        mySingleList.disPlay();
        System.out.println();

        mySingleList.addIndex(2,66);
        mySingleList.disPlay();
        System.out.println();

        boolean ret2 = mySingleList.contains(66);
        System.out.println(ret2);
}
}

实现remove方法

@Override
    public void remove(int key) {
        if(head == null){
            return;
        }
        if(head.val == key){
            head = head.next;
            return;
        }
        ListNode cur = findNodeIndex(key);
        if(cur != null){
            cur.next = cur.next.next;
        }else{
            System.out.println("没有要删除的key值");
            return;
        }
    }
    //供remove使用的方法
    private ListNode findNodeIndex(int key){
        ListNode cur = head;
        while(cur.next != null){
            if(cur.next.val == key){
                return cur;
            }
            cur = cur.next;
        }
        return null;
    }

测试 

public class Test {
    public static void main(String[] args) {
        MySingleList mySingleList = new MySingleList();
        mySingleList.creatList();

        int ret = mySingleList.size();
        System.out.println(ret);

        mySingleList.disPlay();
        System.out.println();

        mySingleList.addFirst(8);
        mySingleList.disPlay();
        System.out.println();

        mySingleList.addLast(20);
        mySingleList.disPlay();
        System.out.println();

        mySingleList.addIndex(2,66);
        mySingleList.disPlay();
        System.out.println();

        boolean ret2 = mySingleList.contains(66);
        System.out.println(ret2);

        mySingleList.remove(66);
        mySingleList.disPlay();
        System.out.println();
}
}

 

实现removeAllKey方法

@Override
    public void removeAllKey(int key) {
        if(head == null){
            return;
        }
        ListNode prev = head;
        ListNode cur = head.next;

        while(cur != null){
            if(cur.val == key){
                prev.next = cur.next;
                cur = cur.next;
            }else{
                prev = cur;
                cur = cur.next;
            }
        }
        if(head.val == key){
            head = head.next;
        }

    }

 

测试一下

public class Test {
    public static void main(String[] args) {
        MySingleList mySingleList = new MySingleList();
        mySingleList.creatList();

        int ret = mySingleList.size();
        System.out.println(ret);

        mySingleList.disPlay();
        System.out.println();

        mySingleList.addFirst(8);
        mySingleList.disPlay();
        System.out.println();

        mySingleList.addLast(20);
        mySingleList.disPlay();
        System.out.println();

        mySingleList.addIndex(2,66);
        mySingleList.disPlay();
        System.out.println();

        boolean ret2 = mySingleList.contains(66);
        System.out.println(ret2);

        mySingleList.remove(66);
        mySingleList.disPlay();
        System.out.println();

        mySingleList.addFirst(9);
        mySingleList.addIndex(1,9);
        mySingleList.addIndex(2,9);
        mySingleList.addIndex(5,9);
        mySingleList.disPlay();
        System.out.println();
        
        mySingleList.removeAllKey(9);//removeALLKey
        
        mySingleList.disPlay();
        System.out.println();
}
}

 

 只看后两行,把9都删除了

实现clear方法

 

 @Override
    public void clear() {
        head = null;
    }

这种方法简单,但是会造成内存泄漏,需要将节点的每一个next值都置为null ,需要下面这种方法

 @Override
    public void clear() {
        ListNode cur = head;
        while(cur != null){
            ListNode curN = cur.next;
            cur.next = null;
            cur = curN;
        }
        head = null;
    }

这种类似于交换两个变量的数值,需要临时拷贝一份

下面是测试类的全部代码

public class Test {
    public static void main(String[] args) {
        MySingleList mySingleList = new MySingleList();
        mySingleList.creatList();

        int ret = mySingleList.size();
        System.out.println(ret);

        mySingleList.disPlay();
        System.out.println();

        mySingleList.addFirst(8);
        mySingleList.disPlay();
        System.out.println();

        mySingleList.addLast(20);
        mySingleList.disPlay();
        System.out.println();

        mySingleList.addIndex(2,66);
        mySingleList.disPlay();
        System.out.println();

        boolean ret2 = mySingleList.contains(66);
        System.out.println(ret2);

        mySingleList.remove(66);
        mySingleList.disPlay();
        System.out.println();

        mySingleList.addFirst(9);
        mySingleList.addIndex(1,9);
        mySingleList.addIndex(2,9);
        mySingleList.addIndex(5,9);
        mySingleList.disPlay();
        System.out.println();

        mySingleList.removeAllKey(9);//removeALLKey

        mySingleList.disPlay();
        System.out.println();

        mySingleList.clear();
        mySingleList.disPlay();
        System.out.println();
        mySingleList.addFirst(1);
        mySingleList.disPlay();
    }
}

下面是MySingleList类的全部代码

public class MySingleList implements Ilist{
    static class ListNode{
        public int val;
        public ListNode next;

        public ListNode(int val) {
            this.val = val;
        }
    }

    public ListNode head;

    public void creatList(){
        ListNode node1 = new ListNode(5);
        ListNode node2 = new ListNode(6);
        ListNode node3 = new ListNode(8);
        ListNode node4 = new ListNode(10);
        ListNode node5 = new ListNode(15);

        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;
        this.head = node1;
    }


    @Override
    public void addFirst(int date) {
        ListNode node = new ListNode(date);
        node.next = head;
        head = node;
    }

    @Override
    public void addLast(int date) {
        ListNode node = new ListNode(date);
        ListNode cur = head;
        while(cur.next != null){
            cur = cur.next;
        }
        cur.next = node;
    }

    @Override
    public void addIndex(int index, int date) {
        int len = size();
        if(index < 0 || index > len){
            System.out.println("index位置不合法");
            return;
        }
        if(index == 0){
            addFirst(date);
        }
        if (index == len){
            addLast(date);
        }
        ListNode cur = head;
        while( index - 1 != 0 ){
            cur = cur.next;
            index--;
        }
        ListNode node = new ListNode(date);
        node.next = cur.next;
        cur.next = node;
    }

    @Override
    public boolean contains(int key) {
        ListNode cur = head;
        while(cur != null){
            if(cur.val == key){
                return true;
            }
            cur = cur.next;
        }
        return false;
    }


    @Override
    public void remove(int key) {
        if(head == null){
            return;
        }
        if(head.val == key){
            head = head.next;
            return;
        }
        ListNode cur = findNodeIndex(key);
        if(cur != null){
            cur.next = cur.next.next;
        }else{
            System.out.println("没有要删除的key值");
            return;
        }
    }
    //供remove使用的方法
    private ListNode findNodeIndex(int key){
        ListNode cur = head;
        while(cur.next != null){
            if(cur.next.val == key){
                return cur;
            }
            cur = cur.next;
        }
        return null;
    }


    @Override
    public void removeAllKey(int key) {
        if(head == null){
            return;
        }
        ListNode prev = head;
        ListNode cur = head.next;

        while(cur != null){
            if(cur.val == key){
                prev.next = cur.next;
                cur = cur.next;
            }else{
                prev = cur;
                cur = cur.next;
            }
        }
        if(head.val == key){
            head = head.next;
        }

    }
    @Override
    public int size() {
        int len = 0;
        ListNode cur = head;
        while(cur != null){
            len++;
            cur = cur.next;
        }
        return len;
    }

    @Override
    public void clear() {
        ListNode cur = head;
        while(cur != null){
            ListNode curN = cur.next;
            cur.next = null;
            cur = curN;
        }
        
        head = null;
    }
   
    @Override
    public void disPlay() {
        ListNode cur = head;
        while(cur != null){
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
    }



}



IList接口中的全部代码

public interface Ilist {
    //头插法
    public void addFirst(int date);
    //尾插法
    public void addLast(int date);
    //任意位置插入,第一个节点为0号下标
    public void addIndex(int index, int date);
    //删除第一次出现值为key的节点
    public void remove(int key);
    //判断链表中是否存在值为key的节点
    public boolean contains(int key);
    //删除所有值为key的节点
    public void removeAllKey(int key);
    //获得链表的长度
    public int size();
    //清空链表
    public void clear();
    //显示链表
    public void disPlay();
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值