数据结构(Java实现):链表与LinkedList

news2024/9/20 12:39:32

文章目录

  • 1. 单向链表
    • 1.1 链表的概念及结构
    • 1.2 链表的实现
      • 1.2.1 单向链表类和节点
      • 1.2.2 打印每个节点的值
      • 1.2.3 计算链表长度
      • 1.2.4 头插节点
      • 1.2.5 尾插节点
      • 1.2.6 在指定下标插入新节点
      • 1.2.7 判断是否存在某个节点
      • 1.2.8 移除某个节点
      • 1.2.9 移除所有指定节点
      • 1.2.10 清空链表
      • 1.2.11 测试代码
    • 1.3 链表相关习题及题解
  • 2. LinkedList(双向链表)
    • 2.1 LinkedList的模拟实现(MyLinkedList)
      • 2.1.1 双向链表类和节点
      • 2.1.2 前插节点
      • 2.1.3 尾插节点
      • 2.1.4 指定位置插入节点
      • 2.1.5 判断是否有目标节点
      • 2.1.6 删除第一次出现的关键字的节点
      • 2.1.7 删除所有目标节点
      • 2.1.8 链表长度
      • 2.1.9 打印链表
      • 2.1.10 清空链表
      • 2.1.11 测试代码
  • 3. LinkedList的使用
    • 3.1 什么是LinkedList
    • 3.2 LinkedList的使用
  • 4. ArrayList和LinkedList的区别

1. 单向链表

1.1 链表的概念及结构

链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。
在这里插入图片描述
在这里插入图片描述
注意:

  1. 从上图可以看出,链式结构在逻辑上是连续的,但物理上不一定连续。
  2. 现实中的节点一般都是从堆上申请出来的。
  3. 从堆上申请的空间,是按照一定的策略来分配的,再次申请的空间可能连续,也可能不连续。

实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:

  1. 单向或者双向
    在这里插入图片描述
  2. 带头或者不带头在这里插入图片描述
  3. 循环或者非循环在这里插入图片描述

虽然有这么多的链表的结构,但是我们重点掌握两种:

  • 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。在这里插入图片描述
  • 无头双向链表:在Java的集合框架库中LinkedList底层实现就是无头双向循环链表。

在这里插入图片描述

1.2 链表的实现

1.2.1 单向链表类和节点

链表的节点我们通过内部类的方式来实现,这个类包含一个值val和下一节点的地址。外部类需要再定义一个头结点。

public class MySingleLinkedList {
    static class ListNode{//节点
        public int val;
        public ListNode next;
        //内部类构造方法,给节点赋值
        public ListNode(int val){
            this.val=val;
            this.next=null;
        }
    }
    //链表的头节点
    public ListNode head = null;
}

下面我们来一步一步分析并实现一些自定义链表的功能,包含在MySingleLinkedList类里面。

1.2.2 打印每个节点的值

我们通过遍历链表来实现每个节点值的打印,注意:我们不能使用头节点去遍历我们的链表,这可能会使我们的链表结构发生改变,所以我们重新创建一个节点cur来遍历链表,下面遍历也是同样的方法。

public void display(){
        ListNode cur=head;
        while (cur!=null){//cur走到最后的next为null,停止循环
            System.out.print(cur.val+" ");
            cur=cur.next;//遍历
        }
        System.out.println();
    }

1.2.3 计算链表长度

跟打印相同的方式进行遍历,然后使用count计数,每遍历一次就加1。然后返回count。

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

1.2.4 头插节点

头插节点仅需要将新增节点的next指向头节点,然后让新增节点化为头节点。

public void addFirst(int val){
        ListNode node = new ListNode(val);//新增节点
        node.next=head;//新增节点的next指向头节点
        head=node;//新增节点化为头节点
    }

1.2.5 尾插节点

尾差节点需要将整个链表遍历完,然后让尾节点的next指向新节点。此时要注意,如果头节点为空就要使新增节点划定位头节点。

public void addLast(int val){
        ListNode node = new ListNode(val);//创建新节点
        //头节点为空就要使新增节点划定位头节点
        if(head == null){
            head = node;
            return;
        }
       //遍历链表
        ListNode cur = head;
        while (cur.next!=null){
            cur=cur.next;
        }
        //尾结点指向新节点
        cur.next=node;
    }

