Python 每日一记230>>>Java单向链表的实现

一、什么是单向链表

单向链表由一个个节点组成,头节点没有元素只有指向下一个节点的地址域,尾节点有元素但是指向地址域为null,其余的节点都有一个数据域和地址域,数据域用于存储数据,地址域用于指向下一个节点,第一个元素是头节点后的第一个节点内的数据;

链表和顺序表是不同的,顺序表有数组作为基础,存储空间连续,有索引可以实现快速查找,但是添加元素和删除元素效率较低;
链表不以数组作为基础,存储空间可以不连续,查找只能从头开始遍历,因此查找速度慢,但是添加和删除元素效率高。

在这里插入图片描述

二、java代码实现

package mypackage;
/**
 * 单向链表的创建
 * 要实现的功能包括:
 * 初始化
 * 返回长度,即节点个数
 * 插入、删除节点
 * 根据索引获取节点
 * 根据节点获取索引
 * 判断是否为空
 *
 * 单项链表的核心在于节点类,有了节点类,才能更好的表示节点之间的链接关系
 *
 * 注意,关于第i个节点的约定,第1个节点是头节点后的第一个节点,依次类推.
 * 我们把第一个节点就称之为第一个节点,注意没有索引的概念
 * 即使有索引的话,也是从1开始的,而不是从0开始的
 */

import java.util.Iterator;

//<T>泛型表示支持任意类型
class LinkList<T> implements Iterable<T>{
    //记录头节点
    private Node head;
    //记录链表的长度,即节点的个数
    private int N;

    //定义节点类,这一步至关重要
    //注意构造方法的参数有一个是next,这个类型是Node,正是我们定义的这个类Node
    //这样的话,我们每个节点就可以传入一个参数,next,然后用当前结点调用.next属性就可以获得下一个节点
    //这就是单项链表链接的核心
    private class Node{
        //数据项和下一个节点项
        T data;
        Node next;
        //构造方法
        public Node(T data, Node next){
            this.data=data;
            this.next=next;
        }
    }

    //构造方法
    public LinkList(){
        //初始化头节点,初步的头节点的数据项和下一个节点项都是null,节点个数为0
        //头节点的数据项本身就定义为null,他的作用只是指向链表的第一个由数据的节点而已
        //尾节点的下一个节点项本身就定义为null,表示链表的结束
        this.head=new Node(null,null);
        this.N=0;
    }

    //清空链表,使得头节点不指向任何节点,且节点个数为0
    public void clear(){
        head.next=null;
        this.N=0;
    }

    //获取节点个数
    public int length(){
        return N;
    }

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

    //直接在尾部添加节点
    public void append(T data){
        Node n=head;
        //找到最后一个节点
        while(n.next!=null){
            n=n.next;
        }
        //创建新节点,最后一个节点的next=null
        Node newnode=new Node(data,null);
        //让当前借点指向新节点
        n.next=newnode;
        N++;
    }


    //向指定位置插入节点,使得这个位置之前的节点指向这个新节点,
    //这个新节点指向这个位置的原本的那个节点
    //其实就是先打断,再链接
    //i第几个节点,和索引没有任何关系,链表没有索引的概念
    public void insert(int i,T data){
        //如果i==N就代表是要在最后添加
        if(i==N){
            Node n=head;
            while(n.next!=null){
                n=n.next;
            }
            //创建新节点,最后一个节点的next=null
            Node newnode=new Node(data,null);
            //让当前借点指向新节点
            n.next=newnode;
            N++;
        }

        //如果在非最后添加
        else{
//            从头节点开始循环,循环一次,到第一个节点,循环第i-1次,循环到第i-1个节点
//            这就找到了第i-1个节点
            Node prenode=head;
            //找到待插入节点的前一个节点
            for (int index=1;index<=i-1;index++){
                prenode=prenode.next;
            }
//            第i个节点
            Node curnode=prenode.next;
//            创建新节点,并且新节点指向第i个节点
            Node newnode=new Node(data,curnode);
            //将前一个节点指向新节点
            prenode.next=newnode;
        }
    }

