@Java300 学习总结

一、自定义节点

LinkList底层为双向链表。特点为查询效率低,但增删效率高,线程不安全。

链表数据储存在节点,且每个节点有指向上个和下个节点的指针。

java LinkedList 合并 java linkedlist get_java LinkedList 合并

创建ggLinkedList类,可以先创建一个节点对象Entry。

public class Entry {
    Entry previous;
    Entry next;
    Object element;
    
    public Entry(Entry previous, Entry next, Object element) {
        super();
        this.previous = previous;
        this.next = next;
        this.element = element;
    }

    public Entry(Object element) {
        super();
        this.element = element;
    }
}
public class Entry {
    Entry previous;
    Entry next;
    Object element;
    
    public Entry(Entry previous, Entry next, Object element) {
        super();
        this.previous = previous;
        this.next = next;
        this.element = element;
    }

    public Entry(Object element) {
        super();
        this.element = element;
    }
}

二、增加add方法

LinkedList通过add方法往里面增加元素。
先建一个类。

public class ggLinkedList {
    private Entry first; //链表头指针,指向第一个节点
    private Entry last; //链表尾指针,指向最后一个节点
    private int size; //长度,增加节点和删除节点时++或--
    
    //往链表尾处添加元素
    public void add(Object obj) {
        Entry entry = new Entry(obj);
        
        if(first == null) {
            first = entry;
            last = entry;
        }else {
        
            entry.previous = last; //新节点头指针指向上一个节点
            entry.next = null; //新节点尾指针指向空
            
            last.next = entry; //上一个节点的尾指针指向新添加节点
            last = entry;//尾指针指向新节点
        }
        size++;//链表长度增加一
    }
    public static void main(String[] args) {
        ggLinkedList list = new ggLinkedList();
        list.add('a');
    }
}
public class ggLinkedList {
    private Entry first; //链表头指针,指向第一个节点
    private Entry last; //链表尾指针,指向最后一个节点
    private int size; //长度,增加节点和删除节点时++或--
    
    //往链表尾处添加元素
    public void add(Object obj) {
        Entry entry = new Entry(obj);
        
        if(first == null) {
            first = entry;
            last = entry;
        }else {
        
            entry.previous = last; //新节点头指针指向上一个节点
            entry.next = null; //新节点尾指针指向空
            
            last.next = entry; //上一个节点的尾指针指向新添加节点
            last = entry;//尾指针指向新节点
        }
        size++;//链表长度增加一
    }
    public static void main(String[] args) {
        ggLinkedList list = new ggLinkedList();
        list.add('a');
    }
}

三、增加toString方法

在ggLinkedList类中,添加toString方法,以数组的形式输出链表每个节点的数据。
在main函数调用System.out.println(list),会默认调用toString方法。

public String toString() {
        StringBuilder sb = new StringBuilder("[");
        Entry  temp = first;
        while(temp!=null) {
            sb.append(temp.element+",");
            temp = temp.next;
        }
        sb.setCharAt(sb.length()-1,']');
        return sb.toString();
    }
public String toString() {
        StringBuilder sb = new StringBuilder("[");
        Entry  temp = first;
        while(temp!=null) {
            sb.append(temp.element+",");
            temp = temp.next;
        }
        sb.setCharAt(sb.length()-1,']');
        return sb.toString();
    }

四、增加get查找方法

get()方法,可以通过传递数字,查找LinkedList对应索引节点上的数据。

public Object get(int index) {
        if(index< 0||index > size -1) {
            throw new RuntimeException("索引数字不合法" + index);
        }
        if(index <= (size>>1)) { //索引index小于链表长度的一半,从链表头部开始查找
            Entry temp = first;
            for(int i = 0;i<index;i++) {
                temp = temp.next;
            }
            return temp.element;
        }else
        {
            Entry temp = last;  //索引index大于链表长度的一半,从链表尾部开始查找
            for(int i = size-1;i > index;i--) { 
                temp = temp.previous;
            }
            return temp.element;
        }
    }
public Object get(int index) {
        if(index< 0||index > size -1) {
            throw new RuntimeException("索引数字不合法" + index);
        }
        if(index <= (size>>1)) { //索引index小于链表长度的一半,从链表头部开始查找
            Entry temp = first;
            for(int i = 0;i<index;i++) {
                temp = temp.next;
            }
            return temp.element;
        }else
        {
            Entry temp = last;  //索引index大于链表长度的一半,从链表尾部开始查找
            for(int i = size-1;i > index;i--) { 
                temp = temp.previous;
            }
            return temp.element;
        }
    }

五、增加remove()删除功能

remove()删除节点,需先定位到目标节点,与get()方法一致,所以可构造getEntry()方法,以简化代码。