1.2.6 在指定下标插入新节点

这里要进行一个判断,判断输入的下标是否合法。因此我们自定义了一个受查异常。

public class IndexLegal extends RuntimeException{
    public IndexLegal(){}

    public IndexLegal(String arg){
        super(arg);
    }
}

然后我们通过遍历定位到指定位置的前一个节点,然后使用新节点的next指向定位节点的下一个节点,定位节点指向新增节点。此处两个步骤不能相反。

public void addIndex(int val, int index){
		//判断位置是否合法
        if(index<0||index>this.size()-1){
            throw new IndexLegal("传入位置不合法!");
        }
        //新节点
        ListNode node=new ListNode(val);
        ListNode cur=head;
        //定位到指定节点的前一个节点
        for (int i = 0; i < index-1; i++) {
            cur=cur.next;
        }
        //新节点的next指向定位节点的下一个节点
        node.next=cur.next;
        //定位节点指向新增节点
        cur.next=node;
    }

1.2.7 判断是否存在某个节点

此处只需要遍历节点,如果某个节点的值等于传入值就返回true,否则返回false。

public boolean contains(int val){
        ListNode cur=head;
        //遍历链表
        while (cur!=null){
            if(cur.val==val){
                return true;//判断为真返回true
            }
            cur=cur.next;
        }
        return false;//遍历完没有返回就不存在指定节点
    }

1.2.8 移除某个节点

如果要移除的节点在头节点就将头结点设置为头结点的next。如果为其他节点,先进行遍历,定位到指定节点的前一个节点,然后让定位节点指向定位节点的next的next。

public void remove(int val){
		//判断指定节点是否为头节点
        if(head.val==val){
        //头结点设置为头结点的next
            head=head.next;
            return;
        }
        ListNode cur=head;
        //遍历链表
        while (cur.next!=null){
        //定位到指定节点的前一个节点
            if(cur.next.val==val){
            //定位节点指向定位节点的next的next。
                cur.next=cur.next.next;
                return;
            }
        }
    }

1.2.9 移除所有指定节点

此时我们可以有两种方法:

  1. 创建一个虚拟头节点,当遍历到的节点不是指定节点就连接上虚拟头结点的那条链表,然后虚拟头结点的next就是所需节点。这里就不进行写入演示了。
  2. 通过使用一个前驱节点和遍历节点,前驱节点指向头节点,遍历节点指向头结点的next。然后遍历链表,当遍历到的节点不是目标节点,就让前驱节点指向遍历节点。如果是目标节点,遍历节点就一直遍历下去,前驱节点next指向遍历节点,由此来达到删除目标节点的功能。最后要判断头结点是否为目标节点,如果是就将头结点转换为头结点的next。
public void removeAll(int val){
        ListNode cur=head.next;//遍历节点
        ListNode prev=head;//前驱节点
        //遍历链表
        while (cur!=null){
        //当遍历到的节点不是目标节点,就让前驱节点指向遍历节点
            if (cur.val != val) {
                prev = cur;
            }
            //如果是目标节点,遍历节点就一直遍历下去
            cur=cur.next;
            //前驱节点next指向遍历节点,由此来达到删除目标节点的功能
            prev.next=cur;
        }
        if(head.val==val){//判断头结点是否为目标节点
        //如果为真,就将头结点转换为头结点的next
            head=head.next;
        }
    }

1.2.10 清空链表

如果进使用head=null,其他节点并没有得到释放。所以我们需要通过遍历来一个一个释放节点,最后再释放头结点。

public void clear(){
        ListNode cur=head;
        while (cur!=null){
            ListNode curN=head.next;
//如果使用cur=null并不能释放当前节点,因为cur只是当前节点的一个副本。
//对cur的操作并不能影响到当前节点。
            cur.next=null;//一个一个释放节点
            cur=curN;
        }
        head=null;//最后释放头结点
    }

