【数据结构】_4.List接口实现类LinkedList与链表

news2025/1/13 17:31:35

目录

1.链表的结构与特点

1.1 链表的结构:

1.2 链表的特点:

2. 不带头单链表的模拟实现

3. 单链表OJ

3.1 题目1:移除链表元素: 

3.2 题目2:反转一个单链表

3.3 题目3:返回链表的中间结点

3.4 题目4:链表的倒数第k个结点

3.5 题目5:合并两个有序链表

3.6 题目6:链表的回文结构

3.7 题目7:链表分割

3.8 题目8:相交链表

3.9 题目9:环形链表

 3.10 题目10:环形链表Ⅱ

4. LinkedList的模拟实现

5. LinkedList的使用

6.LinkedList和ArrayList的区别


1.链表的结构与特点

1.1 链表的结构:

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

(2)现实中常见的链表有8种结构:

单向与双向,带头或不带头,循环或非循环,组合起来就有8种结构;

最常用的是:① 单向不带头非循环链表; ② 双向不带头非循环;

1.2 链表的特点:

(1)链表是由结点构成的,每个节点至少包括两个域:当前结点的数据与下一个结点的地址;

(2)链表的链式结构在逻辑上是连续的,但是物理上不一定连续;

(3)结点一般都是在堆上申请出来的;

2. 不带头单链表的模拟实现

(1)包类关系:

(2)MySingleList:

package TestMySingleList;
// 不带头的非循环单链表
public class MySingleList {
    static class Node{
        public int val;  //存储数据
        public Node next;  //存储下一个结点的地址
        public Node(int val){
            this.val = val;
        }
    }
    public Node head;  // 代表当前链表的头结点的引用
    public void createLink(){
        Node node1 = new Node(12);
        Node node2 = new Node(45);
        Node node3 = new Node(23);
        Node node4 = new Node(90);
        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        head = node1;
    }
    //成员方法1:遍历并打印链表
    public void display(){
        Node cur = head;
      while(cur!=null){
          System.out.print(cur.val+" ");
          cur=cur.next;
      }
    }
    //重载:从指定位置开始遍历打印列表
    public void display(ListNode newHead){
        ListNode cur = newHead;
        while(cur!=null){
            System.out.print(cur.val+" ");
            cur = cur.next;
        }
    }
    //成员方法2:查找某个关键字key是否在单链表中
    public boolean contains(int key){
        Node cur = head;
        while(cur!=null){
            if(cur.val == key){
                // 若为引用类型需用equals方法
                return true;
            }
            cur=cur.next;
        }
        return false;
    }
    //成员方法3:得到链表长度(时间复杂度为O(N)
    public int size(){
        int count=0;
        Node cur = head;
        while(cur!=null){
            count++;
            cur=cur.next;
        }
        return count;
    }
    //成员方法4:头插法
    public void addFirst(int data){
        Node newNode = new Node(data);
        newNode.next = head;
        head = newNode;
    }

    //成员方法5:尾插法
    public void addLast(int data){
        Node newNode = new Node(data);
        newNode.next = null;
        // 判断链表是否为空(判断是否为首次插入)
        if(head==null){
            head = newNode;
            return;
        }
        Node cur = head;
        while(cur.next!=null){
            cur=cur.next;
        }
        cur.next = newNode;
    }
    //成员方法6:任意位置插入,第一个数据节点为0号下标
    public void addIndex(int index,int data) throws ListIndexOutOfException{
        if(index == 0){   // 头插
            addFirst(data);
            return;
        }
        if(index == size()) {    // 尾插
            addLast(data);
            return;
        }
        Node cur = findIndexSubOne(index);
        Node newNode = new Node(data);
        newNode.next = cur.next;
        cur.next = newNode;
    }
    // 辅助方法:判断插入位置下标是否异常
    private void checkIndex(int index){
        if(index<0||index>size()){
            throw new ListIndexOutOfException("下表位置不合法!");
        }
    }
    // 辅助方法:查询目标下标结点的前结点
    private Node findIndexSubOne(int index){
        // 查找index-1位置的结点
        Node cur = head;
        int count=0;
        while(count!=index-1){
            cur=cur.next;
            count++;
        }
        return cur;
    }
    //成员方法7:删除第一次出现关键字为key的结点
    public void remove(int key){
        if(head==null){
            return;  // 链表为空
        }
        if(head.val == key){
            head = head.next;
            return;
        }
        Node preDel = searchPrevNode(key);
        if(preDel == null){
            return;
        }
        Node del = preDel.next;
        preDel.next = del.next;
    }
    //辅助方法:查找目标key值结点的前结点
    private Node searchPrevNode(int key){
        Node cur = head;
        while(cur.next!=null){
            if(cur.next.val == key){
                return cur;
            }
            cur=cur.next;
        }
        return null; // 没有找到待删除的结点
    }
    //成员方法8:删除所有值为key的结点
    public void removeAllKey(int key){
        if(head==null){
            return;
        }
        Node cur = head.next;
        Node prev = head;
        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;
        }
    }
    //成员方法9:清空链表
    public void clear(){
        head =null;
    }
}

