[单向链表与双向链表的实现]

学过Java基础集合的话,就知道链表啊;它增删比较快,查询较慢;
它是物理存储单元上非连续、非顺序的存储结构
在这里插入图片描述

比如我要给这个链表的14和6之间增加新节点56;将预备添加位置的前一个结点指针指向到它即可;

在这里插入图片描述

那么这里准备删除节点节点8呢,操作差不多,指针指向调整一下,它就完美脱离链表了;

在这里插入图片描述

链表这块的话,其实就是在操作它的指针指向;不要觉得非常难哦

单向链表

每个结点都由数据域和指针域组成,头结点的数据域不存储数据,
数据域:真实存储数据,指针域:存储后继结点。

在这里插入图片描述

package com.xiaozhi.day03linkedlist;


import java.util.Iterator;

/**
 * @author by @CSDN 小智RE0
 * @date 2021-12-21 17:20
 * 单向链表;
 */
//为达到遍历,Iterable接口
public class OneDirectionLinked<T> implements Iterable<T> {

    //链表的节点;
    class ListNode {
        //节点元素;
        T data;
        //下一个;
        ListNode next;

        //初始化;
        public ListNode(T data, ListNode next) {
            this.data = data;
            this.next = next;
        }
    }

    //头结点;
    ListNode head;
    //节点个数;
    int size;

    //初始化;
    public OneDirectionLinked() {
        this.head = new ListNode(null, null);
        this.size = 0;
    }

    //判断是否为空;
    public boolean isEmpty() {
        return this.size == 0;
    }

    //链表长度;
    public int getLength() {
        return this.size;
    }

    //清空链表;
    public void clearList() {
        //将头结点下一个节点置为空;
        head.next = null;
        size = 0;
    }

    //获取指定位置的元素;
    public T findDataByIndex(int index) {
        ListNode node = head.next;
        for (int i = 0; i < index; i++) {
            node = node.next;
        }
        return node.data;
    }

    //尾部添加节点;
    public void addNodeLast(T ele) {
        //首先找到尾部;
        ListNode ope = head;
        while (ope.next != null) {
            ope = ope.next;
        }
        //然后创建新节点;
        ListNode newNode = new ListNode(ele, null);
        //接到尾部;
        ope.next = newNode;
        //长度递增;
        this.size += 1;
    }

    //指定位置添加节点;
    public void addNodeByPosition(int po, T ele) {
        //先找到这个指定位置的前一个位置;
        ListNode opNode = head;
        for (int i = 0; i <= po - 1; i++) {
            opNode = opNode.next;
        }

        //新节点将会挂接到这个操作结点下一个节点的后面;
        ListNode insertNext = opNode.next;
        //新节点接到他前面位置的节点即可;
        ListNode newNode = new ListNode(ele, insertNext);
        opNode.next = newNode;
        this.size++;
    }

    //删除指定位置的节点;且返回这个结点值;
    public T removeNodeByPosition(int po) {
        //同样,首先找到这个待删除结点的前一个位置结点;
        ListNode opNode = head;
        for (int i = 0; i <= po - 1; i++) {
            opNode = opNode.next;
        }

        //删除节点;
        ListNode removeNode = opNode.next;
        //删除节点的后一个结点;
        ListNode removeNext = removeNode.next;
        opNode.next = removeNext;
        this.size--;

        return removeNode.data;
    }

    //查询第一个出现的节点位置;若没有就返回-1;
    public int getNodeIndexOf(T ele) {
        ListNode opNode = head;
        //遍历链表,
        for (int index = 0; opNode.next != null; index++) {
            opNode = opNode.next;
            if (opNode.data.equals(ele)) {
                return index;
            }
        }
        return -1;
    }

    //遍历的方法;
    @Override
    public Iterator<T> iterator() {
        return new MyIterator();
    }

    //定义一个内部类实现迭代接口;
    public class MyIterator implements Iterator<T> {
        ListNode node;

        //初始化;
        public MyIterator() {
            this.node = head;
        }

        //是否有下一个节点;
        @Override
        public boolean hasNext() {
            return this.node.next != null;
        }

        //得到下一个节点的值;
        @Override
        public T next() {
            node = node.next;
            return node.data;
        }
    }
}

测试使用

package com.xiaozhi.day03linkedlist;

/**
 * @author by @CSDN 小智RE0
 * @date 2021-12-21 19:37
 */
public class Test {
    //测试
    public static void main(String[] args) {
        OneDirectionLinked<Integer> one = new OneDirectionLinked<>();
        //添加元素;
        one.addNodeLast(12);
        one.addNodeLast(13);
        one.addNodeLast(12);
        one.addNodeLast(14);
        one.addNodeLast(15);
        one.addNodeLast(16);
        //指定位置添加元素
        one.addNodeByPosition(2,123);
        //遍历;
        one.iterator().forEachRemaining(a-> System.out.print(a +"->"));
        System.out.println();
        //删除指定位置的元素;
        System.out.println("删除指定位置元素:"+one.removeNodeByPosition(4));
        one.iterator().forEachRemaining(a-> System.out.print(a +"->"));
        System.out.println();
        System.out.println("123第一次出现的位置:"+one.getNodeIndexOf(123));
    }
}

测试结果

12->13->123->12->14->15->16->
删除指定位置元素:14
12->13->123->12->15->16->
123第一次出现的位置:2

双向链表