1.2.11 测试代码

	public static void main(String[] args) {
        MySingleLinkedList sl=new MySingleLinkedList();
        //尾插
        sl.addLast(12);
        sl.addLast(23);
        sl.addLast(34);
        sl.addLast(45);
        sl.addLast(56);
        //打印
        sl.display();
        System.out.println("==============");
        //头插
        sl.addFirst(11);
        sl.display();
        System.out.println("==============");
        //指定位置插
        sl.addIndex(99,3);
        sl.display();
        //大小
        System.out.println(sl.size());
        //判断
        System.out.println(sl.contains(12));
    }
    public static void main(String[] args) {
        MySingleLinkedList sl=new MySingleLinkedList();
        sl.addLast(11);
        sl.addLast(12);
        sl.addLast(11);
        sl.addLast(14);
        sl.addLast(11);
        sl.addLast(11);
        sl.addLast(15);
        sl.display();
        System.out.println("===========");
        //删除指定节点
        sl.remove(12);
        sl.display();
        System.out.println("===========");
        //删除所有节点
        sl.removeAll(11);
        sl.display();
    }
    public static void main(String[] args) {
        MySingleLinkedList sl=new MySingleLinkedList();
        //当所有节点都为要删除的节点的情况
        sl.addLast(11);
        sl.addLast(11);
        sl.addLast(11);
        sl.addLast(11);
        sl.addLast(11);
        sl.removeAll(11);
        sl.display();
    }
    public static void main(String[] args) {
        MySingleLinkedList sl=new MySingleLinkedList();
        sl.addLast(11);
        sl.addLast(11);
        sl.addLast(11);
        sl.addLast(11);
        sl.addLast(11);
        sl.display();
        //清空链表
        sl.clear();
        sl.display();
    }
 	public static void main(String[] args) {
        MySingleLinkedList sl=new MySingleLinkedList();
    }  
	public static void main(String[] args) {
        MySingleLinkedList sl=new MySingleLinkedList();
    }
 

在这里插入图片描述
在这里插入图片描述

1.3 链表相关习题及题解

链表相关习题及题解
写完这些习题可以更好帮助你迅速掌握和理解链表。(建议去做一下)

2. LinkedList(双向链表)

特点:每一个节点都包含了前驱和后继。

2.1 LinkedList的模拟实现(MyLinkedList)

2.1.1 双向链表类和节点

public class MyLinkedList {
    static class ListNode{//节点
        public int val;//节点值
        public ListNode next;//后继
        public ListNode prev;//前驱
        public ListNode(int val){//构造方法
            this.val=val;
            this.next=null;
            this.prev=null;
        }
    }
    public ListNode head;//头节点
    public ListNode last;//尾节点
    }

特点:每一个节点都包含了前驱和后继。下面这些方法在这个自定义双向链表实现的。

2.1.2 前插节点

前插节点之前先判断头节点是否为null,如果为空将插入节点设置为头结点和尾结点。不为空就使头节点的前驱指向新节点,新节点的后继指向头结点,然后将新节点设置为头结点。
在这里插入图片描述

public void addFirst(int data){
        ListNode node=new ListNode(data);
        if(head==null){//先判断头节点是否为null
        //为空将插入节点设置为头结点和尾结点
            head=last=node;
        }else {
        //不为空
            head.prev=node;//头节点的前驱指向新节点
            node.next=head;//新节点的后继指向头结点
            head=node;//将新节点设置为头结点
        }
    }

2.1.3 尾插节点

尾插节点之前先判断尾节点是否为null,如果为空将插入节点设置为头结点和尾结点。如果不为空,尾结点的后继指向新节点,新节点的前驱指向尾节点,将新节点设置为尾节点。
在这里插入图片描述

public void addLast(int data){
        ListNode node=new ListNode(data);
        //先判断尾节点是否为null
        if(last==null){
        //如果为空将插入节点设置为头结点和尾结点
            head=last=node;
        }else {
        //如果不为空
            last.next=node;//尾结点的后继指向新节点
            node.prev=last;//新节点的前驱指向尾节点
            last=node;//将新节点设置为尾节点
        }
    }

2.1.4 指定位置插入节点

在指定位置插入节点需要先判断传入的位置是否合法。如果合法,判断位置是否为头或者尾,如果为头就调用头插法,如果为尾就调用尾插法。如果为中间,需要改变的指向的位置如下。
在这里插入图片描述

public void addIndex(int index,int data){
		//判断位置是否合法
        if(index<0||index>size()){
            return;
        }
        ListNode node=new ListNode(data);
        //头插
        if(index==0) {
            addFirst(data);
        }else if(index==size()){//尾插
            addLast(data);
        }
        //找到对应位置的节点
        ListNode cur = findIndexNode(index);
        //指针指向转换
        node.next=cur;
        cur.prev.next=node;
        node.prev=cur.prev;
        cur.prev=node;
    }
    //寻找目标节点
    private ListNode findIndexNode(int index){
        ListNode cur = head;
        for (int i = 0; i < index; i++) {
            cur=cur.next;
        }
        return cur;
    }

