[Data Structure] Linked List and LinkedList

Author's homepage: paper jie's blog

Author of this article: Hello everyone, I am paper jie. Thank you for reading this article. Welcome to Yijiansanlian.

This article is included in the "JAVA Data Structure" column. This column is carefully created for college students and programming novices. The author spent a lot of money (time and energy) to build it to cover all the basic knowledge of javaSE. I hope it can help readers.

Other columns: "Detailed Explanation of Algorithms", "C Language", "javaSE", etc.

Content sharing: This issue will share the knowledge of linked lists in data structures

Table of contents

linked list

The concept and structure of linked list

Simulation implementation of one-way linked list

Specific implementation code

MyLinkedList

 indexillgality

LinkedList

Simulation implementation of LinkedList

MyLinkedList

Indexexception

LinkedList in java

Use of LinkedList

Various traversals of LinkedList

The difference between ArrayList and LinkedList


linked list

The concept and structure of linked list

A linked list is a physically discontinuous storage structure, and the logical order of data elements is achieved through the reference link order in the linked list. You can think of it as a real green train

Note here:

The chain is logically continuous, but not necessarily physically continuous.

In reality, nodes are generally applied from the heap.

The space requested from the heap is allocated according to a certain strategy, so the space applied for twice may be continuous or discontinuous.

The structures in the linked list are diverse and can be used according to the situation. Generally, the following structure is used:

One way or two way

To take the lead and not to take the lead

Cyclic and non-cyclical

Among these structures, we need to focus on two types:

Headless one-way acyclic linked list: The structure is simple and generally does not store data alone. In fact, it is more used as a substructure of other data structures, such as hash buckets, adjacency lists of graphs, etc.

Headless two-way linked list: In our Java collection framework, the low-level implementation of LinkedList is a headless two-way circular linked list.

Simulation implementation of one-way linked list

The following are some basic functions that need to be implemented in a one-way linked list:

// 1、无头单向非循环链表实现
public class SingleLinkedList {
//头插法
public void addFirst(int data){
} 
//尾插法
public void addLast(int data){
} 
//任意位置插入,第一个数据节点为0号下标
public void addIndex(int index,int data){
} 
//查找是否包含关键字key是否在单链表当中
public boolean contains(int key){
return false;
} 
//删除第一次出现关键字为key的节点
public void remove(int key){
}
//删除所有值为key的节点
public void removeAllKey(int key){
} 
//得到单链表的长度
public int size(){
return -1;
}
public void clear() {
}
public void display() {}
}

Specific implementation code

MyLinkedList
package myLinkedList;

import sun.awt.image.ImageWatched;

import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: sun杰
 * Date: 2023-09-14
 * Time: 10:38
 */
public class MyLinkedList implements IList{

    static class LinkNode {
        public int value;
        public LinkNode next;
        public LinkNode(int data) {
            this.value = data;
        }
    }
    LinkNode head;
    public void createNode() {
        LinkNode linkNode1 = new LinkNode(12);
        LinkNode linkNode2 = new LinkNode(23);
        LinkNode linkNode3 = new LinkNode(34);
        LinkNode linkNode4 = new LinkNode(56);
        LinkNode linkNode5 = new LinkNode(78);
        linkNode1.next = linkNode2;
        linkNode2.next = linkNode3;
        linkNode3.next = linkNode4;
        linkNode4.next = linkNode5;
        this.head = linkNode1;
    }


    @Override
    public void addFirst(int data) {
        //实例化一个节点
        LinkNode firstNode = new LinkNode(data);
        if(this.head == null) {
            this.head = firstNode;
            return;
        }
        //将原第一个对象的地址给新节点的next,也就是将head给新next
        firstNode.next = this.head;
        //将新的对象的地址给head头
        this.head = firstNode;

    }

    @Override
    public void addLast(int data) {
        //实例化一个节点
        LinkNode lastNode = new LinkNode(data);
        //找到最后一个节点
        LinkNode cur = this.head;
        while(cur.next!= null) {
            cur = cur.next;
        }
        cur.next = lastNode;
        //将最后一个节点的next记录插入节点的地址
    }

    @Override
    public void addIndex(int index, int data) throws indexillgality {
        if(index < 0 || index > size()) {
            throw new indexillgality("index不合法");
        }
        LinkNode linkNode = new LinkNode(data);
        if(this.head == null) {
            addFirst(data);
            return;
        }
        if(size() == index ) {
            addLast(data);
            return;
        }
        LinkNode cur = this.head;
        int count = 0;
        while(count != index - 1) {
            cur = cur.next;
            count++;
        }
        linkNode.next = cur.next;
        cur.next = linkNode;
    }

    @Override
    public boolean contains(int key) {
        LinkNode cur = this.head;
        while(cur != null) {
            if(cur.value == key) {
                return true;
            }
            cur = cur.next;
        }
        return false;

    }