(3)ListIndexOutOfException:

package TestMySingleList;

public class ListIndexOutOfException extends RuntimeException{
    public ListIndexOutOfException(){

    }
    public ListIndexOutOfException(String message){
        super(message);
    }
}

3. 单链表OJ

3.1 题目1:移除链表元素: 

题目链接: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 null;
        }
        ListNode prev = head;
        ListNode cur = prev.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;
    }
}

3.2 题目2:反转一个单链表

题目链接:206. 反转链表 - 力扣(LeetCode)

解题思路:将原列表头结点head.next置为null,依次取头结点的下一个结点对头结点进行头插;

代码:

/**
 * 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 null;
        }
        if(head.next == 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 题目3:返回链表的中间结点

题目链接:876. 链表的中间结点 - 力扣(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 middleNode(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while(fast!=null && fast.next!=null){
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow;
    }
}

注:(1)当链表结点数为奇数时,while循环截止条件是fast.next为空;当链表结点数为偶数时,while循环截止条件是fast为空;

(2)while循环的判断条件逻辑与前后条件不能顺序颠倒,因为当fast为空时,fast.next可能触发空指针异常;

3.4 题目4:链表的倒数第k个结点

题目链接:链表中倒数第k个结点_牛客题霸_牛客网

解题思路:定义快慢指针,令慢指针slow标记待找结点。

当fast指向尾结点时,倒数第k个结点即slow比fast慢k-1步;

故而,令fast走k-1步,slow开始走,两个指针开始同时前进,当fast.next为空(fast行至尾结点)时,slow所指节点就是待找结点;

代码:

import java.util.*;
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
        // 判断 k 位置是否合法
        if(k<=0 || head==null){
            return null;
        }
        ListNode fast = head;
        ListNode slow = head;
        // fast 走 k-1 步
        while(k-1!=0){
            fast=fast.next;
            if(fast==null){
                return null;
            }
            k--;
        }
        // slow 开始和 fast 一起走
        while(fast.next!=null){
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }
}

3.5 题目5:合并两个有序链表

题目链接:21. 合并两个有序链表 - 力扣(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 mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode newHead = new ListNode(0);
        ListNode tmp = newHead;
        // 两链表均有数据
        while(list1!=null && list2!=null){
            if(list1.val < list2.val){
                tmp.next = list1;
                list1 = list1.next;
                tmp = tmp.next;
            }else{
                tmp.next = list2;
                list2 = list2.next;
                tmp = tmp.next;
            }
        }
        // 链表2已经走完,直接将链表1其余部分拼接到tmp结点后即可
        if(list1 != null){
            tmp.next = list1;
        }
        // 链表1已经走完,将链表2其余部分拼接到tmp结点后
        if(list2 != null){
            tmp.next = list2;
        }
        return newHead.next;
    }
}

3.6 题目6:链表的回文结构

题目链接:链表的回文结构_牛客题霸_牛客网

解题思路:寻找链表中间结点,将链表后半部分反转。从链表首位开始依次对应判断是否相等;

代码:

import java.util.*;

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

    ListNode(int val) {
        this.val = val;
    }
}*/
public class PalindromeList {
    public boolean chkPalindrome(ListNode head) {
        if(head == null){
            return false;
        }
        if(head.next == null){
            return true;
        }
        ListNode fast = head;
        ListNode slow = head;
        // 找中间结点
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
        }
        // 翻转
        ListNode cur = slow.next;  // cur代表当前需要翻转的结点
        while(cur != null){
            ListNode curNext = cur.next;
            cur.next = slow;
            slow = cur;
            cur = curNext;
        }
        // slow从后往前, head从前往后 依次对应比较
        while(slow != head){
            if(head.val != slow.val){
                return false;
            }
            if(head.next == slow){
                return true;
            }
            slow = slow.next;
            head = head.next;
        }
        return true;
    }
}

