Java 链表与LinkedList

  1. 链表的组合形式
    ①有头结点、无头结点
    ②单向链表、双向链表
    ③循环链表、非循环链表
    根据自由组合,可以得到8种不同形式的链表,那么在刷题种常碰到的是不带有头结点的单向非循环链表不带头结点的双向非循环链表

  2. 模拟实现不带头结点的单向非循环链表的操作

public class MySingleLinkedList {
    //无头单向非循环链表的实现
    static class ListNode {
        int val;  //数值域
        ListNode next; //指向下一结点

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


    public ListNode head; //记录链表的头


    public void createNode() {
        ListNode listNode1 = new ListNode(1);
        ListNode listNode2 = new ListNode(3);
        ListNode listNode3 = new ListNode(5);
        ListNode listNode4 = new ListNode(7);
        listNode1.next = listNode2;
        listNode2.next = listNode3;
        listNode3.next = listNode4;

        head = listNode1;
    }
    //头插法
    public void addFirst(int data){
        ListNode node = new ListNode(data); //实例化这个结点
        if (head == null) {
            head = node;
        }
        //链表不为空的时候
        node.next = head;
        head = node;
    }
    //尾插法
    public void addLast(int data){
        ListNode node = new ListNode(data); //实例化这个结点
        if (head == null) {
            head = node;
        }
        //找到尾结点
        ListNode cur = head;
        while (cur.next != null) {
            cur = cur.next;
        }//此时cur指向的就是尾结点
        cur.next = node;

    }
    //任意位置插入,第一个数据节点为0号下标
    public void addIndex(int index,int data){
        if (index < 0 || index > size()) {
            //抛异常
            throw new IndexOutException("插入下标不合法");
        }
        if (index == 0) {
            //头插
            addFirst(data);
        }
        if (index == size()) {
            //尾插
            addLast(data);
        }
        //中间插
        ListNode cur = head;
        while (index-1 > 0) {
            cur = cur.next;
            index--;
        }//此时cur是要插入的前一个结点
        ListNode node = new ListNode(data); //实例化这个结点
        node.next = cur.next;
        cur.next = node;
    }
    //查找是否包含关键字key是否在单链表当中
    public boolean contains(int key){
        if (head == null) {
            return false;
        }
        ListNode cur = head;
        while (cur != null) {
            if (cur.val == key) {
                return true;
            }
            cur = cur.next;
        }
        return false;
    }
    //删除第一次出现关键字为key的节点
    public void remove(int key){
        if (head == null) {
            System.out.println("删除失败");
            return;
        }
        if (head.val == key) {
            head = head.next;
            return;
        }
        ListNode cur = head;
        while (cur.next != null) {
            if (cur.next.val == key) {
                cur.next = cur.next.next;
                return;
            }else {
                cur = cur.next;
            }
        }
    }
    //删除所有值为key的节点
    public void removeAllKey(int key){
        if (head == null) {
            System.out.println("删除失败");
            return;
        }
        while (head.val == key) {
            head = head.next;
        }
        ListNode curPre = head;
        ListNode cur = head.next;
        while (cur != null) {
            if (cur.val == key) {
                curPre.next = cur.next;
                cur = cur.next;
            }else {
                curPre = curPre.next;
                cur = cur.next;
            }
        }
    }
    //得到单链表的长度
    public int size(){
        if (head == null) {
            return -1;
        }
        ListNode cur = head; //为了让头结点不发生改变
        int count = 0;
        while (cur != null) {
            count++;
            cur = cur.next;
        }
        return count;
    }
    public void clear() {
        ListNode cur = head;
        while (cur != null) {
            ListNode curNext = cur.next;
            cur.next = null;
            cur = curNext;
        }
        head = null;
    }
    public void display() {
        ListNode cur = head; //为了让头结点不发生改变
        while (cur != null) {
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
        System.out.println();
    }

}

分析:
Java 链表与LinkedList_第1张图片

  1. 模拟实现不带头结点的单向非循环链表的操作(LinkedList)
public class MyLinkedList {
    //模拟双向链表
    static class ListNode {
        int val;  //数值域
        ListNode next; //指向下一结点
        ListNode prev; //指向上一结点