2.1.5 判断是否有目标节点

从头遍历链表,如果节点的目标值等于传入值,返回true。遍历完链表没有返回true,就不存在目标节点,返回false。

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

2.1.6 删除第一次出现的关键字的节点

首先从头遍历整条链表,如果找到关键字的节点,先判断此节点是否为头节点,如果为头节点让头结点设置为头节点的next。然后判断头结点是否为null,如果为null此链表就只存在一个节点,此时将头和尾设置为null就行,否则将头结点的前驱设置为null。如果不是头结点就需要让目标节点的前驱节点的后置节点指向目标节点的后置节点。如果目标节点的后置节点为null(目标节点为尾结点)就将尾结点设置为尾结点的前驱节点。否则让目标节点的后置节点的前驱设置为目标节点的前驱。删除后返回。
在这里插入图片描述

public void remove(int key){
        ListNode cur=head;
        while (cur!=null){//首先从头遍历整条链表
            if(cur.val==key){//如果找到关键字的节点
                if(cur==head){//判断此节点是否为头节点
                //如果为头节点让头结点设置为头节点的next
                    head=head.next;
                    if(head!=null){//判断头结点是否为null
                    //将头结点的前驱设置为null
                        head.prev=null;
                    }else {
                    //此链表就只存在一个节点,此时将头和尾设置为null
                        last=null;
                    }
                }else {//不为头节点
                //让目标节点的前驱节点的后置节点指向目标节点的后置节点
                    cur.prev.next=cur.next;
//目标节点的后置节点为null(目标节点为尾结点)就将尾结点设置为尾结点的前驱节点
                    if(cur.next==null){
                        last=last.prev;
                    }else {//目标节点的后置节点的前驱设置为目标节点的前驱
                        cur.next.prev=cur.prev;
                    }
                }
                return;
            }
            cur=cur.next;
        }
    }

2.1.7 删除所有目标节点

此时只要将上面的返回去掉能达到删除所有目标节点的效果。

public void remove(int key){
        ListNode cur=head;
        while (cur!=null){//首先从头遍历整条链表
            if(cur.val==key){//如果找到关键字的节点
                if(cur==head){//判断此节点是否为头节点
                //如果为头节点让头结点设置为头节点的next
                    head=head.next;
                    if(head!=null){//判断头结点是否为null
                    //将头结点的前驱设置为null
                        head.prev=null;
                    }else {
                    //此链表就只存在一个节点,此时将头和尾设置为null
                        last=null;
                    }
                }else {//不为头节点
                //让目标节点的前驱节点的后置节点指向目标节点的后置节点
                    cur.prev.next=cur.next;
//目标节点的后置节点为null(目标节点为尾结点)就将尾结点设置为尾结点的前驱节点
                    if(cur.next==null){
                        last=last.prev;
                    }else {//目标节点的后置节点的前驱设置为目标节点的前驱
                        cur.next.prev=cur.prev;
                    }
                }
            }
            cur=cur.next;
        }
    }

2.1.8 链表长度

定义一个count,然后遍历链表,每遍历一次count就++。最后返回count就是链表的长度。

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

2.1.9 打印链表

遍历链表,然后打印每个节点的值。

public void display(){
        ListNode cur=head;
        while (cur!=null){//遍历链表
            System.out.print(cur.val+" ");//打印节点的值
            cur=cur.next;
        }
        System.out.println();
    }

2.1.10 清空链表

遍历节点,然后将节点的前驱和后置置为空。

public void clear(){
        ListNode cur=head;
        while (cur!=null){//遍历链表
            ListNode curN=cur.next;
            cur.prev=null;//前驱置空
            cur.next=null;//后继置空
            cur=curN;
        }
        head=last=null;
    }

2.1.11 测试代码

