篇章五 数据结构——链表(一)

news2025/6/7 0:21:29

目录

1.ArrayList的缺陷

2. 链表

2.1 链表的概念及结构

2.2 链表结构

1. 单向或者双向

2.带头或者不带头

3.循环或者非循环

2.3 链表的实现

1.完整代码

2.图解

 3.显示方法

4.链表大小

5. 链表是否存在 key 值

6.头插法

7.尾插法

8.中间插入

9.删除key值节点

 10.删除所有key值节点

11.clear

3.练习

3.1 删除链表中等于给定值 val 的所有节点

3.2 反转一个单链表

3.3 给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点

3.4 输入一个链表,输出该链表中倒数第k个结点

 3.5 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的

3.6 编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前

​编辑

3.7 链表的回文结构

3.8 输入两个链表,找出它们的第一个公共结点

3.9 给定一个链表,判断链表中是否有环

3.10 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 NULL


1.ArrayList的缺陷

通过篇章四,我们已经熟悉了ArrayList的使用,并且进行了简单模拟实现。通过源码知道,ArrayList底层使用数组来存储元素。

那这样会出现什么问题呢?

        由于其底层是一段连续空间,当在ArrayList任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后搬移,时间复杂度为O(n),效率比较低。因此ArrayList不适合做任意位置插入和删除比较多的场景。因此:java集合中又引入了LinkedList,即链表结构。

2. 链表

2.1 链表的概念及结构

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

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

2.2 链表结构

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

1. 单向或者双向

什么是双向?

2.带头或者不带头

什么是带头?

什么是不带头?

3.循环或者非循环

什么是循环?

组合成的 8种链表结构

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

1. 无头单向非循环链表结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。

2. 无头双向非循环链表:在Java的集合框架库中LinkedList底层实现就是无头双向循环链表。

2.3 链表的实现

1.完整代码


/**
 * Created with IntelliJ IDEA
 * Description  无头单向非循环链表实现
 * User: 王杰
 * Date: 2025-05-26
 * Time: 20:33
 */
public class MySingleList implements IList{
    static class ListNode {
        public int val;
        public ListNode next;

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

    public ListNode head;

    // 创建链表
    public void createList() {
        ListNode node1 = new ListNode(12);
        ListNode node2 = new ListNode(23);
        ListNode node3 = new ListNode(34);
        ListNode node4 = new ListNode(45);
        ListNode node5 = new ListNode(56);

        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;
        this.head = node1;
    }

    // 显示方法
    @Override
    public void display() {
        ListNode cur = head;
        while (cur != null) {
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
    }

    // 链表大小
    @Override
    public int size() {
        int len = 0;
        ListNode cur = head;
        while (cur != null) {
            len++;
            cur = cur.next;
        }
        return len;
    }

    // 链表是否存在 key 值
    @Override
    public boolean contains(int key) {
        ListNode cur = head;
        while (cur != null) {
            if (cur.val == key) {
                return true;
            }
            cur = cur.next;
        }
        return false;
    }

    // 头插法
    @Override
    public void addFirst(int data) {
        ListNode node = new ListNode(data);

        node.next = head;
        head = node;
    }

    // 尾插法
    @Override
    public void addLast(int data) {
        ListNode node = new ListNode(data);

        // 一个节点都没有
        if (head == null) {
            head = node;
            return;
        }

        // 找尾巴
        ListNode cur = head;
        while (cur != null) {
            if (cur.next == null) {
                cur.next = node;
                return;
            }
            cur = cur.next;
        }
    }

    //中间插入
    @Override
    public void addIndex(int index, int data) {
        int len = size();
        if (index < 0 || index > len) {
            System.out.println("index位置不存在");
            return;
        }

        if (index == 0) {
            addFirst(data);
            return;
        }

        if (index == len) {
            addLast(data);
            return;
        }

        // 中间插入
        ListNode cur = head;
        if (index - 1 != 0) {
            cur = cur.next;
            index--;
        }
        ListNode node = new ListNode(data);
        // 所有的插入 优先 绑定后边
        node.next = cur.next;
        cur.next = node;

    }



    // 删除 key值 节点
    @Override
    public void remove(int key) {
        if (head == null) {
            return;
        }

        // 删除头节点
        if (head.val == key) {
            head = head.next;
            return;
        }

        ListNode cur = findNodeOfKey(key);
        if (cur == null) {
            return;
        }
        ListNode del = cur.next;
        cur.next = del.next;
    }

    private ListNode findNodeOfKey(int key) {
        ListNode cur = head;
        while (cur.next != null) {
            if (cur.next.val == key) {
                return cur;
            }
            cur = cur.next;
        }
        return null;
    }

    // 删除 所有key值 节点
    @Override
    public void removeAllKey(int key) {
        if (head == null) {
            return;
        }

        ListNode prev = head;
        ListNode cur = head.next;

        while (cur != null) {
            if (cur.val == key) {
                prev.next = cur.next;
                cur = cur.next;
            }else {
                prev = cur;
                cur = cur.next;
            }
        }

        if (head.val == key) {
            head = head.next;
        }
    }

    @Override
    public void clear() {
        ListNode cur = head;
        while (cur != null) {
            ListNode curNext = cur.next;
            cur.next = null;
            cur = curNext;
        }
        head = null;
    }



}

2.图解

单向不带头非循环链表:

 3.显示方法

// 显示方法
@Override
public void display() {
    ListNode cur = head;
    while (cur != null) {
        System.out.print(cur.val + " ");
        cur = cur.next;
    }
}

4.链表大小

	// 链表大小
    @Override
    public int size() {
        int len = 0;
        ListNode cur = head;
        while (cur != null) {
            len++;
            cur = cur.next;
        }
        return len;
    }

实现到这里,我们需要掌握的是:

1.ListNode cur = head; 

        此处申请了临时变量,因为数据存储在堆空间,而且 cur 也指向链表,所以改变有效。同时 此处也是为了不改变 head 的位置,因为后续要用head找到该链表,如果head位置变动了,就找不到该链表了。

2.cur != null;

        此处最后一个节点,是会运算的。最后,cur指向的是最后一个节点的下一个节点,也就是 null;

3.cur.next != null;

        此处最后一个节点,是不会运算的。最后,cur指向的是最后一个节点。

5. 链表是否存在 key 值

    // 链表是否存在 key 值
    @Override
    public boolean contains(int key) {
        ListNode cur = head;
        while (cur != null) {
            if (cur.val == key) {
                return true;
            }
            cur = cur.next;
        }
        return false;
    }

6.头插法

    // 头插法
    @Override
    public void addFirst(int data) {
        ListNode node = new ListNode(data);

        node.next = head;
        head = node;
    }

7.尾插法

	// 尾插法
    @Override
    public void addLast(int data) {
        ListNode node = new ListNode(data);

        // 一个节点都没有
        if (head == null) {
            head = node;
            return;
        }

        // 找尾巴
        ListNode cur = head;
        while (cur != null) {
            if (cur.next == null) {
                cur.next = node;
                return;
            }
            cur = cur.next;
        }
    }

8.中间插入

	//中间插入
    @Override
    public void addIndex(int index, int data) {
        int len = size();
        if (index < 0 || index > len) {
            System.out.println("index位置不存在");
            return;
        }

        if (index == 0) {
            addFirst(data);
            return;
        }

        if (index == len) {
            addLast(data);
        }

        // 中间插入
        ListNode cur = head;
        if (index - 1 != 0) {
            cur = cur.next;
            index--;
        }

        ListNode node = new ListNode(data);
        // 所有的插入 优先 绑定后边
        node.next = cur.next;
        cur.next = node;

    }

注意:

1.此处中间插入,关键是找到 要 插入的位置前一个位置

2.要牢记 所有的插入 优先 绑定后边

9.删除key值节点

	// 删除 key值 节点
    @Override
    public void remove(int key) {
        if (head == null) {
            return;
        }

        // 删除头节点
        if (head.val == key) {
            head = head.next;
            return;
        }

        ListNode cur = findNodeOfKey(key);
        if (cur == null) {
            return;
        }
        ListNode del = cur.next;
        cur.next = del.next;

    }

    private ListNode findNodeOfKey(int key) {
        ListNode cur = head;
        while (cur.next != null) {
            if (cur.next.val == key) {
                return cur;
            }
            cur = cur.next;
        }
        return null;
    }

注意:

        找到 要删除的节点 的前一个节点

这一思路在单链表中很关键

 10.删除所有key值节点

	// 删除 所有key值 节点
    @Override
    public void removeAllKey(int key) {
        if (head == null) {
            return;
        }

        ListNode prev = head;
        ListNode cur = head.next;

        while (cur != null) {
            if (cur.val == key) {
                prev.next = cur.next;
                cur = cur.next;
            }else {
                prev = cur;
                cur = cur.next;
            }
        }

        if (head.val == key) {
            head = head.next;
        }
    }

11.clear