    @Override
    public void remove(int key) {
        if(this.head.value == key) {
            this.head = this.head.next;
            return ;
        }
        //找前驱
        LinkNode cur = findprev(key);
        //判断返回值
        if(cur != null) {
            //删除
            LinkNode del = cur.next;
            cur.next = del.next;
            //cur.next = cur.next.next;
        }
    }
    //找删除的前驱
    private LinkNode findprev(int key) {
        LinkNode cur = head;
            while(cur.next != null) {
                if(cur.next.value == key) {
                    return cur;
                }
                cur = cur.next;
            }
        return null;
    }

    @Override
    public void removeAllKey(int key) {
        if(size() == 0) {
            return ;
        }
        if(head.value == key) {
            head = head.next;
        }
        LinkNode cur = head.next;
        LinkNode prev = head;
        while(cur != null) {
            if(cur.value == key) {
                prev.next = cur.next;
            }
            prev = cur;
            cur = cur.next;
        }

    }

    @Override
    public int size() {
        LinkNode cur = head;
        int count = 0;
        while(cur != null) {
            count++;
            cur = cur.next;
        }
        return count;
    }

    @Override
    public void display() {
        LinkNode x = head;
        while(x != null) {
            System.out.print(x.value + " ");
            x = x.next;
        }
        System.out.println();
    }

    @Override
    public void clear() {
        LinkNode cur = head;
        while(cur != null) {
            LinkNode curNext = cur.next;
            cur.next = null;
            cur = curNext;
        }
        head = null;
    }
}
 indexillgality

At this time a custom exception

package myLinkedList;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: sun杰
 * Date: 2023-09-14
 * Time: 12:55
 */
public class indexillgality extends RuntimeException {
    public indexillgality(String message) {
        super(message);
    }
}

LinkedList

Simulation implementation of LinkedList

This is equivalent to the implementation of a headless doubly linked list. Here are the basic functions it requires:

// 2、无头双向链表实现
public class MyLinkedList {
//头插法
public void addFirst(int data){ }
//尾插法
public void addLast(int data){}
//任意位置插入,第一个数据节点为0号下标
public void addIndex(int index,int data){}
//查找是否包含关键字key是否在单链表当中
public boolean contains(int key){}
//删除第一次出现关键字为key的节点
public void remove(int key){}
//删除所有值为key的节点
public void removeAllKey(int key){}
//得到单链表的长度
public int size(){}
public void display(){}
public void clear(){}
}

MyLinkedList

package myLinkedList;

import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: sun杰
 * Date: 2023-09-20
 * Time: 18:49
 */
public class MyLinkedList implements IList {

    //单个节点
    public static class ListNode {
        private int val;
        private ListNode prev;
        private ListNode next;

        public ListNode(int val) {
            this.val = val;
        }
    }

    ListNode head;
    ListNode last;
    @Override
    public void addFirst(int data) {
        ListNode cur = new ListNode(data);
        if(head == null) {
            cur.next = head;
            head = cur;
            last = cur;
        }else {
            cur.next = head;
            head.prev = cur;
            head = cur;
        }

    }

    @Override
    public void addLast(int data) {
        ListNode cur = new ListNode(data);
        if(head == null) {
            head = cur;
            last = cur;
        } else {
            last.next = cur;
            cur.prev = last;
            last = cur;
        }
    }

    @Override
    public void addIndex(int index, int data) throws Indexexception {
        ListNode cur = new ListNode(data);
        if(index < 0 || index > size()) {
            throw new Indexexception("下标越界");
        }

        //数组为空时
        if(head == null) {
            head = cur;
            last = cur;
            return ;
        }

        //数组只有一个节点的时候
        if(head.next == null || index == 0) {
            head.prev = cur;
            cur.next = head;
            head = cur;
            return;
        }

        if(index == size()) {
            last.next = cur;
            cur.prev = last;
            return ;
        }

        //找到对应下标的节点
        ListNode x = head;
        while(index != 0) {
            x = x.next;
            index--;
        }

        //头插法
        cur.next = x;
        cur.prev = x.prev;
        x.prev.next = cur;
        x.prev = cur;

    }

    @Override
    public boolean contains(int key) {
        ListNode cur = head;
        while(cur != null) {
            if(cur.val == key) {
                return true;
            }
            cur = cur.next;
        }
        return false;
    }

    @Override
    public void remove(int key) {
        if(head == null) {
            return;
        }
        ListNode cur = head;
        while(cur != null) {
            if(cur.val == key) {
                if(cur.next == null && cur.prev == null) {
                    head = null;
                    last = null;
                    return;
                }else if(cur.next == null){
                    cur.prev.next = null;
                    last = cur.prev;
                    return;
                }else if(cur.prev == null) {
                    head = cur.next;
                    cur.next.prev = null;
                    return ;
                }else {
                    ListNode frone = cur.prev;
                    ListNode curnext = cur.next;
                    frone.next = curnext;
                    curnext.prev = frone;
                    return ;
                }

            }
            cur = cur.next;
        }

    }