public Entry getEntry(int index) {
        Entry temp = null;
        if(index <= (size>>1)) {
            temp = first;
            for(int i = 0;i<index;i++) {
                temp = temp.next;
            }
            return temp;
        }else
        {
            temp = last;
            for(int i = size-1;i > index;i--) {
                temp = temp.previous;
            }
            return temp;
        }
    }
public Entry getEntry(int index) {
        Entry temp = null;
        if(index <= (size>>1)) {
            temp = first;
            for(int i = 0;i<index;i++) {
                temp = temp.next;
            }
            return temp;
        }else
        {
            temp = last;
            for(int i = size-1;i > index;i--) {
                temp = temp.previous;
            }
            return temp;
        }
    }

重构get()方法

public Object get(int index) {
        if(index< 0||index > size -1) {
            throw new RuntimeException("索引数字不合法" + index);
        }
        Entry temp = getEntry(index);
        return temp!= null?temp.element:null;
    }
public Object get(int index) {
        if(index< 0||index > size -1) {
            throw new RuntimeException("索引数字不合法" + index);
        }
        Entry temp = getEntry(index);
        return temp!= null?temp.element:null;
    }

remove()方法

public void remove(int index) {
        Entry temp = getEntry(index); //索引到指定的节点
        Entry up = temp.previous; //上一个节点为up
        Entry down = temp.next; // 下一个节点为down
        if(temp!= null) { 
            if(down!= null) { //下一个节点不为空,down的头指针指向上一个节点
                down.previous = up; 
            }
            if(up!= null) { //上一个节点不为空,up的的尾指针为下一个节点
                up.next = down;
            }
            if(index == 0) { //移除节点为头节点,链表头指针指向第二个
                first = down;
            }
            if(index == (size-1)) { //移除节点为最后一个,链表尾指针指向倒数第二个
                last = up;
            }
        }
        size--;
    }
public void remove(int index) {
        Entry temp = getEntry(index); //索引到指定的节点
        Entry up = temp.previous; //上一个节点为up
        Entry down = temp.next; // 下一个节点为down
        if(temp!= null) { 
            if(down!= null) { //下一个节点不为空,down的头指针指向上一个节点
                down.previous = up; 
            }
            if(up!= null) { //上一个节点不为空,up的的尾指针为下一个节点
                up.next = down;
            }
            if(index == 0) { //移除节点为头节点,链表头指针指向第二个
                first = down;
            }
            if(index == (size-1)) { //移除节点为最后一个,链表尾指针指向倒数第二个
                last = up;
            }
        }
        size--;
    }

六、增加插入方法

重载add()方法,实现在指定索引位置插入元素。

public void add(int index,Object obj) {
            Entry newEntry = new Entry(obj); //新建节点,将它插入在索引节点的前面
            Entry down = getEntry(index); //原节点为新插入节点的下一个节点,变量名为down
            
            if(down!=null) { //原节点不为空
                Entry up = down.previous; //原节点的上一个节点为上一个节点,变量名为up
                
                if(index == 0) {
                    down.previous = newEntry; //原节点的前一个为新节点
                    newEntry.next = down;//新节点的下一个为原节点
                    first = newEntry;//链表头指针指向新节点
                }
                else if(index == (size-1)) {
                    down.next = newEntry; //原节点的下一个为新节点
                    newEntry.previous = up;//新节点的上一个为up
                    last = newEntry;//尾指针指向新节点
    
                }else {
                    down.previous = newEntry;
                    up.next = newEntry;
                    newEntry.next = down;
                    newEntry.previous = up;
                }
            }
            size++;
public void add(int index,Object obj) {
            Entry newEntry = new Entry(obj); //新建节点,将它插入在索引节点的前面
            Entry down = getEntry(index); //原节点为新插入节点的下一个节点,变量名为down
            
            if(down!=null) { //原节点不为空
                Entry up = down.previous; //原节点的上一个节点为上一个节点,变量名为up
                
                if(index == 0) {
                    down.previous = newEntry; //原节点的前一个为新节点
                    newEntry.next = down;//新节点的下一个为原节点
                    first = newEntry;//链表头指针指向新节点
                }
                else if(index == (size-1)) {
                    down.next = newEntry; //原节点的下一个为新节点
                    newEntry.previous = up;//新节点的上一个为up
                    last = newEntry;//尾指针指向新节点
    
                }else {
                    down.previous = newEntry;
                    up.next = newEntry;
                    newEntry.next = down;
                    newEntry.previous = up;
                }
            }
            size++;

至此,LinkedList部分方法已实现,后续也可增加其他方法,或泛型。旨在理解底层原理,提升代码能力