注:在head与slow分别开始从两端对应比较时,对于结点个数为偶数个的链表,直接判断head与slow是否相遇会导致head与slow错过,需要增加一个判断:head.next是否为slow,如果是则说明是回文序列;

3.7 题目7:链表分割

题目链接:链表分割_牛客题霸_牛客网

代码:

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 bs = null;   // 前半段首结点
        ListNode be = null;   // 前半段尾结点
        ListNode as = null;   // 后半段首结点
        ListNode ae = null;   // 后半段尾结点
        ListNode cur = pHead;
        while(cur != null){
            if(cur.val < x){
                if(bs == null){
                    // 前半段首次插入
                    bs = cur;
                    be = cur;
                }else{
                    be.next = cur;
                    be = be.next;
                }
            }
            else{
                if(as == null){
                    // 后半段首次插入
                    as = cur;
                    ae = cur;
                }else{
                ae.next = cur;
                ae = ae.next;
                }
            }
            cur = cur.next;
        }
        // 可能不是同时存在小于x和大于x数据的情况
        // 前半段为空直接返回后半段
        if(bs == null){   
            return as;
        }
        // 前半段不为空,则与后半段连接即可
        be.next = as;
        // 后半段不为空时,将后半段指针域置空
        if(as != null){
           ae.next = null; 
        }
        return bs;
    }
}

3.8 题目8:相交链表

题目链接:160. 相交链表 - 力扣(LeetCode)

解题思路:定义两头结点指针,确定长短链表;

为了保证指针能同时到达两链表相交结点位置,令长链表头结点指针向前走两链表长度之差步;

令两链表头结点指针开始同步前进并对应判断是否引用相同并返回两引用任意其一即可;

代码:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public int size(ListNode head){
        int len=0;
        ListNode cur =head;
        while(cur!=null){
            len++;
            cur = cur.next;
        }
        return len;
    }
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        // 求两个链表长度并确定长短链表
        int lenA = size(headA);
        int lenB = size(headB);
        int len = lenA - lenB;
        ListNode headLong = headA;
        ListNode headShort = headB;
        if(len < 0){ // 链表B比链表A长
            headLong = headB;
            headShort = headA;
            len = lenB - lenA;
        }
        // 令长链表头结点指针走两链表之差长度的距离
        while(len != 0){
            headLong = headLong.next;
            len--;
        }
        // 两链表头结点指针开始同步前进
        while(headLong != headShort){
            headLong = headLong.next;
            headShort = headShort.next;
        }
        // 判断是否两指针走完链表都未相遇,同时等于空值而相等
        if(headLong == headShort && headLong == null){
            return null;
        }
        return headLong;
    }
}

3.9 题目9:环形链表

题目链接:141. 环形链表 - 力扣(LeetCode)

代码:

