高频面试手撕

在这里插入图片描述

手撕高频结构

前言,以下内容,都是博主在秋招面试中,遇到的面试手撕代码题目,包含常见的数据结构、多线程以及数据库连接池等。

ArrayList

  • 实现了ArrayList的基本功能,包括随机访问自动扩容

  • 添加元素时,如果数组容量不足,会自动扩容,避免频繁的手动扩展操作。

  • 能够处理常见的越界检查、扩容和元素添加。

public class MyArrayList<T> {private T[] elements; // 用于存储元素的数组private int size;     // 当前ArrayList中实际元素的个数// 默认初始容量private static final int DEFAULT_CAPACITY = 10;// 无参构造函数,使用默认初始容量public MyArrayList() {elements = (T[]) new Object[DEFAULT_CAPACITY];size = 0;}// 带初始容量的构造函数public MyArrayList(int initialCapacity) {if (initialCapacity <= 0) {throw new IllegalArgumentException("初始容量必须大于0");}elements = (T[]) new Object[initialCapacity];size = 0;}// 添加元素方法(自动扩容)public void add(T element) {ensureCapacity(); // 检查是否需要扩容elements[size++] = element; // 将元素添加到数组中,并更新size}// 获取元素方法,根据索引随机访问元素public T get(int index) {checkIndex(index); // 检查索引是否越界return elements[index];}// 返回当前ArrayList的大小public int size() {return size;}// 扩容方法,将数组容量增加1.5倍private void ensureCapacity() {if (size == elements.length) {int newCapacity = elements.length * 1.5;elements = Arrays.copyOf(elements, newCapacity); // 扩容}}// 检查索引是否越界的方法private void checkIndex(int index) {if (index < 0 || index >= size) {throw new IndexOutOfBoundsException("索引超出范围: " + index);}}// 重写toString方法,方便输出查看@Overridepublic String toString() {return Arrays.toString(Arrays.copyOf(elements, size));}// 测试MyArrayList的功能public static void main(String[] args) {MyArrayList<Integer> list = new MyArrayList<>();// 添加元素list.add(10);list.add(20);list.add(30);list.add(40);// 打印列表System.out.println("ArrayList内容: " + list);// 随机访问元素System.out.println("索引1的元素: " + list.get(1));// 添加更多元素,测试扩容for (int i = 0; i < 10; i++) {list.add(i * 10);}// 打印扩容后的列表System.out.println("扩容后的ArrayList内容: " + list);System.out.println("ArrayList大小: " + list.size());}
}

LinkedList

底层是链表

public class MyLinkedList {// 链表节点类static class Node {int data;  // 节点的数据Node next; // 指向下一个节点的指针// 构造函数public Node(int data) {this.data = data;this.next = null;}}private Node head; // 链表的头节点// 构造函数,初始化空链表public MyLinkedList() {this.head = null;}// 1. 在链表的头部插入节点public void addFirst(int data) {Node newNode = new Node(data);newNode.next = head; // 新节点指向当前头节点head = newNode;      // 头节点更新为新节点}// 2. 在链表的尾部插入节点public void addLast(int data) {Node newNode = new Node(data);if (head == null) {head = newNode; // 如果链表为空,则新节点为头节点} else {Node cur = head;while (cur.next != null) {cur = cur.next; // 找到最后一个节点}cur.next = newNode; // 将新节点插入到最后}}// 3. 查找链表中是否存在某个数据public boolean contains(int key) {Node cur = head;while (cur != null) {if (cur.data == key) {return true; // 找到返回 true}cur = cur.next;}return false; // 未找到返回 false}// 4. 删除链表中首次出现的指定数据public void remove(int key) {if (head == null) {return; // 链表为空,直接返回}// 如果删除的是头节点if (head.data == key) {head = head.next; // 头节点指向下一个节点return;}// 遍历链表,找到要删除的节点Node prev = null;Node cur = head;while (cur != null && cur.data != key) {prev = cur;cur = cur.next;}// 如果找到要删除的节点if (cur != null) {prev.next = cur.next; // 前一个节点的 next 指向当前节点的下一个节点}}// 5. 获取链表的长度public int size() {int count = 0;Node cur = head;while (cur != null) {count++;cur = cur.next;}return count;}// 6. 打印链表public void printList() {Node cur = head;while (cur != null) {System.out.print(cur.data + " -> ");cur = cur.next;}System.out.println("null");}// 7. 清空链表public void clear() {head = null;}// 测试代码public static void main(String[] args) {MyLinkedList list = new MyLinkedList();list.addFirst(1);list.addFirst(2);list.addLast(3);list.addLast(4);list.printList();   // 打印链表: 2 -> 1 -> 3 -> 4 -> nullSystem.out.println("List size: " + list.size());  // 输出链表长度: 4System.out.println("Contains 3? " + list.contains(3));  // 输出 trueSystem.out.println("Contains 5? " + list.contains(5));  // 输出 falselist.remove(1); // 删除 1list.printList();   // 打印链表: 2 -> 3 -> 4 -> nulllist.clear();  // 清空链表list.printList();   // 打印链表: null}
}