    @Override
    public void clear() {
        ListNode cur = head;
        while (cur != null) {
            ListNode curNext = cur.next;
            cur.next = null;
            cur = curNext;
        }
        head = null;
    }

注意:

         此处最后 head 也要置空

3.练习

3.1 删除链表中等于给定值 val 的所有节点

203. 移除链表元素 - 力扣(LeetCode)

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeElements(ListNode head, int val) {
        if (head == null) {
            return head;
        }

        ListNode prev = head;
        ListNode cur = head.next;

        while (cur != null) {
            if (cur.val == val) {
                prev.next = cur.next;
                cur = cur.next;
            }else {
                prev = cur;
                cur = cur.next;
            }
        }

        if (head.val == val) {
            head = head.next;
        }
        return head;
    }
}

203. 移除链表元素 - 力扣(LeetCode) 此处和 2.3 中的 10.删除所有key节点 一样

3.2 反转一个单链表

OJ链接

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        if(head == null) {
            return head;
        }

        ListNode cur = head.next;
        head.next = null;

        while(cur != null) {
            ListNode curNext = cur.next;

            cur.next = head;
            head = cur;
            cur = curNext;
        }

        return head;
    }
}

3.3 给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点

OJ链接

  /**
   * Definition for singly-linked list.
   * public class ListNode {
   *     int val;
   *     ListNode next;
   *     ListNode() {}
   *     ListNode(int val) { this.val = val; }
   *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
   * }
   */
  class Solution {
      public ListNode middleNode(ListNode head) {
          if(head == null) {
              return null;
          }

          ListNode fast = head;
          ListNode slow = head;
          while(fast != null && fast.next != null) {
              slow = slow.next;
              fast = fast.next.next;
          }     
          return slow;  
      }
  }

注意:

        做这些练习的时候,要考虑 空链表 的情况,也就是 head == null 

3.4 输入一个链表,输出该链表中倒数第k个结点

OJ链接

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public int kthToLast(ListNode head, int k) {
        if(head == null) {
            return -1;
        }

        ListNode fast = head;
        ListNode slow = head;

        // fast 走 k - 1 步
        int count = 0;        
        while(count != k - 1) {
            fast = fast.next;
            count++;
        }

        while(fast.next != null) {
            slow = slow.next;
            fast = fast.next;
        }

        return slow.val;
    }
}

注意:

1. fast.next != null;

        此处 fast 走到最后一个节点即可,不必走到 null

2.此处 k 值,不确定是否合法,一般题目中会设置范围,但是没设置的话就需要补充上k值合法性的校验

补充:验证 k 的合法性

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public int kthToLast(ListNode head, int k) {
        if(head == null) {
            return -1;
        }

        if(k <= 0) {
            return -1;
        }

        ListNode fast = head;
        ListNode slow = head;

        // fast 走 k - 1 步
        int count = 0;        
        while(count != k - 1) {
            fast = fast.next;
            if(fast == null) {
                return -1;
            }
            count++;
        }

        while(fast.next != null) {
            slow = slow.next;
            fast = fast.next;
        }

        return slow.val;
    }
}

 3.5 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的

OJ链接

  /**
   * Definition for singly-linked list.
   * public class ListNode {
   *     int val;
   *     ListNode next;
   *     ListNode() {}
   *     ListNode(int val) { this.val = val; }
   *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
   * }
   */
  class Solution {
      public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
          ListNode newHead = new ListNode();
          ListNode cur = newHead;

          while(list1 != null && list2 != null) {
              if(list1.val > list2.val) {
                  cur.next = list2;
                  list2 = list2.next;
                  cur = cur.next;
              }else {
                  cur.next = list1;
                  list1 = list1.next;
                  cur = cur.next;
              }
          }

          if(list1 != null) {
              cur.next = list1;
          }

          if(list2 != null) {
              cur.next = list2;
          }

          return newHead.next;
      }
  }

3.6 编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前

OJ链接

