LinkedList概念+MyLinkedList的实现

文章目录


LinkedList笔记


一、 LinkedList

1.概念

LinkedList的底层是一个双向链表

  • 在插入和删除时,不用挪动元素
  • 在获取尾部结点时,不需要遍历获取,直接利用last结点

2.LinkedList的构造方法

  • 分为无参构造和有参构造

有参:使用其他集合容器中元素构造List

在构造LinkedList的时候,传递的参数的类型要满足指定泛型的上界,同时要实现Collection接口

3.LinkedList的遍历

分别用重写的print方法、foreach、迭代器进行遍历

java 复制代码
 public static void main(String[] args) {
        LinkedList<String> linkedList = new LinkedList<>();
        linkedList.add("hello");
        linkedList.add("world");
        linkedList.add("!");
        linkedList.add("?");
        linkedList.add("|");
        System.out.println(linkedList);
        System.out.println("-----------");
        for (String x:linkedList) {
            System.out.print(x+" ");
        }
        System.out.println();
        System.out.println("-----------");
        //使用迭代器遍历-正向遍历
        ListIterator<String> it = linkedList.listIterator();
        while (it.hasNext()){
            System.out.print(it.next()+" ");
        }
        System.out.println();
        System.out.println("===========");

        ListIterator<String> rit = linkedList.listIterator(linkedList.size());
        while (rit.hasPrevious()){
            System.out.print(rit.previous()+" ");
        }

        //使用迭代器遍历-反向遍历
    }

二、MyLinkedList的实现

1.定义内部类

与单链表不同的是,双链表的结点新增了prev域

java 复制代码
public class MyLinkedList {
    static class ListNode{
        public int val;
        public ListNode prev;//前驱
        public ListNode next;//后继

        public ListNode(int val) {//构造方法
            this.val = val;
        }
    }
    public ListNode head;//定义头结点
    public ListNode last;//定义尾结点

1.在内部类中定义结点的元素

2.定义构造器

3.创建头/尾结点

2.打印链表、求链表长度、判断是否包含关键字

与单链表的形式相同

java 复制代码
 public void  disPlay(){
        ListNode cur = head;
        while (cur!=null){ 
            System.out.print(cur.val+" ");
            cur = cur.next;
        }
        System.out.println();
    }

    /**
     *求链表长度
     * @return int
     */
    public int size(){
        ListNode cur = head;
        int count = 0;
        while (cur!=null){
            count++;
            cur = cur.next;
        }
        return count;
    }

    /**
     * 查看在链表中是否包含关键字key
     * @param key
     * @return
     */
    public boolean contains(int key){
        ListNode cur = head;
        while (cur != null){
            if (cur.val == key){
                return true;
            }
            cur = cur.next;
        }
        return false;
    }

3. 头插法和尾插法

java 复制代码
    /**
     * 头插法
     * o(1)
     * @param data
     */
    public void addFirst(int data){
        ListNode node = new ListNode(data);
        if (head ==null){
            head = node;
            last = node;
        }else {
            node.next = head;
            head.prev = node;
            head = node;//头结点前移
        }
    }

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

因为尾插的时候有last结点,不用进行尾结点的遍历查找

所以双链表尾插的时间复杂度是 o(1)

4.在任意位置插入

java 复制代码
  public void addIndex(int index, int data) {

        if (index < 0 || index > size()) {//判断索引是否超出
           return;
        }
        if (index == 0) {//利用头插
            addFirst(data);
            return;
        }
        if (index == size()) {//利用尾插
            addLast(data);
            return;
        }
        ListNode node = new ListNode(data);
        ListNode cur = head;
        while (index!=0){//找到索引的位置
            cur = cur.next;
            index--;
        }
        node.next = cur;
        cur.prev.next = node;
        node.prev = cur.prev;
        cur.prev = node;
    }

1.先判断索引下标是否溢出

2.如果索引是开头或者末尾的位置,调用写好的头插法和尾插法

3.通过遍历找到索引的位置cur

4.将cur插入链表中

  • 先改变node的next域,
  • 将node与cur相连 将cur的前驱的next域,改为node,
  • 将node与cur的前一个结点相连
  • 将node前驱改为cur前驱的地址 将cur的前驱改为node的地址值

5.删除结点

java 复制代码
    public void remove(int key) {
        ListNode cur = head;
        while (cur != null) {
            if (cur.val == key) {
                if (cur == head) {//删的是头的情况
                    head = head.next;
                    if (head!=null){//如果只有一个结点,移动后前驱不需要置空
                        head.prev = null;//head的前驱置为空
                    }

                } else {//删除中间或者尾部
                    cur.prev.next = cur.next;
                    if (cur == last) {//如果是尾部
                        last = last.prev;
                    } else {//删除的是中间
                        cur.next.prev = cur.prev;
                    }
                }
                return;
            }
            cur = cur.next;
        }
    }

1.通过遍历找到值等于key的结点

2.如果要删的是头结点,头结点向后移动一位。如果移动后的头结点不为空,将此时头结点的前驱置为空

3.如果要删除的cur是尾结点,将cur前驱的地址值指向cur的下一个地址,将last向前移动一位

4.如果要删除的是中间结点,将cur前驱的地址值指向cur的下一个地址,将cur后继的前驱指向cur的前驱

6.清空链表

java 复制代码
 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.遍历链表,用curNext记录cur的下一个结点

2.将cur的前驱和后继置为null

3.将头结点和尾结点置为空。

点击移步博客主页,欢迎光临~

相关推荐
哎呦没18 分钟前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
Kalika0-035 分钟前
猴子吃桃-C语言
c语言·开发语言·数据结构·算法
编程、小哥哥1 小时前
netty之Netty与SpringBoot整合
java·spring boot·spring
代码雕刻家1 小时前
课设实验-数据结构-单链表-文教文化用品品牌
c语言·开发语言·数据结构
IT学长编程2 小时前
计算机毕业设计 玩具租赁系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·课程设计·毕业论文·计算机毕业设计选题·玩具租赁系统
莹雨潇潇2 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器
杨哥带你写代码2 小时前
足球青训俱乐部管理:Spring Boot技术驱动
java·spring boot·后端
小字节,大梦想2 小时前
【C++】二叉搜索树
数据结构·c++
我是哈哈hh3 小时前
专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结
服务器·数据结构·c++·算法·机器学习·深度优先·剪枝
郭二哈3 小时前
C++——模板进阶、继承
java·服务器·c++