Stack栈

先进后出

public class MyStack {public int[] elem;public int usedSize;public static final int DEFAULT_CAPACITY=10;public MyStack() {elem=new int[DEFAULT_CAPACITY];}/*** 入栈* @param val*/public void push(int val) {//先判断栈是否满了if(isFull()) {elem= Arrays.copyOf(elem,2*elem.length);}elem[usedSize++]=val;}/*** 判断当前栈是否满了* @return*/public boolean isFull() {if(usedSize==elem.length) {return true;}return false;}/*** 删除栈顶元素*/public int pop() {if(isEmpty()) {throw new RuntimeException("栈空了");}int val= elem[usedSize-1];usedSize--;return val;}/*** 是否为空* @return*/public boolean isEmpty() {return usedSize==0;}/*** 获取栈顶元素但不删除* @return*/public int peek() {if(isEmpty()) {throw new RuntimeException("栈为空了!");}return elem[usedSize-1];}
}

Queue队列

先进先出

public class MyQueue {static class Node {public int val;public Node next;public Node(int val) {this.val = val;}}public Node head;//队列的头public Node tail;//队列的尾/*** 入队操作* @param val*/public void offer(int val) {Node node=new Node(val);if(head==null) {head=node;tail=node;}else {tail.next=node;tail=tail.next;}}/*** 出队操作*/public int poll() {if(head==null)throw new RuntimeException("队列为空!");int val= head.val;;if(head.next==null)head=tail=null;elsehead=head.next;return val;}/*** 查看队头元素*/public int peek() {if(head==null) {throw new RuntimeException("队列为空!");}return head.val;}
}

优先级队列(大根堆)

队列是一种先入先出的数据结构,但是如果队列中的元素带有优先级,就可能需要让优先级高的元素先出队列

这种情况下就有了优先级队列这种数据结构,这种结构提供了两个基本操作,一是返回最高优先级对象,二是添加新的对象

PriorityQueue的底层使用了的数据结构,堆其实就是一棵完全二叉树,若该完全二叉树的每棵子树都是根结点最大,叫做大根堆(否则叫小根堆)

public class Heap {public int[] elem;public int usedSize;// 当前堆中有效元素个数public Heap() {this.elem=new int[10];}public void initArray(int[] array) {elem= Arrays.copyOf(array,array.length);usedSize=elem.length;}/*** 建堆* 时间复杂度:O(n)*/public void createHeap() {for (int parent = (usedSize-1-1)/2; parent >=0 ; parent--) {shiftDown(parent,usedSize);// usedSize保证所有子树的下标都不会比它大,可比较用于所有子树的结束}}/*** 向下调整 让每棵子树都成为大根堆* @param parent  每棵子树的根结点下标* @param len  所有子树的结束位置(usedSize)*/private void shiftDown(int parent,int len) {int child=2*parent+1;while (child<len) {// 存在右孩子的情况下,比较左右孩子的大小,child记录较大值的下标if(child+1<len&&elem[child]<elem[child+1]) {child++;}// 此时child记录的是孩子中的较大值,再去与父节点进行比较if(elem[child]>elem[parent]) {swap(elem,child,parent);// 向下调整,让parent到child的位置,继续往下做比较parent=child;child=2*parent+1;}else {// 如果走到else,说明此时该子树符合大根堆结构,不需要再做向下调整,直接跳出循环即可break;}}}private void swap(int[] array,int i,int j) {int tmp=array[i];array[i]=array[j];array[j]=tmp;}/*** 入队(插入元素)* 【插入末尾位置,然后向上调整结构】* @param x*/public void offer(int x) {if(isFull()) {elem=Arrays.copyOf(elem,elem.length*2);}this.elem[usedSize]=x;shiftUp(usedSize);usedSize++;}private boolean isFull() {return usedSize== elem.length;}/*** 向上调整* @param child 子节点下标*/private void shiftUp(int child) {// 找到其父节点int parent=(child-1)/2;// 向上调整一直到根节点结束while (child>0) {// 判断子节点与父节点大小if(elem[child]>elem[parent]) {swap(elem,child,parent);child=parent;parent=(child-1)/2;}else {// 若不需要调整,则直接跳出循环break;}}}/*** 出队(删除元素)* 【交换堆顶与队尾元素,删除队尾元素,再让堆顶做向下调整】* @return*/public int poll() {if(isEmpty()) {return -1;}int old=elem[0];// 交换堆顶与堆尾元素swap(elem,0,usedSize-1);// 删除堆尾元素usedSize--;// 将堆顶元素向下调整shiftDown(0,usedSize);return old;}/*** 返回堆顶最大元素* @return*/public int peek() {if(isEmpty()) {return -1;}int val=elem[0];return val;}public boolean isEmpty() {return usedSize==0;}/*** 堆排序* 1、将堆顶元素【最大值】放到末尾,剩余部分做向下调整* 2、持续遍历所有操作,完成堆排序,大顶堆通过堆排序后得到升序数组* 时间复杂度 O(n logn) ;* 空间复杂度 O(1)*/public void heapSort() {int end=usedSize-1;while (end>0) {swap(elem,0,end);shiftDown(0,end);end--;}}public static void main(String[] args) {Heap heap=new Heap();// 初始化数组并创建堆int[] array={10,20,15,30,40,25,50};System.out.println("初始化堆");heap.initArray(array); // 初始化数据heap.createHeap();  // 建堆System.out.println("初始最大堆:"+Arrays.toString(Arrays.copyOfRange(heap.elem,0,heap.usedSize)));heap.offer(35);System.out.println("插入后最大堆:"+Arrays.toString(Arrays.copyOfRange(heap.elem,0,heap.usedSize)));heap.poll();System.out.println("弹出最大元素后最大堆:"+Arrays.toString(Arrays.copyOfRange(heap.elem,0,heap.usedSize)));heap.heapSort();System.out.println("堆排序结果:"+Arrays.toString(Arrays.copyOfRange(heap.elem,0,heap.usedSize)));}
}
//
初始化堆
初始最大堆:[50, 40, 25, 30, 20, 10, 15]
插入后最大堆:[50, 40, 25, 35, 20, 10, 15, 30]
弹出最大元素后最大堆:[40, 35, 25, 30, 20, 10, 15]
堆排序结果:[10, 15, 20, 25, 30, 35, 40]Process finished with exit code 0

HashMap

用拉链法解决冲突,实现了常见的方法

public class MyQueue {static class Node {public int val;public Node next;public Node(int val) {this.val = val;}}public Node head;//队列的头public Node tail;//队列的尾/*** 入队操作* @param val*/public void offer(int val) {Node node=new Node(val);if(head==null) {head=node;tail=node;}else {tail.next=node;tail=tail.next;}}/*** 出队操作*/public int poll() {if(head==null)throw new RuntimeException("队列为空!");int val= head.val;;if(head.next==null)head=tail=null;elsehead=head.next;return val;}/*** 查看队头元素*/public int peek() {if(head==null) {throw new RuntimeException("队列为空!");}return head.val;}
}

生产者消费者模型

生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取。

该模型有以下两个用途:
1)削峰填谷
阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。