    @Override
    public void removeAllKey(int key) {
        if(head == null) {
            return;
        }
        ListNode cur = head;
        while(cur != null) {
            if(cur.val == key) {
                if(cur.next == null && cur.prev == null) {
                    head = null;
                    last = null;
                } else if(cur.next == null){
                    cur.prev.next = null;
                    last = cur.prev;
                }else if(cur.prev == null) {
                    head = cur.next;
                    cur.next.prev = null;

                }else {
                    ListNode frone = cur.prev;
                    ListNode curnext = cur.next;
                    frone.next = curnext;
                    curnext.prev = frone;
                }
            }
            cur = cur.next;
        }

    }

    @Override
    public int size() {
        int count = 0;
        ListNode cur = head;
        while(cur != null) {
            count++;
            cur = cur.next;
        }
        return count;
    }

    @Override
    public void display() {
        ListNode cur = head;
        while(cur != null) {
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
        System.out.println();
    }

    @Override
    public void clear() {
        if(head == null) {
            return;
        }
        ListNode cur = head.next;
        while(cur != null) {
            head = null;
            head = cur;
            cur = cur.next;
        }
        head = null;
    }
}

Indexexception

This is also a custom exception

package myLinkedList;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: sun杰
 * Date: 2023-09-21
 * Time: 9:47
 */
public class Indexexception extends RuntimeException{
    public Indexexception(String message) {
        super(message);
    }
}

LinkedList in java

The bottom layer of LinkedList is a doubly linked list structure. Since the linked list does not store elements in a continuous space, the elements are stored in separate nodes, and the nodes are then connected through references. Because of this, when inserting and deleting elements at any position, there is no need to move the elements, which is more efficient. 

In the collection framework, LinkedList also implements the List interface:

Notice:

LinkedList implements the List interface

The underlying layer of LinkedList uses a doubly linked list

Linked does not implement the RandomAccess interface, so LinkedList does not support random access.

LinkedList is more efficient when inserting and deleting elements at random positions, with a complexity of O(1)

LinkedList is more suitable for inserting at any position.

Use of LinkedList

Construction of LinkedList:

Generally speaking there are two methods:

No-argument construction:

List<Integer> list = new LinkedList<>();

Construct a List using elements from other collection containers:

public LinkedList(Collection<? extends E> c)

chestnut:

public static void main(String[] args) {
// 构造一个空的LinkedList
        List<Integer> list1 = new LinkedList<>();
        List<String> list2 = new java.util.ArrayList<>();
        list2.add("JavaSE");
        list2.add("JavaWeb");
        list2.add("JavaEE");
// 使用ArrayList构造LinkedList
        List<String> list3 = new LinkedList<>(list2);
    }

Basic methods of LinkedList:

public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<>();
list.add(1); // add(elem): 表示尾插
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
list.add(7);
System.out.println(list.size());
System.out.println(list);
// 在起始位置插入0
list.add(0, 0); // add(index, elem): 在index位置插入元素elem
System.out.println(list);
list.remove(); // remove(): 删除第一个元素,内部调用的是removeFirst()
list.removeFirst(); // removeFirst(): 删除第一个元素
list.removeLast(); // removeLast(): 删除最后元素
list.remove(1); // remove(index): 删除index位置的元素
System.out.println(list);
// contains(elem): 检测elem元素是否存在,如果存在返回true,否则返回false
if(!list.contains(1)){
list.add(0, 1);
}
list.add(1);
System.out.println(list);
System.out.println(list.indexOf(1)); // indexOf(elem): 从前往后找到第一个elem的位置
System.out.println(list.lastIndexOf(1)); // lastIndexOf(elem): 从后往前找第一个1的位置
int elem = list.get(0); // get(index): 获取指定位置元素
list.set(0, 100); // set(index, elem): 将index位置的元素设置为elem
System.out.println(list);
// subList(from, to): 用list中[from, to)之间的元素构造一个新的LinkedList返回
List<Integer> copy = list.subList(0, 3);
System.out.println(list);
System.out.println(copy);
list.clear(); // 将list中元素清空
System.out.println(list.size());
}

Various traversals of LinkedList

foreach:

public static void main(String[] args) {
        List<Integer> list = new LinkedList<>();
        list.add(1);
        list.add(3);
        list.add(5);
        list.add(2);
        list.remove(1);
        for (int x:list) {
            System.out.print(x + " ");
        }
    }

Use iterator to traverse:

ListIterator<Integer> it = list.listIterator();
        while(it.hasNext()) {
            System.out.println(it.next() + " ");
        }
    }

The difference between ArrayList and LinkedList


Guess you like

Origin blog.csdn.net/paperjie/article/details/133240159