/**
 * 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) {
        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.10 题目10:环形链表Ⅱ

题目链接:142. 环形链表 II - 力扣(LeetCode)

(与上一题的区别在于,如果有环则返回链表开始入环的第一个结点)

代码:

/**
 * 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;
        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;
        }
        // 此时fast和slow在相遇点
        // 将slow置回头结点
        slow = head;
        // 令slow从头结点出发,fast从相遇点出发,二者再次相遇点即为环的入口点
        while(fast != slow){
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }
}

4. LinkedList的模拟实现

LinkedList底层就是一个双向链表;

(1)包类关系:

 

(2)MyLinkedList:

package TestMyLinkedList;

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;
    // 遍历并打印链表
    public void display(){
        ListNode cur = head;
        while(cur != null){
            System.out.print(cur.val+" ");
            cur = cur.next;
        }
        System.out.println();
    }
    // 求链表长度
    public int size(){
        ListNode cur = head;
        int len=0;
        while(cur!=null){
            cur = cur.next;
            len++;
        }
        return len;
    }
    // 查找关键字key是否包含在链表中
    public boolean contains(int key){
        ListNode cur = head;
        while(cur != null){
            if(cur.val == key){
                return true;
            }
        }
        return false;
    }
    // 尾插 O(1)
    public void addLast(int data){
        ListNode newNode = new ListNode(data);
        if(head == null){
            head = newNode;
            last = newNode;
        }else{
            last.next = newNode;
            newNode.prev = last;
            last = newNode;
        }
    }
    // 头插
    public void addFirst(int data){
        ListNode newNode = new ListNode(data);
        if(head==null){
            head = newNode;
            last = newNode;
        }else{
            newNode.next = head;
            head.prev = newNode;
            head = newNode;
        }
    }
    // 任意位置插入,第一个数据节点为0号下标
    public void addIndex(int index, int data){
        if(index<0 || index>size()){
            throw new ListIndexOutOfException();
        }
        if(index == 0){
            addFirst(data);
            return;
        }
        if(index == size()){
            addLast(data);
            return;
        }
        ListNode newNode = new ListNode(data);
        ListNode cur = findIndex(index);
        ListNode preCur = cur.prev;
        preCur.next = newNode;
        newNode.prev = preCur;
        newNode.next = cur;
        cur.prev = newNode;
    }
    // 辅助方法:查询目标下标结点
    private ListNode findIndex(int index){
        ListNode cur = head;
        while(index!=0){
            cur = cur.next;
            index--;
        }
        return cur;
    }
    // 删除第一次出现关键词key的结点
    public void remove(int key){
        if(head == null){
            return;
        }
        if(head.val == key){
            head = head.next;
            return;
        }
        if(last.val == key){
            last = last.prev;
            last.next =null;
            return;
        }
        ListNode del = findKey(key);
        ListNode preDel = del.prev;
        ListNode delNext = del.next;
        preDel.next = delNext;
        delNext.prev = preDel;
    }
    // 辅助方法:查找关键词为key的结点
    public ListNode findKey(int key){
        ListNode cur = head;
        while(cur!=null){
            if(cur.val == key){
                return cur;
            }
            cur =cur.next;
        }
        return null;
    }
    // 删除链表中所有值为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;
        }
    }
    // 清空列表
    public void clear(){
        ListNode cur = head;
        ListNode curNext = cur.next;
        while(cur!=null){
            cur.val = 0;
            cur.next = null;
            cur.prev = null;
            cur = curNext;
        }
        head = null;
        last = null;
    }
}

(3)ListIndexOtOfException:

package TestMyLinkedList;

public class ListIndexOutOfException extends RuntimeException{
    public ListIndexOutOfException(){

    }
    public ListIndexOutOfException(String message){
        super(message);
    }
}

注:其中删除所有值为key的结点方法removeAllKey也可以写为:

/ 删除链表中所有值为key的结点
    public void removeAllKey(int key){
        if(head == null){
            return;
        }
        while(head.val == key){
            head = head.next;
            if(head == null){
                return;
            }
        }
        if(last.val == key){
            last = last.prev;
            last.next = null;
            return;
        }
        ListNode cur = head;
        while(cur!=null){
            ListNode del = findKey(cur, key);
            if(del!=null) {
                ListNode preDel = del.prev;
                ListNode delNext = del.next;
                preDel.next = delNext;
                delNext.prev = preDel;
            }
            cur = cur.next;
        }
    }
    public ListNode findKey(ListNode node, int key){
        ListNode cur = node;
        while(cur != null){
            if(cur.val == key){
                return cur;
            }
            cur = cur.next;
        }
        return null;
    }

5. LinkedList的使用

Linkedlist的方法与ArrayList基本一致,此处不再详细举例,请参考ArrayList文章:

CSDN

注:(1)LinkedList使用其他集合容器构造方法含义:

(2)LinkedList的迭代器遍历法:

ListIterator<String> it =linkedList.listIterator();
        while(it.hasNext()){
            // 有下一个则打印下一个并向下走一步
            System.out.print(it.next());
        }
        ListIterator<String> it2 = linkedList.listIterator(linkedList.size());
        while(it2.hasPrevious()){
            // 有前一个则打印前一个并向前走一步
            System.out.print(it2.previous());
        }

6.LinkedList和ArrayList的区别

不同点ArrayListLinkedList
存储空间上物理上一定连续逻辑上连续,但物理上不一定联系
随机访问支持:O(1)不支持:O(N)
头插需要搬移元素,效率低:O(N)只需要修改引用的指向,时间复杂度为O(1)
插入空间不够时需要扩容没有容量的概念
应用场景元素高效存储+频繁访问任意位置插入和删除频繁

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

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

相关文章

Python连接MariaDB数据库

Python连接MariaDB数据库 一、安装mariadb库 pip install mariadb 二、连接数据库 connect()函数连接数据库。 import mariadbconn mariadb.connect(user"root", password"Root123", host"192.168.0.182", port3306, database"compan…

Linux环境搭建(XShell+云服务器)

好久不见啊&#xff0c;放假也有一周左右了&#xff0c;简单休息了下&#xff08;就是玩了几天~~&#xff09;&#xff0c;最近也是在学习Linux&#xff0c;现在正在初步的学习阶段&#xff0c;本篇将会简单的介绍一下Linux操作系统和介绍Linux环境的安装与配置&#xff0c;来帮…

【沁恒蓝牙mesh】组网方式选择与分析

本文主要介绍了【沁恒蓝牙mesh】组网方式选择与分析 1.开发环境搭建与程序烧录 参考博文&#xff1a;【经验】如何搭建沁恒蓝牙SoC CH58x开发环境 2. 组网方式 蓝牙mesh组网实践&#xff08;配网方式的选择&#xff09; 自配网&#xff1a;自己给自己配网&#xff0c;当节点…

Labview串口通信MSComm实现串口收发

文章目录 前言一、什么是 MSComm二、MSComm 控件下载三、MSComm 控件的注册四、使用 MSComm 控件1、前面板放置控件2、MSComm 的常用属性3、MSComm 控件的事件 五、实现串口收发1、搭建虚拟串口2、发送测试3、接收测试4、后面板核心程序框图 六、程序自取 前言 本文介绍使用 A…

study 第三方库

import osprint(os.listdir()) #列出当前目录下的文件 print(os.getcwd()) #获取绝对路径if not os.path.exists("b"):os.mkdir("b") if not os.path.exists("b/test.ext"):f open("b/text.txt","w")f.write("hello,f…

sql学习笔记

sql语句优先级 FROM → WHERE → GROUP BY → SELECT → HAVING → ORDER BY sql case用法 例题&#xff1a; 按照销售单价( sale_price )对练习 3.6 中的 product&#xff08;商品&#xff09;表中的商品进行如下分类。 低档商品&#xff1a;销售单价在1000日元以下&#x…

MATLAB | 产生阿尔法稳定分布噪声并作出概率密度函数

一、问题描述 想产生不同特征参数的α稳定随机变量&#xff0c;并且作出其概率密度函数进行对比。 二、解决思路 运行了MATLAB的官方实例代码&#xff1a; openExample(‘stats/ComparePDFsOfStableDistributionsExample’) &#xff08;1&#xff09;使用makedist()函数生成…

低代码未来的发展方向

大的未来都是AI &#xff0c;AI &#xff0c; AI …&#xff0c;理论上不可能有别的。 拿iVX来说吧&#xff0c;已经做了一整套完整的 可视化编程范式&#xff0c;基本可以生成所有系统的前端后台和数据库代码。也就是说&#xff0c;其组件系统和逻辑表达&#xff08;非代码&a…

整天用 Calendar 日历组件,不如自己手写一个吧!

目录 Date 的 api 实现日历组件 静态的布局 再来写逻辑 增加两个参数 提供 ref 来暴露 api 总结 日历组件想必大家都用过&#xff0c;在各个组件库里都有。比如 antd 的 Calendar 组件&#xff08;或者 DatePicker 组件&#xff09;&#xff1a; 那这种日历组件是怎么实…

【论文阅读】A Comprehensive Survey

论文来源&#xff1a;Li M , Liu Y , Liu X ,et al.The Deep Learning Compiler: A Comprehensive Survey[J]. 2020.DOI:10.1109/TPDS.2020.3030548. 这是一篇关于深度学习编译器的综述类文章。 什么是深度学习编译器 深度学习&#xff08;Deep Learning&#xff09;编译器将…

STM32H5开发(4)----开发板介绍

STM32H5开发----4.开发板介绍 套件概述样品申请特征系统控制和生态系统访问功能示意图系统框图跳线设置开发板原理图 套件概述 STM32H503RBTx_LQFP64是STM32H5系列微控制器的一款出色评估套件&#xff0c;它采用了先进的40nm工艺制造&#xff0c;为开发者提供了卓越的性能和能…

MyBatis基础模块-类型转换模块

文章目录 1. 为什么需要类型转换模块2. TypeHandler 1. 为什么需要类型转换模块 执行sql&#xff0c;在PreparedStatement设置参数时&#xff0c;需要把java类型转换成jdbc类型&#xff0c;而从结果集中获取数据时&#xff0c;需要把jdbc类型转换为java类型。 2. TypeHandle…

软件测试未来的发展趋势以及软件测试进阶路线

全球各地的企业每天都在发展变化着&#xff0c;以应对市场挑战&#xff0c;满足日益成熟的客户需求。即使是正在进行的技术进步也会使软件测试专家在实践的过程中更加专注和精确。 2021年给软件测试领域带来了新的技术解决方案&#xff0c;以及质量保证和软件测试的实现。与此同…

【数据结构和算法14】堆结构(基于数组实现)

目录 1、有关二叉树和堆的介绍 2、大根堆的代码实现 3、小根堆的代码实现 1、有关二叉树和堆的介绍 计算机科学中&#xff0c;堆是一种基于树的数据结构&#xff0c;通常用完全二叉树实现。堆的特性如下 在大顶堆&#xff08;大根堆&#xff09;中&#xff0c;任意节点 C 与…

开源视频监控管理平台国标GB28181视频EasyCVR电子地图功能展示优化

视频监控综合管理平台EasyCVR可提供的视频能力包括&#xff1a;视频监控直播、云端录像、云存储、录像检索与回看、告警上报、平台级联、云台控制、语音对讲、电子地图、H.265自动转码等&#xff0c;也具备接入AI智能分析的能力。 视频汇聚平台EasyCVR可拓展性强、视频能力灵活…

centos7中用shell脚本实现mysql分库分表备份

环境&#xff1a; 脚本&#xff1a; #!/bash/bin back_path/backup/db databases_file/backup/databases.list [ -f $databases_file ] || touch /backup/databases.list if [[ ! -s ${databases_file} ]] thenecho "$databases_file为空,请在该文件中写上需要备份的数据…

C# Modbus TCP上位机测试

前面说了三菱和西门子PLC的上位机通信&#xff0c;实际在生产应用中&#xff0c;设备会有很多不同的厂家生产的PLC&#xff0c;那么&#xff0c;我们就需要一种通用的语言&#xff0c;进行设备之间的通信&#xff0c;工业上较为广泛使用的语言之一就是Modbus。 Modbus有多种连…

filscan api 获取错误扇区个数

获取错误扇区个数 POST 请求 curl -s -X POST -H "Content-Type: application/json" -d {"account_id": "f01889512"} https://api-v2.filscan.io/api/v1/AccountInfoByID | jq -r .result.account_info.account_miner.account_indicator.fault…

JMM内存模型深入详解,探索volatile、synchronized与VarHandle深层次的奥秘

文章目录 一、JMM内存模型1、什么是JMM&#xff08;1&#xff09;参考资料 2、竞态条件&#xff08;Race Condition&#xff09;&#xff08;1&#xff09;实例 3、同步动作&#xff08;Synchronization Order&#xff09;&#xff08;1&#xff09;实例&#xff08;2&#xff…

fSGAT批量候选基因关联分析丨快速单基因关联分析

候选基因如何分析&#xff1f; 通常情况下关联分析会得到一大堆候选基因&#xff0c;总不可能每个都有用&#xff0c;因此需要对候选基因进行深一步分析&#xff0c;本篇笔记分享一下群体遗传学研究中GWAS候选位点与候选基因的筛选思路。主要的方式包括单基因关联分析、连锁程度…