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

Posted 小智RE0

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[单向链表与双向链表的实现]相关的知识,希望对你有一定的参考价值。

学过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

以上是关于[单向链表与双向链表的实现]的主要内容,如果未能解决你的问题,请参考以下文章

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

链表的java实现(单向双向链表,单向链表的反转)

链表的java实现(单向双向链表,单向链表的反转)

数据结构《二》链表的实现

双向链表与LinkedHashMap

单向链表和双向链表的原理及其相关实现