//清空链表测试
	public static void main(String[] args) {
        MyLinkedList ll=new MyLinkedList();
        ll.addFirst(1);
        ll.addFirst(2);
        ll.addFirst(3);
        ll.addFirst(4);
        ll.addFirst(5);
        ll.clear();
        ll.display();

    }
    //移除所有目标节点测试
    public static void main(String[] args) {
        MyLinkedList ll=new MyLinkedList();
        ll.addLast(1);
        ll.addLast(1);
        ll.addLast(1);
        ll.addLast(1);
        ll.addLast(1);
        ll.addLast(1);
        ll.display();
        ll.removeAllKey(1);
        System.out.println("=========");
        ll.display();
    }
    //移除目标值和判断目标节点测试
    public static void main(String[] args) {
        MyLinkedList ll=new MyLinkedList();
        ll.addLast(1);
        ll.addLast(2);
        ll.addLast(3);
        ll.addLast(4);
        ll.addLast(5);
        ll.remove(1);
        ll.display();
        ll.remove(3);
        ll.display();
        System.out.println(ll.contains(2));
        System.out.println(ll.contains(3));
    }
    //尾插和指定位置插测试
    public static void main(String[] args) {
        MyLinkedList ll=new MyLinkedList();
        ll.addLast(1);
        ll.addLast(2);
        ll.addLast(3);
        ll.addLast(4);
        ll.addLast(5);
        ll.display();
        System.out.println("================");
        ll.addIndex(2,99);
        ll.display();
    }
    //前插测试
    public static void main(String[] args) {
        MyLinkedList ll=new MyLinkedList();
        ll.addFirst(1);
        ll.addFirst(2);
        ll.addFirst(3);
        ll.addFirst(4);
        ll.addFirst(5);
        ll.display();
    }

3. LinkedList的使用

3.1 什么是LinkedList

LinkedList官方文档
LinkedList的底层是双向链表结构,由于链表没有将元素存储在连续的空间中,元素存储在单独的节点中,然后通过引用将节点连接起来了,因此在在任意位置插入或者删除元素时,不需要搬移元素,效率比较高。LinkedList还被当做双向链表来使用。
在这里插入图片描述
在这里插入图片描述
【说明】

  1. LinkedList实现了List接口
  2. LinkedList的底层使用了双向链表
  3. LinkedList没有实现RandomAccess接口
  4. LinkedList的任意位置插入和删除元素时效率比较高,删除时时间复杂度为O(1)
  5. LinkedList比较适合任意位置插入的场景

知识补充:RandomAccess接口简介
RandomAccess接口是一个标记接口,用以标记实现的List集合具备快速随机访问的能力。
当一个List拥有快速访问功能时,其遍历方法采用for循环最快速。而没有快速访问功能的List,遍历的时候采用Iterator迭代器最快速。

if(list instanceof RandomAccess) {//判断链表是否实现RandomAccess接口
    // for循环
    System.out.println("采用for循环遍历");
    for (int i = 0;i< list.size();i++) {
        System.out.println(list.get(i));
    }
} else {
    // 迭代器
    System.out.println("采用迭代器遍历");
    Iterator it = list.iterator();
    while(it.hasNext()){
        System.out.println(it.next());
    }
}

3.2 LinkedList的使用

  1. LinkedList的构造方法在这里插入图片描述
    可以看到第二个构造方法有一个参数,解析如下。
    在这里插入图片描述
    有了第二种构造方法,我们可以复制相同类型或相同类型的子类的链表或者顺序表。
    public static void main(String[] args) {
        ArrayList<Integer> list1=new ArrayList<>();
        list1.add(1);
        list1.add(2);
        list1.add(3);

        LinkedList<Integer> list2=new LinkedList<>(list1);//复制顺序表
        System.out.println(list2);
        
        LinkedList<Integer> list3=new LinkedList<>();
        list3.add(4);
        list3.add(5);
        list3.add(6);
        
        LinkedList<Integer> list4=new LinkedList<>(list3);//复制链表
        System.out.println(list4);
    }
  1. LinkedList的其他常用方法介绍在这里插入图片描述
    上面的一些常用的方法跟我们第二模块模拟实现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());

    }
  1. LinkedList的遍历