三峡大坝,汛期控制水量,防止水灾;旱期释放积攒的水,防止旱灾。

2)解耦合
阻塞队列也能使生产者和消费者之间解耦(减少两者之间的关联关系)

过年一家子一起包饺子,一般有明确的分工,一个人负责擀饺子皮,其他人负责包,擀饺子皮的人就是“生产者”,包饺子的人就是“消费者”,擀饺子皮的人不关心包饺子的人是谁,包饺子的人也不关心擀饺子皮的人是谁。

代码关键点总结

  • 生产者-消费者模型:生产者生成数据并放入队列,消费者从队列中取数据进行处理。BlockingQueue自动处理了队列为空或满时的阻塞问题,简化了多线程编程中的同步控制。
  • 线程安全LinkedBlockingQueue是线程安全的,它内部使用了锁机制来保证线程之间对队列的安全访问。
  • 无限循环的消费者线程:消费者线程在while(true)中不断取数据,因此只要有生产者继续生产,消费者就会不断消费。
  • Thread.sleep(1000)模拟生产过程的延迟:生产者每次生产一个元素后会等待1秒,模拟一个耗时的生产过程。
public static void main(String[] args) {BlockingQueue<Integer> queue=new LinkedBlockingQueue<>();Thread consumer=new Thread() {@Overridepublic void run() {while (true) {try {Integer value=queue.take();System.out.println("消费元素:"+value);} catch (InterruptedException e) {e.printStackTrace();}}}};consumer.start();Thread producer=new Thread() {@Overridepublic void run() {for (int i = 0; i < 10000; i++) {System.out.println("生产了元素:"+i);try {queue.put(i);Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}};producer.start();try {consumer.join(); // join()方法的作用是等待线程终止producer.join(); // 由于消费者线程是一个无限循环,实际运行中,主线程将会永远阻塞在consumer.join()上。} catch (InterruptedException e) {e.printStackTrace();}
}

BlockingQueue

阻塞队列是一种特殊的队列. 也遵守 “先进先出” 的原则.

阻塞队列是一种线程安全的数据结构, 并且具有以下特性:

当队列满的时候, 继续入队列就会阻塞, 直到有其他线程从队列中取走元素.
当队列空的时候, 继续出队列也会阻塞, 直到有其他线程往队列中插入元素.

public class Main {static class BlockingQueue {//1000就相当于队列的最大容量,此处暂不考虑扩容问题private int[] items=new int[1000];private volatile int head=0;private volatile int tail=0;private volatile int size=0;private Object locker=new Object();//put用来入队列public void put(int item) throws InterruptedException {//因为队列中涉及修改操作,所以通过加锁来解决线程不安全问题(原子性)。synchronized (locker) {//使用while就是为了让wait被唤醒之后,再次确认条件是否成立while (size==items.length) {//队列已经满了,对于阻塞队列来说就要阻塞locker.wait();}items[tail]=item;tail++;//如果到达末尾,就回到起始位置if(tail>=items.length) {tail=0;}size++;locker.notify();}}public int take() throws InterruptedException {int ret=0;synchronized (locker) {while (size==0) {//对于阻塞队列来说,如果队列为空,在尝试获取元素,就要阻塞locker.wait();}ret=items[head];head++;if(head>=items.length) {head=0;}size--;//此处的notify用来唤醒put中的waitlocker.notify();}return ret;}}public static void main(String[] args) throws InterruptedException {BlockingQueue queue=new BlockingQueue();//消费者模型Thread consumer=new Thread() {@Overridepublic void run() {while (true) {try {int elem= queue.take();System.out.println("消费者元素:"+elem);} catch (InterruptedException e) {e.printStackTrace();}}}};consumer.start();//生产者线程Thread producer=new Thread() {@Overridepublic void run() {for (int i = 0; i < 10000; i++) {System.out.println("生产元素:"+i);try {queue.put(i);Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}};producer.start();consumer.join();producer.join();}
}

多线程顺序打印ABC

  • 锁与条件变量:我们使用一个 lock 对象来保证线程间的同步,所有线程共享这个锁。

  • 状态控制:通过一个 state 变量控制当前该哪个线程执行。state 的取值为 012,分别代表线程A、B、C。

  • 同步块与等待机制

    • 使用 synchronized 来保证同一时间只有一个线程能访问共享资源。

    • 使用 wait()notifyAll() 来使得线程在不符合条件时等待,并在条件满足时通知其他线程。

  • 执行结果:

每次运行该程序,三个线程会顺序打印 "ABCABCABC...",直到打印10次结束。

public class PrintABC {private static final Object lock = new Object();private static int state = 0;  // 0: A, 1: B, 2: Cpublic static void main(String[] args) {Thread threadA = new Thread(new PrintTask("A", 0));Thread threadB = new Thread(new PrintTask("B", 1));Thread threadC = new Thread(new PrintTask("C", 2));threadA.start();threadB.start();threadC.start();}static class PrintTask implements Runnable {private String name;private int flag; // 用于标识当前线程的顺序public PrintTask(String name, int flag) {this.name = name;this.flag = flag;}@Overridepublic void run() {try {for (int i = 0; i < 10; i++) {  // 打印10次ABCsynchronized (lock) {while (state != flag) {lock.wait();  // 如果不是当前线程的轮次,则等待}System.out.print(name);  // 打印当前线程对应的字符state = (state + 1) % 3;  // 更新状态,确保下一个线程打印lock.notifyAll();  // 唤醒其他线程}}} catch (InterruptedException e) {e.printStackTrace();}}}
}

线程池

步骤:

  • 使用一个BlockingQueue组织所有任务
  • 核心操作为submit,将任务加入线程池阻塞队列中,并创建线程
  • 一个线程池可用同时提交N个任务,对应线程池中有M个线程来负责完成这N个任务,利用生产者消费者模型,把N个任务分配给M个线程
public class MyThreadPool {private BlockingQueue<Runnable> queue=new LinkedBlockingQueue<>();public MyThreadPool(int m) {// 在构造方法中,创建出m个线程,负责完成工作for (int i = 0; i < m; i++) {Thread t=new Thread(()->{while (true) {try {Runnable runnable=queue.take();runnable.run();} catch (InterruptedException e) {e.printStackTrace();}}});t.start();}}// 将任务加入线程池阻塞队列中public void submit(Runnable runnable) throws InterruptedException {queue.put(runnable);}public static void main(String[] args) throws InterruptedException {MyThreadPool pool=new MyThreadPool(10);for (int i = 0; i < 1000; i++) {int taskId=i;pool.submit(new Runnable() {@Overridepublic void run() {System.out.println("执行当前任务:"+taskId+"当前线程:"+Thread.currentThread().getName());}});}}
}

数据库连接池

步骤:

1、创建固定数量的数据库连接并保存到一个集合中

2、提供getConnection()方法从池中获取连接

3、提供releaseConnection()方法将使用完的连接返回到池中

4、实现线程安全的连接获取和释放

public class ConnectionPool {private List<Connection> connectionPool;private int poolSize=10; // 池中连接数量private String url="jdbc:mysql://localhost:3306/test"; // 数据库URLprivate String username="root"; // 数据库用户名private String password="password"; // 数据库密码// 构造函数,初始化连接池public ConnectionPool() {connectionPool=new ArrayList<>();try {// 加载数据库驱动Class.forName("com.mysql.cj.jdbc.Driver");// 初始连接池for (int i = 0; i < poolSize; i++) {connectionPool.add(DriverManager.getConnection(url,username,password));}} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();}}// 从池中获取连接public synchronized Connection getConnection() {// 如果池中有可用连接,返回第一个连接if(!connectionPool.isEmpty()) {return connectionPool.remove(0);}else {// 如果池中没有可用连接,返回 null或抛出异常System.out.println("连接池已用完,无法提供连接");return null;}}// 释放连接,将连接返回到池中public synchronized void releaseConnection(Connection connection) {if(connection!=null) {connectionPool.add(connection); // 归还连接到池中}}// 关闭连接池中的所有连接public synchronized void closeAllConnections() {for (Connection connection:connectionPool) {try {connection.close();}catch (SQLException e) {e.printStackTrace();}}}// 获取连接池的当前大小public int getCurrentPoolSize() {return connectionPool.size();}public static void main(String[] args) {ConnectionPool pool=new ConnectionPool();// 获取一个连接Connection  connection=pool.getConnection();// 假设进行了一些数据库操作// 使用完后将连接返回到池中pool.releaseConnection(connection);// 打印连接池剩余连接数System.out.println("当前连接池大小:"+pool.getCurrentPoolSize());// 关闭连接池pool.closeAllConnections();}
}

改进空间:

  1. 连接池动态扩展:目前连接池的大小是固定的,实际生产环境中可以根据需求动态扩展或缩减连接池的大小。
  2. 连接池维护:可以添加心跳检测,自动关闭不可用的连接并替换。
  3. 最大等待时间:如果连接池耗尽,可以设置最大等待时间,并且在超时后抛出异常。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

施磊C++ | 进阶学习笔记 | 1.对象的应用优化、右值引用的优化

一.对象的应用优化、右值引用的优化 文章目录 一.对象的应用优化、右值引用的优化1.1 构造&#xff0c;拷贝&#xff0c;赋值&#xff0c;析构中的优化课后练习&#xff1a; 1.2 函数调用过程中对象背后调用的方法1.3 对象优化三原则1.4 右值引用、move移动语意、完美转发 1.1 …

ThingsBoard规则链节点:Clear Alarm节点详解

引言 Clear Alarm 节点含义 使用场景 实际项目中的运用场景 智能建筑管理系统 工业生产线监控 远程医疗监护 结论 引言 ThingsBoard 是一个开源的物联网平台&#xff0c;它提供了设备管理、数据收集、处理和可视化等功能。在 ThingsBoard 中&#xff0c;规则链&#xff…

QExcel 保存数据 (QtXlsxWriter库 编译)

QtXlsxWriter 是一个用于在 Qt 应用程序中创建和操作 Excel XLSX 文件的库。它提供了一个简单的 API&#xff0c;使开发者能够轻松地生成和修改 Excel 文件&#xff0c;而无需依赖 Microsoft Excel 或其他外部应用程序。支持初始化、写文件、读文件、格式设置、合并单元格、加粗…

scala 高阶函数 (下)

一.fold fold的作用 idea实例 二.sorted函数 sort基础知识 idea实例 三.sortWith sortWith基础知识 idea实例

音乐播放器项目专栏介绍​

1.简介 本专栏使用Qt QWidget作为显示界面&#xff0c;你将会学习到以下内容&#xff1a; 1.大量ui美化的实例。 2.各种复杂ui布局。 3.常见显示效果实现。 4.大量QSS实例。 5.Qt音频播放&#xff0c;音乐歌词文件加载&#xff0c;展示。 6.播放器界面换肤。 相信学习了本专栏…

Java学习-JUC

目录 1. 简介 2. Atomic包 2.1 什么是原子类 2.2 Atomic包里的类 3. CAS 3.1 CAS是什么 3.2 Java中对CAS的实现 3.3 CAS的缺陷 4. JUC里面的常见锁 4.1 锁分类 4.1.1 按上锁方式划分 4.1.2 按特性划分 4.1.3 其他锁 4.2 Synchronized和JUC的锁对比 5. 锁原理分析…

智慧园区能带来哪些便利?

所谓智慧园区&#xff0c;是指通过信息化手段&#xff0c;实现园区内各项业务的数字化和智能化管理。园区管理者可以利用智能化平台实时监控各项运营情况&#xff0c;如能源使用、安全监控和物流运输等&#xff0c;及时调整管理策略&#xff0c;提高运营效率。智慧园区利用大数…

pycharm 找不到conda环境

参考&#xff1a;新版Pycharm解决Conda executable is not found-CSDN博客

WNMP环境本地搭建并配置公网地址远程搭建动态网站或服务器

文章目录 前言1.Wnmp下载安装2.Wnmp设置3.安装cpolar内网穿透3.1 注册账号3.2 下载cpolar客户端3.3 登录cpolar web ui管理界面3.4 创建公网地址 4.固定公网地址访问 前言 本教程主要介绍如何在Windows系统电脑本地下载安装 Wnmp&#xff0c;以及结合cpolar内网穿透工具一键配…

【C++】——多态(上)

【C】——多态&#xff08;上&#xff09; 1 多态的概念2 多态的定义及实现2.1 多态的构成条件2.1.1 实现多态的必要条件2.1.2 虚函数2.1.3 感受多态2.1.4 判断是否满足多态2.1.5 多态场景的一道选择题2.1.6 虚函数重写的一些其他问题2.1.6.1 协变2.1.6.2 析构函数的重写 2.1.7…

深度学习-26-基于PyTorch的多层感知机DNN

文章目录 1 代码分析1.1 加载数据集1.2 定义模型1.3 定义损失函数和优化器1.4 定义训练函数1.4.1 定义累加器Accumulator1.4.2 计算准确率accuracy1.4.3 评估函数evaluate_accuracy1.4.4 单轮训练函数train_epoch1.4.5 训练函数train1.2 执行训练2 整体代码3 参考附录1 代码分析…

使用Python构建一个高级计算器

使用Python构建一个高级计算器 在现代编程中&#xff0c;构建一个功能强大的计算器不仅是学习编程的好项目&#xff0c;还有助于提高对数据处理和用户交互的理解。本文将带您通过使用Python构建一个高级计算器&#xff0c;该计算器支持基本运算、科学运算以及简单的图形用户界…

将SpringBoot项目部署到linux服务器使得本地可以访问

首先我们要先从本地打包jar文件上传到linux中&#xff0c;这些的步骤可以参考其他打包上传的博客哈 打包上传后&#xff0c;可以看到对应的 .jar 文件 如果这样直接运行java -jar code-sandbox-0.0.1-SNAPSHOT.jar 是不行的&#xff0c;因为你还没有在服务器上开放端口&#x…

ubuntu中使用cmake编译报错No CMAKE_CXX_COMPILER could be found.的解决方法

ubuntu中使用cmake编译报错No CMAKE_CXX_COMPILER could be found.的解决方法 No CMAKE_CXX_COMPILER could be found.Could NOT find CUDA (missing: CUDA_NVCC_EXECUTABLE CUDA_CUDART_LIBRARY)Could not find a package configuration file provided by "OpenCV" …

中国制造业精益生产管理的现状与挑战

在当今全球制造业竞争日益激烈的背景下&#xff0c;精益生产管理作为一种高效、灵活的生产模式&#xff0c;已成为众多企业追求的核心竞争力之一。然而&#xff0c;尽管精益生产理念在中国制造业中已得到广泛传播和应用&#xff0c;其实践水平却参差不齐&#xff0c;多数企业仍…

Ansible概述

目录 一、ansible简介 二、absible的特点 三、ansible的工作原理以及流程 四、ansible环境安装部署 五、ansible命令行模块 六、inventory 主机清单 一、ansible简介 Ansible是一个基于Python开发的配置管理和应用部署工具&#xff0c;现在也在自动化管理领域大放异彩。…

解决ultralytics中的YOLOv8在执行task.py文件添加模块操作出现的KeyError报错

报错详情&#xff1a; 在ultralytics项目文件夹内运行/home/xxx/ultralytics/train.py进行单GPU训练的时候训练可以正常进行 from ultralytics import YOLO# Load a model model YOLO("/home/xxx/ultralytics/ultralytics/cfg/models/v8/yolov8s-FASFF.yaml") # …

3.C++经典实例-计算一个数的阶乘

阶乘&#xff08;factorial&#xff09;是‌基斯顿卡曼于1808年发明的运算符号&#xff0c;用于表示一个正整数n的所有小于及等于该数的正整数的积。自然数n的阶乘写作n!。例如&#xff0c;5的阶乘表示为5! 1 2 3 4 5 120。 阶乘在数学和计算机科学中有广泛的应用。例如…

git--git reset

HEAD 单独一个HEAD eg:git diff HEAD 表示当前结点。 HEAD~ HEAD~只处理当前分支。 注意&#xff1a;master分支的上一个结点是tmp分支的所在的结点fc11b74, 79f109e才是master的第二个父节点。 HEAD~ 当前结点的父节点。 HEAD~1 当前结点的父节点。 HEAD~n 当前结点索…

react+video:限制快进、倍速、画中画

实现代码&#xff1a; <video ref{videoRef} src{videoUrl} className{style.video} controls onRateChange{rateChange} onPlay{playVideo} onPause{pauseVideo} onTimeUpdate{timeUpdate} disablePictureInPicture playsInline poster{poster} controlsList"nodownl…