import java.util.*;

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Partition {
    public ListNode partition(ListNode pHead, int x) {
        ListNode cur = pHead;
        
        ListNode beforStart = null;
        ListNode beforEnd = null;

        ListNode afterStart = null;
        ListNode afterEnd = null;

        while(cur != null) {
            if(cur.val < x) {
                if(beforStart == null) {
                    beforStart = cur;
                    beforEnd = cur;
                }else {
                    beforEnd.next = cur;
                    beforEnd = beforEnd.next;
                }
                cur = cur.next;
            }else {
                if(afterStart == null) {
                    afterStart = cur;
                    afterEnd = cur;
                }else {
                    afterEnd.next = cur;
                    afterEnd = afterEnd.next;
                }
                cur = cur.next;
            }  
        }

        if(beforStart == null) {
            return afterStart;
        }

        // 置空 afterEnd.next
        if(afterStart != null) {
            afterEnd.next = null;
        }

        beforEnd.next = afterStart;

        return beforStart;
    }
}

注意:

此处思路:是把 大于x 和 小于x 的值分为两个链表。

但是:注意特殊情况,比如大于x的链表为空 和 小于x的链表为空。

而且:要注意,在 小于x的链表不为空时, 置空 afterEnd.next

3.7 链表的回文结构

OJ链接

import java.util.*;

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class PalindromeList {
    public boolean chkPalindrome(ListNode A) {
        if(A == null) {
            return true;
        }

        ListNode fast = A;
        ListNode slow = A;

        while(fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }

        ListNode cur = slow.next;

        while(cur != null) {
            ListNode curNext = cur.next;
            cur.next = slow;
            slow = cur;
            cur =curNext;
        } 

        while(A != slow) {
            if(A.val != slow.val) {
                return false;
            }

            // 偶数情况
            if(A.next == slow) {
                return true;
            }

            A = A.next;
            slow = slow.next;
        }
        return true;
    }
}

注意:

1.  三步走:找中间节点,反转中间节点后的链表,比较前半部分和后半部分链表的val值

2. 偶数情况:
            if(A.next == slow) {
                return true;
            }

3.8 输入两个链表,找出它们的第一个公共结点

OJ链接

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode pLong = headA;
        ListNode pShort = headB;

        // 先求两个链表的长度
        int lenA = 0;
        int lenB = 0;
        while(pLong != null) {
            lenA++;
            pLong = pLong.next;
        }
        while(pShort != null) {
            lenB++;
            pShort = pShort.next;
        }

        pLong = headA
        pShort = headB

        // 求差值
        int len = lenA - lenB;
        if(len < 0) {
            pLong = lenB;
            pShort = lenA;
            len = lenB - lenA;
        }

        // 走完上述两步 pLong 一定指向最长的链表  pShort 一定指向最短的链表
        // 接下来的操作 只需要操作 pLong 和 pShort 就行了

        // 让最长的链表走 len 步
        while(len != 0) {
            pLong = pLong.next;
            len--;
        }

        // 两个引用同时走 直到他们相遇
        while(pLong != pShort) {
            pLong = pLong.next;
            pShort = pShort.next;
        }

        if(pLong == null) {
            return null; // 不相交
        }
        
        return pLong;
    }
}

注意:

1.主要思路就是:走两个链表长度的差值步

2. 此处注意还原 pLong 和 pShort ,因为算长度,他们的位置发生了改变,要还原,否则影响下面代码

        pLong = headA
        pShort = headB

3.注意不相交的情况:

        if(pLong == null) {
            return null; // 不相交
        }

3.9 给定一个链表,判断链表中是否有环

OJ链接

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head == null) {
            return false;
        }

        if(head.next == null) {
            return false;
        }
        ListNode fast = head;
        ListNode slow = head;
        while(fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow) {
                return true;
            }
        }
        return false;
    }
}

【思路】

        快慢指针,即慢指针一次走一步,快指针一次走两步,两个指针从链表起始位置开始运行,如果链表带环则一定会在环中相遇,否则快指针率先走到链表的末尾。比如:陪女朋友到操作跑步减肥。

【扩展问题】

  • 为什么快指针每次走两步,慢指针走一步可以?

    假设链表带环,两个指针最后都会进入环,快指针先进环,慢指针后进环。当慢指针刚进环时,可能就和快

    指针相遇了,最差情况下两个指针之间的距离刚好就是环的长度。此时,两个指针每移动一次,之间的距离就缩小一步,不会出现每次刚好是套圈的情况,因此:在慢指针走到一圈之前,快指针肯定是可以追上慢指针的,即相遇。

  • 快指针一次走3步,走4步,...n步行吗?

 注意:

1.链表为空,和只有一个节点的情况是不存在环的

        if(head == null) {
            return false;
        }

        if(head.next == null) {
            return false;
        }