public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();
        list.add(1);
        list.add(2);
        list.add(3);

        System.out.println("===for循环===");
        for (int i = 0; i < list.size(); i++) {
            System.out.print(list.get(i)+" ");
        }
        System.out.println();

        System.out.println("===for-each===");
        for (Integer x:list) {
            System.out.print(x+" ");
        }
        System.out.println();

        System.out.println("===Iterator迭代器===");
        Iterator<Integer> it1= list.iterator();
        while (it1.hasNext()){
            System.out.print(it1.next()+" ");
        }
        System.out.println();

        System.out.println("===ListIterator迭代器===");
        ListIterator<Integer> it2=list.listIterator();//ListIterator实现Iterator接口,专属于list的迭代器
        while (it2.hasNext()){
            System.out.print(it2.next()+" ");
        }
        System.out.println();

        System.out.println("===ListIterator迭代器反向遍历===");
        ListIterator<Integer> it3=list.listIterator(list.size());//ListIterator的反向遍历(区别于普通Iterator迭代器)
        while (it3.hasPrevious()){
            System.out.print(it3.previous()+" ");
        }
        System.out.println();
    }

运行结果
在这里插入图片描述

4. ArrayList和LinkedList的区别

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2072641.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux:管道】

进程间通信背景&#xff1a; 每一个进程想要访问物理内存&#xff0c;都是通过访问进程虚拟地址空间当中的虚拟地址进行访问&#xff0c;访问时&#xff0c;通过各自的页表结构&#xff0c;造成了每一个进程和每一个进程的数据独立&#xff0c;由于进程独立性的存在&#xff0c…

Java | Leetcode Java题解之第373题查找和最小的K对数字

题目&#xff1a; 题解&#xff1a; class Solution {public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {int m nums1.length;int n nums2.length;/*二分查找第 k 小的数对和的大小*/int left nums1[0] nums2[0];int right nums…

Github 2024-08-25 php开源项目日报 Top10

