LinkedList与链表①——SingleLinkedList的模拟实现(简单)

一、LinkedList简介

适合插入与删除!!

在集合框架中,LinkedList也实现了List接口,具体如下:

【说明】

  1. LinkedList实现了List接口

  2. LinkedList的底层使用了双向链表

  3. LinkedList没有实现RandomAccess接口,因此LinkedList不支持随机访问

  4. LinkedList的任意位置插入和删除元素时效率比较高,时间复杂度为O(1)

二、LinkedList底层

LinkedList的底层是双向链表结构。由于链表没有将元素存储在连续的空间中,元素存储在单独的节点中,然后通过引用将节点连接起来了,因此,在任意位置插入或者删除元素时,不需要搬移元素,效率比较高

三、LinkedList构造

方法功能
LinkedList()无参构造
public LinkedList(Collection<? extends E> c)使用其他集合容器中元素构造List
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); 

}

四、LinkedList常用方法

方法功能
boolean add(E e)尾插 e
void add(int index, E element)将 e 插入到 index 位置
boolean addAll(Collection<? extends E> c)尾插 c 中的元素
E remove(int index)删除 index 位置元素
boolean remove(Object o)删除遇到的第一个 o
E get(int index)获取下标 index 位置元素
E set(int index, E element)将下标 index 位置元素设置为 element
void clear()清空
boolean contains(Object o)判断 o 是否在线性表中
int indexOf(Object o)返回第一个 o 所在下标
int lastIndexOf(Object o)返回最后一个 o 的下标
List<E> subList(int fromIndex, int toIndex)截取部分 list
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()); 

}

五、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()); 

    // foreach遍历 
    for (int e:list) { 
        System.out.print(e + " "); 
    }
    System.out.println(); 

    // 使用迭代器遍历---正向遍历 
    ListIterator<Integer> it = list.listIterator(); 
    while(it.hasNext()){ 
        System.out.print(it.next()+ " "); 
    }
    System.out.println(); 

    // 使用反向迭代器---反向遍历 
    ListIterator<Integer> rit = list.listIterator(list.size()); 
    while (rit.hasPrevious()){ 
        System.out.print(rit.previous() +" "); 
    }
    System.out.println(); 

}

六、链表

1. 概念

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

2.结构

单向链表:

双向链表:

 

七、SingleLinkedList模拟实现(简单)

无头单向非循环链表实现

//单向链表
class Node {
    public int val;
    public Node next;//类型是Node  null

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

}

public class SingleLinkedList{

    public Node head;//定义头节点
    public int usedSize;//记录当前链表中节点的个数


    //方法的模拟实现

}
  • 创建链表
    /**
     * 使用穷举的方式,创建链表
     */
    public void createList() {
        Node node1 = new Node(1);
        Node node2 = new Node(2);
        Node node3 = new Node(3);
        Node node4 = new Node(4);
        Node node5 = new Node(5);
        
        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;

        this.head = node1;
        this.usedSize = 5;
    }
  • 打印链表里面的元素
    /**
     * 打印链表里面的元素
     */
    public void myToString(){
        Node cur = this.head;
        while (cur != null) {
            System.out.print(cur.val+" ");
            cur = cur.next;
        }
    }
  • 查找是否包含关键字key是否在单链表当中
    //查找是否包含关键字key是否在单链表当中
    public boolean contains(int key){
        Node cur=this.head;
        while(cur!=null){
            if(cur.val==key){
                return true;
            }
            cur=cur.next;
        }
        return false;
    }
  • 得到单链表的长度
    //得到单链表的长度,不用定义的usedSize
    public int size(){
        int count=0;
        Node cur=this.head;
        while(cur!=null){
            count++;
            cur=cur.next;
        }
        return count;
    }
  • 头插法
    //头插法
    public void addFirst(int data) {
        Node node=new Node(data);
        if(this.head==null) {
            this.head=node;
        }
        else{
            node.next=this.head;
            this.head=node;
        }
        this.usedSize++;
    }
  • 尾插法
    //尾插法
    public void addLast(int data){
        Node node=new Node(data);
        if(this.head==null) {
            this.head=node;
        }
        else{
            Node cur=this.head;
            while(cur.next!=null){
                cur=cur.next;
            }
            cur.next=node;
        }
    }
  • 任意位置插入,第一个数据节点为0号下标
    //任意位置插入,第一个数据节点为0号下标
    public void addIndex(int index,int data){
        if(index<0||index>this.usedSize){
            throw new RuntimeException("index不合法!");
        }
        if(index==0){
            addFirst(data);
            return;
        }
        if(index==this.usedSize){
            addLast(data);
            return;
        }
        Node node=new Node(data);
        Node cur=this.head;
        for(int i=0;i<index-1;i++){
            cur=cur.next;
        }
        node.next=cur.next;
        cur.next=node;
        this.usedSize++;
    }
  • 删除第一次出现关键字为key的节点
    //删除第一次出现关键字为key的节点
    public void remove(int key){
        if(this.head==null) return;
        if(this.head.val==key){
            this.head=this.head.next;
            this.usedSize--;
            return;
        }
        Node prev=this.head;
        Node cur=this.head.next;
        while(cur!=null){
            if(cur.val==key){
                prev.next=cur.next;
                this.usedSize--;
                return;
            }
            else{
                prev=cur;
                cur=cur.next;
            }
        }
        if(prev.next==null){
            throw new RuntimeException("不存在你要删除的节点!");
        }
    }
  • 删除所有值为key的节点
    //删除所有值为key的节点
    public void removeAllKey(int key){
        if(this.head==null) return;
        Node prev=this.head;
        Node cur=this.head.next;
        while(cur!=null){
            if(cur.val==key){
                prev.next=cur.next;
                cur=cur.next;
                this.usedSize--; 
            }
            else{
                prev=cur;
                cur=cur.next;
            }
        }
        if(this.head.val==key){
            this.head=this.head.next; 
            this.usedSize--;
        }
    }
  • 清空列表
    /**
     * 清空列表
     */

    //方法一
    public void clear1(){
        this.head=null;
        this.usedSize=0;
    }

    //方法二
    public void clear2(){
        Node cur=this.head;
        while(cur!=null){
            Node curNext=cur.next;
            cur.next=null;
            cur=curNext;
        }
        this.head=null;
    }
  • 测试及运行结果
public static void main(String[] args) {

        SingleLinkedList singleLinkedList=new SingleLinkedList();
        singleLinkedList.createList();
        singleLinkedList.myToString();//12345

        System.out.println();
        System.out.println(singleLinkedList.size());//5

        System.out.println(singleLinkedList.contains(3));//true
        System.out.println(singleLinkedList.contains(9));//false

        singleLinkedList.addFirst(6);//612345
        singleLinkedList.myToString();

        System.out.println();
        singleLinkedList.addLast(7);//6123457
        singleLinkedList.myToString();

        System.out.println();
        singleLinkedList.addIndex(3,5);//61253457
        singleLinkedList.myToString();

        System.out.println();
        singleLinkedList.remove(2);//6153457
        singleLinkedList.myToString();

        System.out.println();
        singleLinkedList.removeAllKey(5);//61347
        singleLinkedList.myToString();

        System.out.println();
        singleLinkedList.clear1();
        singleLinkedList.myToString();

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值