        public ListNode(int val) {
            this.val = val;
        }
    }
    public ListNode head; //头结点
    public ListNode last; //尾结点
    //创建结点
    public void createNode() {
        ListNode listNode1 = new ListNode(1);
        ListNode listNode2 = new ListNode(3);
        ListNode listNode3 = new ListNode(5);
        ListNode listNode4 = new ListNode(7);
        listNode1.next = listNode2;
        listNode2.prev = listNode1;
        listNode2.next = listNode3;
        listNode3.prev = listNode2;
        listNode3.next = listNode4;
        listNode4.prev = listNode3;
        head = listNode1;
        last = listNode4;
    }
//头插法
    public void addFirst(int data){
        ListNode node = new ListNode(data);
        if (head == null) {
            head = node;
            last = node;
        }else{
            node.next = head;
            head = node;
        }

    }
//尾插法
    public void addLast(int data){
        ListNode node = new ListNode(data);
        if (last == null ) {
            head = node;
            last = node;
        }else {
            last.next = node;
            last = node;
        }

    }
//任意位置插入,第一个数据节点为0号下标
    public void addIndex(int index,int data){
        if (index < 0 || index > size()) {
            throw new IndexOutException("下标不合法");
        }
        if (index == 0) {
            addFirst(data);
            return;
        }
        if (index == size()) {
            addLast(data);
            return;
        }
        ListNode cur = head;
        ListNode node = new ListNode(data);
        //找到要插入结点的前一个结点
        while (index-1 > 0) {
            cur = cur.next;
            index--;
        }
        node.next = cur.next;
        cur.next = node;
        node.next.prev = node;
        node.prev = cur;
    }
//查找是否包含关键字key是否在单链表当中
    public boolean contains(int key){
        ListNode cur = head;
        while (cur != null) {
            if (cur.val == key) {
                return true;
            }
            cur = cur.next;
        }
        return false;
    }
//删除第一次出现关键字为key的节点
    public void remove(int key){
        if (head == null) {
            return;
        }
        if (head.val == key) {
            if (head == last) {
                head = null;
                last = null;
                return;
            }else {
                head = head.next;
                head.prev = null;
                return;
            }
        }
        if (last.val == key) {
            if (head == last) {
                head = null;
                last = null;
                return;
            }else {
                last = last.prev;
                last.next = null;
                return;
            }
        }
        //要删的在中间
        ListNode cur = head;
        ListNode curNext = head.next;
        while (curNext != null) {
            if (curNext.val == key) {
                cur.next = curNext.next;
                curNext.next.prev = cur;
                return;
            }else {
                cur = cur.next;
                curNext = curNext.next;
            }
        }

    }
//删除所有值为key的节点
    public void removeAllKey(int key){
        ListNode cur = head;
        while (cur != null) {
            if(cur.val == key) {
                //判断当前是不是头节点
                if(cur == head) {
                    head = head.next;
                    if(head != null) {
                        head.prev = null;//一个节点
                    }
                }else {
                    //中间和尾巴的情况
                    cur.prev.next = cur.next;
                    if(cur.next != null) {
                        cur.next.prev = cur.prev;
                    }else {
                        last = last.prev;
                    }
                }
                cur = cur.next;
            }else {
                cur = cur.next;
            }
        }
    }
//得到单链表的长度
    public int size(){
        int count = 0;
        ListNode cur = head;
        while (cur != null) {
            cur = cur.next;
            count ++;
        }
        return count;
    }
    public void display(){
        ListNode cur = head;
        while (cur != null) {
            System.out.print(cur.val +" ");
            cur = cur.next;
        }
        System.out.println();
    }
    public void clear(){
        ListNode cur = head;
        while (cur != null) {
            ListNode curNext = cur.next;
            cur.next = null;
            cur.prev = null;
            cur = curNext;
        }
        head = null;
        last = null;
    }
}
  1. 关于LinkedList的使用
    LinkdeList实际上是一个双向的无头结点的非循环链表
    其构造方法有2种
        List<Integer> list = new ArrayList<>();
        list.add(1);
        LinkedList<Integer> list1 = new LinkedList<>();
        list1.add(6);
        LinkedList<Integer> list2 = new LinkedList<>(list);
        System.out.println(list1);
        System.out.println(list2);

①第一种是无参构造
②第二种是带参数构造,传入一个其他集合容器种的元素

  1. LinkedList的遍历
        LinkedList<Integer> list = new LinkedList<>();
        list.add(1);
        list.add(2);
        list.add(3);

①sout直接输出(必然重写例如toString)

        System.out.println(list);

②for-each

        for (int x: list) {
            System.out.println(x);
        }

③迭代器

        ListIterator<Integer> iterator =  list.listIterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next());
        }
        //逆序
        ListIterator<Integer> iterator1 =  list.listIterator(list.size());
        while (iterator1.hasPrevious()) {
            System.out.print(iterator1.previous());
        }
  1. 关于链表和顺序表的区别
    ①存储空间上:顺序表逻辑上相邻物理位置上也一定相邻;链表逻辑上相邻,但是物理位置上不一定相邻
    ②随机访问:顺序表可以随机访问,而链表需要从头到尾遍历访问
    ③插入删除效率:顺序表插入和删除需要移动大量的元素,但是链表不需要

你可能感兴趣的:(Java数据结构,链表,java,数据结构)