在这里插入图片描述

package com.xiaozhi.day03linkedlist.twodirection;

import java.util.Iterator;

/**
 * @author by @CSDN 小智RE0
 * @date 2021-12-21 20:32
 * 双向链表
 */

public class DoubleDirectionLinked<T> implements Iterable<T> {
    //节点类;
    class ListNode {
        //节点数据;
        T data;
        //前置指针;
        ListNode pre;
        //后置指针;
        ListNode next;

        //初始化;
        public ListNode(T data, ListNode pre, ListNode next) {
            this.data = data;
            this.pre = pre;
            this.next = next;
        }
    }

    //头结点;不存储数据;
    ListNode head;
    //尾节点;
    ListNode tail;
    //节点的个数;
    int size;

    //初始化链表;
    public DoubleDirectionLinked() {
        this.head = new ListNode(null, null, null);
        this.tail = null;
        this.size = 0;
    }

    //获取链表的长度;
    public int getLength() {
        return this.size;
    }

    //判断链表是否为空;
    public boolean isEmpty() {
        return this.size == 0;
    }

    //清空链表;
    public void clearList() {
        this.head.pre = null;
        this.head.next = null;
        this.tail = null;
        this.size = 0;
    }

    //尾部添加新节点;
    public void addNodeToLast(T ele) {
        if (isEmpty()) {
            //若链表为空,直接让挂接到头结点后即可;
            ListNode node = new ListNode(ele, head, null);
            this.tail = node;
            this.head.next = tail;
        } else {
            ListNode initTail = this.tail;
            //直接挂接到尾节点;
            ListNode node = new ListNode(ele, initTail, null);
            initTail.next = node;
            tail = node;
        }
        this.size += 1;
    }

    //指定位置添加新节点;
    public void addNodeByPosition(int po, T ele) {
        //首先找到前一个位置的节点;以及当前需要添加节点的位置;
        ListNode preNode = head;
        for (int i = 0; i < po; i++) {
            preNode = preNode.next;
        }

        //要添加的位置;
        ListNode curNode = preNode.next;
        //要添加的新节点;
        ListNode node = new ListNode(ele, preNode, curNode);
        preNode.next = node;
        curNode.pre = node;

        this.size += 1;
    }

    //获取链表第一个节点;
    public T getFirst() {
        if (isEmpty()) return null;

        return head.next.data;
    }

    //获取末尾节点;
    public T getLast() {
        if (isEmpty()) return null;

        return this.tail.data;
    }

    //查询指定位置的元素;
    public T getDataByIndex(int index) {
        ListNode opNode = head.next;
        for (int i = 0; i < index; i++) {
            opNode = opNode.next;
        }
        return opNode.data;
    }

    //查询到节点在链表中第一次出现的位置;找不到则返回-1;
    public int getPositionByData(T ele) {
        ListNode node = head;
        for (int i = 0; node != null; i++) {
            node = node.next;
            if (node.data.equals(ele)) {
                return i;
            }
        }
        return -1;
    }

    //删除指定位置的元素;
    public T removeDataByIndex(int index) {
        //找到删除元素的前一个位置结点;
        ListNode preNode = head;
        for (int i = 0; i < index; i++) {
            preNode = preNode.next;
        }

        //需要删除的节点;
        ListNode curNode = preNode.next;
        //待删除结点的下一个节点;
        ListNode nextNode = curNode.next;
        //更改指向关系;
        preNode.next = nextNode;
        nextNode.pre = preNode;
        //元素个数减少;
        this.size -= 1;

        return curNode.data;
    }

    //实现链表的遍历;
    @Override
    public Iterator<T> iterator() {
        return new MyIterator();
    }

    //使用自定义内部类完成迭代器功能;
    class MyIterator implements Iterator {
        private ListNode node;

        //初始化;
        public MyIterator() {
            this.node = head;
        }

        //判断是否还有下一个元素;
        @Override
        public boolean hasNext() {
            return node.next != null;
        }

        //得到下一个元素;
        @Override
        public Object next() {
            node = node.next;
            return node.data;
        }
    }
}

测试

public class Test {
    //测试
    public static void main(String[] args) {
        DoubleDirectionLinked<Integer> dou= new DoubleDirectionLinked<>();
        //添加元素;
        dou.addNodeToLast(12);
        dou.addNodeToLast(13);
        dou.addNodeToLast(12);
        dou.addNodeToLast(14);
        dou.addNodeToLast(15);
        dou.addNodeToLast(16);
        //指定位置添加元素
        dou.addNodeByPosition(2,123);
        //遍历;
        dou.iterator().forEachRemaining(a-> System.out.print(a +"->"));
        System.out.println();
        //删除指定位置的元素;
        System.out.println("删除指定位置元素:"+dou.removeDataByIndex(4));
        dou.iterator().forEachRemaining(a-> System.out.print(a +"->"));
        System.out.println();
        System.out.println("123第一次出现的位置:"+dou.getPositionByData(123));
        System.out.println("获取第一个元素-->"+dou.getFirst());
        System.out.println("获取第一个元素-->"+dou.getLast());
    }
}

测试结果

12->13->123->12->14->15->16->
删除指定位置元素:14
12->13->123->12->15->16->
123第一次出现的位置:2
获取第一个元素-->12
获取第一个元素-->16
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小智RE0

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

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

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

打赏作者

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

抵扣说明:

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

余额充值