    //返回第i个节点的值
    public T get(int i){
        //从头节点向后循环找,循环1此找打第一个节点,循环i次找到第i个节点
        Node n=head;
        for (int index=1;index<=i;index++){
            n=n.next;
        }
        //找到节点后,返回节点的数据
        return n.data;
    }
    //删除指定位置节点,并返回删除的值
    //删除后将指定位置的前一个节点指向后一个节点
    public T remove(int i){
        //如果删除最后一个节点,直接将最后一个节点的前一个节点next=null,并且N--
        if(i==N){
            Node prenode=head;
            for (int index=1;index<=i-1;index++){
                prenode=prenode.next;
            }
//            最后一个节点
            Node curnode=prenode.next;
//            使最后一个节点的前一个节点指向null
            prenode.next=null;
            N--;
//            返回最后一个节点的元素值
            return curnode.data;
        }

        //如果删除非最后节点
        else{
            //找到i位置的前一个节点,删除后将指定位置的前一个节点指向后一个节点
            Node prenode=head;
            for (int index=1;index<=i-1;index++){
                prenode=prenode.next;
            }
//            指定节点
            Node curnode=prenode.next;
//            指定节点的后一个节点
            Node nextnode=curnode.next;
//            使得指定节点的前一个节点指向指定节点的后一个节点
            prenode.next=nextnode;
            N--;
//            返回指定节点的元素
            return curnode.data;
        }
    }

    //查找某个节点第一次出现的位置,即是第几个元素,从1开始
    //循环查找,找到就返回,没找到就返回-1
    public int indexOf(T data){
        Node n=head;
        for (int index=1;index<=N;index++){
            n=n.next;
            if(n.data.equals(data)){
                return index;
            }
            break;
        }
        return -1;
    }

    //实现遍历
    //遍历的话,要重写此方法
    @Override
    public Iterator<T> iterator() {
        // 返回的Iterator对象,创建一个内部类实现这个接口
        return new LIterator();
    }

    //    创建一个内部类实现Iterator接口
    public class LIterator implements Iterator {
        //        定义一个遍历的节点
        private Node n;
        public LIterator(){
//            初始化为0索引位置
            this.n=head;
        }
        //重写两个方法
        @Override
        public boolean hasNext() {
//            这个方法判断是否超出最大索引,如果超出会停止遍历
            return n.next!=null;
        }

        @Override
        public Object next() {
//            这个方法会遍历得每个节点
            n=n.next;
            return n.data;
        }
    }
}


//测试
public class Test {
    public static void main(String[] args) {
//        创建一个链表
        LinkList<Object> list = new  LinkList<>();
//        添加节点节点
        list.append(1);
         list.append(2);
         list.append(3);


        //开始遍历
        for(Object ls:list){
            System.out.println("遍历元素---"+ls);
        }

 //       返回节点个数
         int length1 = list.length();
         System.out.println("元素个数"+length1);

 //        插入节点
         list.insert(2, 100);
        //开始遍历
        for(Object ls:list){
            System.out.println("插入节点后遍历元素---"+ls);
        }

 //       删除节点
         Object remove = list.remove(1);
         System.out.println("删除指定位置处的节点元素是"+remove);
        //开始遍历
        for(Object ls:list){
            System.out.println("删除节点后遍历节点元素---"+ls);
        }

 //     返回第几个节点元素
         System.out.println("第1个节点的元素是"+list.get(1));

         // 返回某个值的位置
         System.out.println("指定节点元素对应的位置为"+list.indexOf(100));

 //        清空
         list.clear();

 //        是否为空
         System.out.println("判断是否为空"+list.isEmpty());
    }
}

结果:
在这里插入图片描述

发布了235 篇原创文章 · 获赞 24 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/weixin_44663675/article/details/105421039