2020年9月21日 手动实现单向链表

package com.atguigu.test03;

public class SingleLinkedList {
    //这里不需要数组,不需要其他的复杂的结构,我只要记录单向链表的“头”结点
    private Node first;//first中记录的是第一个结点的地址
    private int total;//这里我记录total是为了后面处理的方便,例如:当用户获取链表有效元素的个数时,不用现数,而是直接返回total等
    
    /*
     * 内部类,因为这种Node结点的类型,在别的地方没有用,只在单向链表中,用于存储和表示它的结点关系。
     * 因为我这里涉及为内部类型。
     */
    private class Node{
        Object data;//因为数据可以是任意类型的对象,所以设计为Object
        Node next;//因为next中记录的下一个结点的地址,因此类型是结点类型
        //这里data,next没有私有化,是希望在外部类中可以不需要get/set,而是直接“结点对象.data","结点对象.next"使用
        Node(Object data, Node next){
            this.data = data;
            this.next = next;
        }
    }
    
    public void add(Object obj){
        /*
         * (1)把obj的数据,包装成一个Node类型结点对象
         * (2)把新结点“链接”当前链表的最后
         * ①当前新结点是第一个结点
         * 如何判断是否是第一个   if(first==null)说明暂时还没有第一个
         * ②先找到目前的最后一个,把新结点链接到它的next中
         * 如何判断是否是最后一个   if(某个结点.next == null)说明这个结点是最后一个
         */
//        (1)把obj的数据,包装成一个Node类型结点对象
        //这里新结点的next赋值为null,表示新结点是最后一个结点
        Node newNode = new Node(obj, null);
        
        //①当前新结点是第一个结点
        if(first == null){
            //说明newNode是第一个
            first = newNode;
        }else{
            //②先找到目前的最后一个,把新结点链接到它的next中
            Node node = first;//创建一个新的结点,来动态表示最后一个结点;
            while(node.next != null){
                node = node.next;
            }
            //退出循环时node指向最后一个结点
            
            //把新结点链接到它的next中
            node.next = newNode;
        }
        
        total++;
    }
    
    public int size(){
        return total;
    }
    
    public Object[] getAll(){
        //(1)创建一个数组,长度为total
        Object[] all = new Object[total];
        
        //(2)把单向链表的每一个结点中的data,拿过来放到all数组中
        Node node = first;
        for (int i = 0; i < total; i++) {
//            all[i] = 结点.data;
            all[i] = node.data;
            //然后node指向下一个
            node = node.next;
        }
        
        //(3)返回数组
        return all;
    }
    
    public void remove(Object obj){
        if(obj == null){
            //(1)先考虑是否是第一个
            if(first!=null){//链表非空
                
                //要删除的结点正好是第一个结点
                if(first.data == null){
                    //让第一个结点指向它的下一个
                    first = first.next;
                    total--;
                    return;
                }
                
                //要删除的不是第一个结点
                Node node = first.next;//第二个结点
                Node last = first;
                while(node.next!=null){//这里不包括最后一个,因为node.next==null,不进入循环,而node.next==null是最后一个
                    if(node.data == null){
                        last.next = node.next;
                        total--;
                        return;
                    }
                    last = node;
                    node = node.next;
                }
                
                //单独判断最后一个是否是要删除的结点
                if(node.data == null){
                    //要删除的是最后一个结点
                    last.next = null;
                    total--;
                    return;
                }
            }
        }else{
            //(1)先考虑是否是第一个
            if(first!=null){//链表非空
                
                //要删除的结点正好是第一个结点
                if(obj.equals(first.data)){
                    //让第一个结点指向它的下一个
                    first = first.next;
                    total--;
                    return;
                }
                
                //要删除的不是第一个结点
                Node node = first.next;//第二个结点
                Node last = first;
                while(node.next!=null){//这里不包括最后一个,因为node.next==null,不进入循环,而node.next==null是最后一个
                    if(obj.equals(node.data)){
                        last.next = node.next;
                        total--;
                        return;
                    }
                    last = node;
                    node = node.next;
                }
                
                //单独判断最后一个是否是要删除的结点
                if(obj.equals(node.data)){
                    //要删除的是最后一个结点
                    last.next = null;
                    total--;
                    return;
                }
            }
        }
    }

    public int indexOf(Object obj){
        if(obj == null){
            Node node = first;
            for (int i = 0; i < total; i++) {
                if(node.data == null){
                    return i;
                }
                node = node.next;
            }
        }else{
            Node node = first;
            for (int i = 0; i < total; i++) {
                if(obj.equals(node.data)){
                    return i;
                }
                node = node.next;
            }
        }
        return -1;
    }
}
package com.atguigu.test03;

import java.util.Arrays;

public class TestSingleLinkedList {

    public static void main(String[] args) {
        SingleLinkedList list = new SingleLinkedList();
        
        list.add("张三");
        list.add("李四");
        list.add("王五");
        list.add("赵六");
        list.add("钱七");
        
        System.out.println("元素个数:" + list.size());
    
        Object[] all = list.getAll();
        System.out.println(Arrays.toString(all));
        
        /*list.remove("张三");
        System.out.println("元素个数:" + list.size());
        all = list.getAll();
        System.out.println(Arrays.toString(all));
        
        list.remove("王五");
        System.out.println("元素个数:" + list.size());
        all = list.getAll();
        System.out.println(Arrays.toString(all));
        
        list.remove("钱七");
        System.out.println("元素个数:" + list.size());
        all = list.getAll();
        System.out.println(Arrays.toString(all));*/
        
        System.out.println(list.indexOf("张三"));
        System.out.println(list.indexOf("王五"));
        System.out.println(list.indexOf("钱七"));
    }

}
原文地址:https://www.cnblogs.com/douyunpeng/p/13705687.html