1.链表:

链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序来实现的。

2.链表的模拟实现:

首先,创建一个MyLinkedList类:

class Node{
    public int data;//实例成员变量
    public Node next;
    
    public Node(){//无参构造
        
    }
    
    public  Node(int data){//带有一个参数的构造方法
        this.data = data;
    }
}

(1)创建链表

public class MyLinkedList{
    public Node head;//表示当前链表的头,其值默认为null

    //1.创建链表
    public void createLinked(){
        this.head = new Node(10);
        Node node2 = new Node(20);
        Node node3 = new Node(30);
        Node node4 = new Node(40);
        this.head.next= node2;
        node2.next = node3;
        node3.next = node4;
    }

    //2.打印链表
    public void display(){
        Node cur = this.head;
        while(cur != null){
            System.out.print(cur.data + " ");
            cur = cur.next;
        }
        System.out.println();
    }
}

测试代码:

public class Test {
    public static void main(String[] args) {
        MyLinkedList myLinkedList = new MyLinkedList();
        myLinkedList.createLinked();
        myLinkedList.display();
    }
}

运行结果:

jjquery能新增删除列的表格_jjquery能新增删除列的表格

(2)通过遍历,打印链表的每一个元素

//3.通过遍历,打印链表的每一个元素
    public void display(){
        Node cur = this.head;
        while(cur != null){
            System.out.print(cur.data + " ");
            cur = cur.next;
        }
        System.out.println();
    }

(3)通过遍历,找到链表的最后一个节点

//4.通过遍历,找到链表的最后一个节点
    public Node findLastNode(){
        if(this.head == null){
            System.out.println("head == null");
            return null;
        }
        Node cur = this.head;
        while(cur.next != null){
            cur = cur.next;
        }
        return cur;
    }

(4)通过遍历,找到链表的倒数第二个节点

//5.通过遍历,找到链表的倒数第二个节点
    public Node findLastTwo(){
        if(this.head == null){
            System.out.println("一个节点也没有!");
            return null;
        }
        if(this.head.next == null){
            System.out.println("只有一个节点!");
            return null;
        }
        Node cur = this.head;
        while(cur.next.next != null){
            cur = cur.next;
        }
        return cur;
    }

(5)通过遍历,找到链表的第n个节点(链表的长度 >= n)

//6.通过遍历,找到链表的第n个节点(链表的长度 >= n)
    public Node findN(int n){
        if(this.head == null){
            System.out.println("此链表为空!");
            return null;
        }
        if(n <= 0){
            System.out.println("输入的n太小了!");
            return null;
        }
        if(n > size()){
            System.out.println("输入的n超过了链表的长度了!");
            return null;
        }
        int count = 1;
        Node cur = this.head;
        while(count != n){
            count++;
            cur = cur.next;
        }
        return cur;
    }

(6)通过遍历,计算链表元素的个数

//7.通过遍历,计算链表元素的个数
    public int size(){
        Node cur = this.head;
        int count = 0;//计数
        while(cur != null){
            count++;
            cur = cur.next;
        }
        return count;
    }

(7)通过遍历,找到链表中是否包含某个元素

//8.通过遍历,找到链表中是否包含某个元素
    public boolean contains(int key){
        Node cur = this.head;
        while(cur != null){
            if(cur.data == key){
                return true;
            }
        }
        return false;
    }

(8)头插法

//9.头插法
    public void addFirst(int data){
        //0.创建节点
        Node node = new Node(data);
        //1.判断链表是否为空
        if(this.head == null){
           this.head = node;
        }else{
            //2.插入节点
            node.next = this.head;
            this.head = node;
        }
    }

(9)尾插法

//10.尾插法
    public void addLast(int data){
        //0.创建节点
        Node node = new Node(data);
        if(this.head == null){
            this.head = node;
        }else{
            //1. cur 找尾巴
            Node cur = this.head;
            while(cur.next != null){
                cur = cur.next;
            }
            //2.插入
            cur.next = node;
        }
    }

(10)任意位置插入,第一个数据节点为0号下标

//11.任意位置插入,第一个数据节点为0号下标
    public void addIndex(int index,int data) {
        if(index < 0 || index > size()){
            System.out.println("index位置不合法!");
            return;
        }
        //头插法
        if(index == 0){
            addFirst(data);
            return;
        }
        //尾插法
        if(index == size()){
            addLast(data);
            return;
        }
        //cur保存的是index- 1位置的节点的引用
        Node cur = moveIndex(index);
        Node node = new Node(data);
        node.next = cur.next;
        cur.next = node;
    }

    /***
     * 该函数的功能是找到index - 1位置的节点的引用
     * @param index
     * @return
     */
    public Node moveIndex(int index){
        Node cur = this.head;
        int count = 0;
        while (count != index - 1){
            cur = cur.next;
            count++;
        }
        return cur;
    }

(11)删除第一次出现关键字key的节点

//12.删除第一次出现关键字为key的节点
    public void remove(int key) {
        if(this.head == null){
            System.out.println("没有节点!");
        }

        if(this.head.data == key){//删除头结点
            this.head = this.head.next;
            return;
        }
        Node prev = searchPrev(key);
        if(prev == null){
            System.out.println("没有这个可以的前驱!");
        }
        else{
            Node del = prev.next;
            prev.next = del.next;
        }

    }

    /***
     * 此函数的作用找到要删除节点的前驱
     * @param key
     * @return
     */
    public Node searchPrev(int key){
       Node cur = this.head;
       while(cur.next != null){
           if(cur.next.data == key){
               return cur;//返回要删除节点的前驱
           }
           cur = cur.next;
       }
       return null;

    }

(12)删除所有值为key的节点

//13.删除所有值为key的节点
    public void removeAllKey(int key){
        if(this.head == null){
            return;
        }
        Node curHead = this.head;
        Node prev = this.head;
        Node cur = this.head.next;
        while(cur != null){
            if(cur.data == key){
                prev.next = cur.next;
                cur = cur.next;
            }else{
                prev = cur;
                cur = cur.next;
            }
        }
        if(this.head.data == key){
            this.head = this.head.next;
        }
    }

3.链表的问题

链表的缺点

(1)以节点为单位进行存储,不支持随机访问;

链表的优点

(1)任意位置插入删除时间复杂度为O(1);

(2)没有增容问题,插入一个开辟一个空间。