2.快慢指针的步数问题:

        快 2 慢 2:会相遇

        快3 慢 1 :永不相遇

可见:并不是快指针比慢指针快就行,还得注意步数问题。

3.10 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 NULL

OJ链接

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;

        if(head == null) {
            return null;
        }

        if(head.next == null) {
            return null;
        }

        while(fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow) {
                break;
            }
        }

        if(fast == null || fast.next == null) {
            return null; // 没有环
        }

        slow = head;
        while(slow != fast) {
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }
}

【结论】

        让一个指针从链表起始位置开始遍历链表,同时让一个指针从判环时相遇点的位置开始绕环运行,两个指针都是每次均走一步,最终肯定会在入口点的位置相遇。

【证明】

 注意:

1.链表为空,和只有一个节点的情况是不存在环的

        if(head == null) {
            return false;
        }

        if(head.next == null) {
            return false;
        }

2.相遇时出循环:

        while(fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow) {
                break;
            }
        }

3.去除没有环的情况:

        if(fast == null || fast.next == null) {
            return null; // 没有环
        }

4.关键:让慢指针回到链表开头,然后慢指针与快指针以相同的速度走

        slow = head;
        while(slow != fast) {
            fast = fast.next;
            slow = slow.next;
        }

5.证明:此处最关键的是,fast的路程是slow路程的二倍,建立等式,计算,取极端情况 得出关系,写代码。

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

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

相关文章

一文清晰理解目标检测指标计算

一、核心概念 1.交并比IoU 预测边界框与真实边界框区域的重叠比&#xff0c;取值范围为[0,1] 设预测边界框为&#xff0c;真实边界框为 公式&#xff1a; IoU计算为两个边界框交集面积与并集面积之比&#xff0c;图示如下 IoU值越高&#xff0c;表示预测边界框与真实边界框的对…

Artificial Analysis2025年Q1人工智能发展六大趋势总结

2025年第一季度人工智能发展六大趋势总结 ——基于《Artificial Analysis 2025年Q1人工智能报告》 趋势一&#xff1a;AI持续进步&#xff0c;竞争格局白热化 前沿模型竞争加剧&#xff1a;OpenAI凭借“o4-mini&#xff08;高智能版&#xff09;”保持领先&#xff0c;但谷歌&…

高效管理 Python 项目的 UV 工具指南

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 持续学习&#xff0c;不断…

初识vue3(vue简介,环境配置,setup语法糖)

一&#xff0c;前言 今天学习vue3 二&#xff0c;vue简介及如何创建vue工程 Vue 3 简介 Vue.js&#xff08;读音 /vjuː/&#xff0c;类似 “view”&#xff09;是一款流行的渐进式 JavaScript 框架&#xff0c;用于构建用户界面。Vue 3 是其第三代主要版本&#xff0c;于 …

LeetCode-链表操作题目

虚拟头指针&#xff0c;在当前head的前面建立一个虚拟头指针&#xff0c;然后哪怕当前的head的val等于提供的val也能进行统一操作 203移除链表元素简单题 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(…

【ARM】MDK浏览信息的生成对于构建时间的影响

1、 文档目标 用于了解MDK的代码浏览信息的生成对于工程的构建是否会产生影响。 2、 问题场景 客户在MDK中使用Compiler 5对于工程进行构建过程中发现&#xff0c;对于是否产生浏览信息会对于构建时间产生一定的影响。在Options中Output栏中勾选了Browse Information后&#…

py爬虫的话,selenium是不是能完全取代requests?

selenium适合动态网页抓取&#xff0c;因为它可以控制浏览器去点击、加载网页&#xff0c;requests则比较适合静态网页采集&#xff0c;它非常轻量化速度快&#xff0c;没有浏览器开销&#xff0c;占用资源少。当然如果不考虑资源占用和速度&#xff0c;selenium是可以替代requ…

docker B站学习

镜像是一个只读的模板&#xff0c;用来创建容器 容器是docker的运行实例&#xff0c;提供了独立可移植的环境 https://www.bilibili.com/video/BV11L411g7U1?spm_id_from333.788.videopod.episodes&vd_sourcee60c804914459274157197c4388a4d2f&p3 目录挂载 尚硅谷doc…

SpringBoot高校宿舍信息管理系统小程序

概述 基于SpringBoot的高校宿舍信息管理系统小程序项目&#xff0c;这是一款非常适合高校使用的信息化管理工具。该系统包含了完整的宿舍管理功能模块&#xff0c;采用主流技术栈开发&#xff0c;代码结构清晰&#xff0c;非常适合学习和二次开发。 主要内容 这个宿舍管理系…