根据Github Trendings的统计,今日(2024-08-25统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量PHP项目10Blade项目1Laravel: 以优雅语法简化Web开发 创建周期:4028 天开发语言:PHP协议类型:MIT LicenseStar数量:30824 个Fork数量:1052…

windows安装wsl,出现错误WslRegisterDistribution failed with error: 0x8007019e的解决方案

错误WslRegisterDistribution failed with error: 0x8007019e 笔者直接从Microsoft Store 安装 WSL后&#xff0c;没有其他操作&#xff0c;直接打开WSL&#xff0c;结果出现Error: 0x8007019e错误提示&#xff1a; Error 0x8007019e 解决方案 &#xff08;1&#xff09;Win…

滑块自动化分析

大家好!我是炒青椒不放辣,关注我,收看每期的编程干货。 滑块分析是爬虫工程师进阶必备技能,当我们遇到一个问题时可能会有多种解决途径,而如何做出高效的抉择和完善的解决流程又需要经验的积累。本期文章将以实战的方式,带你使用 playwright 进行滑块分析,不仅会告诉你应…

iPhone抹掉数据后能恢复吗?详解数据恢复的可能性与方法

在使用iPhone的过程中&#xff0c;有时候我们会因为各种原因选择“抹掉所有内容和设置”&#xff0c;以期望将手机恢复到出厂状态。然而&#xff0c;一旦执行了这个操作&#xff0c;很多用户就会开始担心&#xff1a;iPhone抹掉数据后&#xff0c;这些数据还能恢复吗&#xff1…

VMware安装Ubuntu20.04

1. 下载 整理的镜像链接 阿里网盘&#xff1a;阿里云盘快传 2. 新建虚拟机向导 选择自定义&#xff0c;然后下一步。 默认配置&#xff0c;下一步。 选择稍后安装操作系统&#xff0c;下一步。 选择操作系统Linux&#xff0c;版本Ubuntu64位&#xff0c;下一步。 给虚拟机命名…

2534. 乘方 [CSP-J 2022]

代码 #include<bits/stdc.h> using namespace std; int main() {long long n,m,i,sum1;cin>>n>>m;for(i1;i<m;i){sum*n;if(sum>1000000000){cout<<-1;return 0;;}}cout<<sum;return 0; } 记得点赞关注收藏&#xff01;&#xff01;&…

根据股票列表获取资金流入情况

获取股票列表 作为演示&#xff0c;以创业板为例&#xff08;数据不多&#xff09;&#xff0c;我们通过自编的 get_stock_list 方法获取股票列表&#xff1a; import pandas from bad import BigAData from tqdm.notebook import tqdmplate cyb bad BigAData() json bad.…

180页某项目可视化智能停车场系统技术解决方案WORD

今天分享的是一份《180页某项目可视化智能停车场系统技术解决方案WORD》&#xff0c;资料详细完整的描述了关于数智化停车场的建设方案&#xff0c;参考价值很高。 传统停车场存在进出场效率低、找车位难、找车难、管理难、管理成本高等诸多问题&#xff0c;本次建设的XX项目将…

四、控制结构

文章目录 引言一、顺序控制二、分支控制&#xff08;if&#xff0c;else&#xff0c;switch&#xff09;2.1 if 单分支2.2 if 双分支2.3 if 多分支2.4 if 嵌套分支2.5 switch分支结构2.6 switch和if的比较 三、循环控制&#xff08;for&#xff0c;while&#xff0c;dowhile&am…

[Linux#47][网络] 网络协议 | TCP/IP模型 | 以太网通信

目录 1.网络协议 2.协议分层 2.1 OSI七层模型 2.2TCP/IP五层(四层)模型 2.3 以太网通信 1.网络协议 "协议"本质就是一种约定 计算机之间的传输媒介是光信号和电信号. 通过 "频率" 和 "强弱" 来表示 0 和 1 这样的 信息. 要想传递各种不同…

全志616系统启动和登录

一、系统启动 刷完机烧入镜像&#xff0c;直接用MobaXterm软件串口登陆 约定固定的波特率115200。 默认登录&#xff1a; 用户&#xff1a;orangepi 密码&#xff1a;orangepi 或用户&#xff1a;root 密码&#xff1a;orangepi 在输入密码时…

SEO之网站结构优化(十三-网站地图)

** 初创企业搭建网站的朋友看1号文章&#xff1b;想学习云计算&#xff0c;怎么入门看2号文章谢谢支持&#xff1a; ** 1、我给不会敲代码又想搭建网站的人建议 2、“新手上云”能够为你开启探索云世界的第一步 博客&#xff1a;阿幸SEO~探索搜索排名之道 网站无论大小&…

5分钟学会使用Linux的 grep、find、ls、wc 命令

Linux基础命令和工具 一、前导&#xff1a;概述1.1、监控1.2、测试1.3、优化 二、grep 搜索字符三、find 查找文件四、ls 显示文件五、wc 命令六、总结 一、前导&#xff1a;概述 本系列主要讲解Linux运行时命令&#xff0c;包括网络、磁盘、内存、CPU相关参数等&#xff0c;主…

伏图芯片应力仿真功能介绍

随着电子产品向小型化、规模化、集成化方向发展&#xff0c;机械应力对器件性能的影响日益显著。产品在晶圆加工、芯片封装、元器件装配等过程中均会受到机械应力的作用&#xff0c;可能会直接影响芯片的电性能和可靠性。 仿真技术在芯片产品研发设计和故障排查阶段扮演着至关…

Python | Leetcode Python题解之第372题超级次方

题目&#xff1a; 题解&#xff1a; class Solution:def superPow(self, a: int, b: List[int]) -> int:MOD 1337ans 1for e in b:ans pow(ans, 10, MOD) * pow(a, e, MOD) % MODreturn ans

NIOS Eclipse突然报错:No rule to make target `/system.h

NIOS Eclipse突然报错&#xff1a;No rule to make target /system.h 今天打开NIOS Eclipse编译昨天完好的工程&#xff0c;发现报错。我就纳闷了&#xff0c;代码没有修改&#xff0c;编译结果报错 控制台中problems选线中显示&#xff1a; No rule to make target /system…

嵌入式开发神器——vim配置

本期主题&#xff1a; 讲解vim的一些配置&#xff0c;让大家也可以用上自己定制化的vim 目录 0. 目前个人所用的vim配置截图1. vim的插件1. 怎么找插件2. 如何安装插件3. 安装好了如何使用插件 2. 个人配置的vim链接 0. 目前个人所用的vim配置截图 1. vim的插件 1. 怎么找插件…

【Qt】输入类控件QSlider

目录 输入类控件QSlider 例子&#xff1a;调整窗口大小 例子&#xff1a;通过自定义快捷键调整滑动条位置 输入类控件QSlider 使用QSlider表示一个滑动条 QDail与QSlider都继承于QAbstractSlider&#xff0c;所以其用法基本相似。 核心属性 属性说明 value 持有的数值 mi…