ICASSP2025丨融合语音停顿信息与语言模型的阿尔兹海默病检测

阿尔兹海默病&#xff08;Alzheimers Disease, AD&#xff09;是一种以认知能力下降和记忆丧失为特征的渐进性神经退行性疾病&#xff0c;及早发现对于其干预和治疗至关重要。近期&#xff0c;清华大学语音与音频技术实验室&#xff08;SATLab&#xff09;提出了一种将停顿信息…

LabVIEW杂草识别与精准喷洒

基于LabVIEW构建了一套集成机器视觉、智能决策与精准控制的农业杂草识别系统。通过高分辨率视觉传感器采集作物图像&#xff0c;利用 LabVIEW 的 NI Vision 模块实现图像颜色匹配与特征分析&#xff0c;结合 Arduino 兼容的工业级控制硬件&#xff0c;实现杂草定位与除草剂精准…

学习日记-day20-6.1

完成目标&#xff1a; 知识点&#xff1a; 1.集合_Collections集合工具类 方法:static <T> boolean addAll(Collection<? super T> c, T... elements)->批量添加元素 static void shuffle(List<?> list) ->将集合中的元素顺序打乱static <T>…

【音视频】 FFmpeg 解码H265

一、概述 实现了使用FFmpeg读取对应H265文件&#xff0c;并且保存为对应的yuv文件 二、实现流程 读取文件 将H265/H264文件放在build路径下&#xff0c;然后指定输出为yuv格式 在main函数中读取外部参数 if (argc < 2){fprintf(stderr, "Usage: %s <input file&…

软件测试|FIT故障注入测试工具——ISO 26262合规下的智能汽车安全验证引擎

FIT&#xff08;Fault Injection Tester&#xff09;是SURESOFT专为汽车电子与工业控制设计的自动化故障注入测试工具​&#xff0c;基于ISO 26262等国际安全标准开发&#xff0c;旨在解决传统测试中效率低、成本高、安全隐患难以复现的问题&#xff0c;其核心功能包括&#xf…

3D拟合测量水杯半径

1&#xff0c;目的。 测量水杯的半径 如图所示&#xff1a; 2&#xff0c;原理。 对 3D 点云对象 进行圆柱体拟合&#xff0c;获取拟合后的半径。 3&#xff0c;注意事项。 在Halcon中使用fit_primitives_object_model_3d进行圆柱体拟合时&#xff0c;输出的primitive_para…

Python训练打卡Day38

Dataset和Dataloader类 知识点回顾&#xff1a; Dataset类的__getitem__和__len__方法&#xff08;本质是python的特殊方法&#xff09;Dataloader类minist手写数据集的了解 在遇到大规模数据集时&#xff0c;显存常常无法一次性存储所有数据&#xff0c;所以需要使用分批训练的…

Selenium基础操作方法详解

Selenium基础操作方法详解&#xff1a;从零开始编写自动化脚本&#xff08;附完整代码&#xff09; 引言 Selenium是自动化测试和网页操作的利器&#xff0c;但对于新手来说&#xff0c;掌握基础操作是成功的第一步。本文将手把手教你使用Selenium完成浏览器初始化、元素定位、…

简单三步FastAdmin 开源框架的安装

简单三步FastAdmin 开源框架的安装 第一步&#xff1a;新建站点1&#xff0c;在宝塔面板中&#xff0c;创建一个新的站点&#xff0c;并填写项目域名。 第二步&#xff1a;上传框架1&#xff0c;框架下载2&#xff0c;上传解压缩 第三步&#xff1a;配置并安装1&#xff0c;进入…

RISC-V 开发板 MUSE Pi Pro 搭建 Spacengine AI模型部署环境

视频讲解&#xff1a; RISC-V 开发板 MUSE Pi Pro 搭建 Spacengine AI模型部署环境 Spacengine 是由 进迭时空 研发的一套 AI 算法模型部署工具&#xff0c;可以方便的帮助用户部署自己的模型在端侧&#xff0c; 环境部署的方式&#xff0c;官方提供了两种方式&#xff1a; do…

【Unity】AudioSource超过MaxDistance还是能听见

unity版本&#xff1a;2022.3.51f1c1 将SpatialBlend拉到1即可 或者这里改到0 Hearing audio outside max distance - #11 by wderstine - Questions & Answers - Unity Discussions