数据结构(Java)实现:栈和队列

news2025/1/16 13:46:11

文章目录

  • 1. 栈的模拟实现
    • 1.1 普通栈的模拟实现
    • 1.2 泛型栈的模拟实现
  • 2. 栈的介绍
  • 3. 栈的使用
  • 4. 栈的应用场景
    • 4.1 改变元素的序列
    • 4.2 将递归转换为循环
    • 4.3 使用栈解题
  • 5. 栈的链表实现
  • 6. 队列概念
  • 7. 队列的使用
  • 8. 模拟队列的实现
    • 8.1 链式队列
    • 8.2 顺序队列
  • 9. 双端队列

1. 栈的模拟实现

在这里插入图片描述
从上图中可以看到,Stack继承了Vector,Vector和ArrayList类似,都是动态的顺序表,不同的是Vector是线程安全的。

1.1 普通栈的模拟实现

在这里插入图片描述
栈的模拟实现没有顺序表和链表难,实现代码和对应的注释如下。

public class MyStack {
    int[] elem;
    int usedSize=0;
    public MyStack(){
        elem=new int[10];
    }
    //入栈
    public void push(int e){
    	//判满,如果满了扩容
        if(isFull()){
            elem= Arrays.copyOf(elem,elem.length*2);
        }
        //入栈
        elem[usedSize]=e;
        usedSize++;
    }
    //判满
    public boolean isFull(){
        return usedSize==elem.length;
    }
    //出栈
    public int pop(){
    	//判空,如果为空返回-1
        if(empty()){
            return -1;
        }
        //出栈后元素个数减一
        usedSize--;
        return elem[usedSize];
    }
    //查看
    public int peek(){
    	//判空,如果为空返回-1
        if(empty()){
            return -1;
        }
        //peek只返回,不删除
        return elem[usedSize-1];
    }
    //判空
    public boolean empty(){
        return usedSize==0;
    }
}

测试代码

    public static void main(String[] args) {
        MyStack s=new MyStack();
        s.push(1);
        s.push(2);
        s.push(3);

        System.out.println(s.pop());
        System.out.println(s.peek());
        System.out.println(s.peek());
    }

1.2 泛型栈的模拟实现

要使栈变成泛型,仅需改变数据类型。

public class MyStack2 <E>{
    public Object[] elem;//泛型的本质是Object类
    public int usedSize = 0;
    public MyStack2(){
        elem=new Object[10];
    }
    public void push(E e){
        if(isFull()){
            elem= Arrays.copyOf(elem,elem.length*2);
        }
        elem[usedSize]=e;
        usedSize++;
    }
    public boolean isFull(){
        return usedSize==elem.length;
    }
    //出栈
    public E pop(){//返回类型为E
        if(empty()){
            return null;
        }
        usedSize--;
        return (E)elem[usedSize];//类型转换
    }
    public E peek(){//返回类型为E
        if(empty()){
            return null;
        }
        return (E)elem[usedSize-1];//类型转换
    }
    public boolean empty(){
        return usedSize==0;
    }
}

测试代码

    public static void main(String[] args) {
        MyStack2<String > s = new MyStack2<>();
        s.push("hello");
        s.push("zzuli");
        s.push("welcome");
        s.push("to");
        s.push("zzuli");

        System.out.println(s.pop());
        System.out.println(s.pop());
        System.out.println(s.peek());
        System.out.println(s.peek());
    }

2. 栈的介绍

:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶
出栈:栈的删除操作叫做出栈。出数据在栈顶
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. 栈的使用

在这里插入图片描述

    public static void main(String[] args) {
        Stack<Integer> s=new Stack<>();
        s.push(1);//入栈
        s.push(2);//入栈
        s.push(3);//入栈
        s.push(4);//入栈
        s.push(5);//入栈

        System.out.println(s.size());//栈的数据个数
        System.out.println(s.pop());//出栈
        System.out.println(s.pop());//出栈
        System.out.println(s.peek());//查看栈顶元素
        System.out.println(s.peek());//查看栈顶元素

        if(s.empty()){//判空
            System.out.println("栈空");
        }else{
            System.out.println("栈不为空");
        }
    }

4. 栈的应用场景

4.1 改变元素的序列

在这里插入图片描述
答案:C、B

4.2 将递归转换为循环

当我们逆序打印单向链表时,可以通过递归的方式打印。

// 递归方式
void printList(Node head){//传入链表的头结点
    if(null != head){
        printList(head.next);//递归
        System.out.print(head.val + " ");
    }
}

我们也可以利用栈的方式,将链表的节点入栈,然后出栈。就可以实现逆序打印。

    void printList(Node head){
        if(null == head){
            return;
        }
        Stack<Node> s = new Stack<>();
        // 将链表中的结点保存在栈中
        Node cur = head;
        while(null != cur){
            s.push(cur);
            cur = cur.next;
        }
        // 将栈中的元素出栈
        while(!s.empty()){
            System.out.print(s.pop().val + " ");
        }
    }

4.3 使用栈解题

  1. 括号匹配
  2. 逆波兰表达式求值
  3. 出栈入栈次序匹配
  4. 最小栈

上面四题题解链接

5. 栈的链表实现

Java集合类的Stack底层是一个数组。这种栈叫做顺序栈。那么是否可以使用链表来实现栈呢?
在这里插入图片描述
如果那单链表来实现栈,最好使用链表头部进行入栈和头栈,这样时间复杂度为O(1)。相反,如果从链表的尾部入栈和出栈,时间复杂度为O(n)(此时需要遍历链表才能实现入栈和出栈)。
在这里插入图片描述
如果使用双向链表,从链表的头或者尾进行入栈和出栈,时间复杂度均为O(1)。因此,如果我们要使用链式栈,就可以选用双线链表来操作。
代码示例

    public static void main(String[] args) {
        LinkedList<Integer> stack=new LinkedList<>();
        stack.push(1);//入栈
        stack.push(2);
        stack.push(3);
        
        stack.pop();//出栈
    }

通过Ctrl查看LInkedListpush方法和pop方法可以发现,其本质是链表的头插和头删。
在这里插入图片描述
在这里插入图片描述

6. 队列概念

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出得的特点FIFO(First In First Out)。
入队列:进行插入操作的一端称为队尾(Tail/Rear)
出队列:进行删除操作的一端称为队头(Head/Front)
在这里插入图片描述

7. 队列的使用

在Java中,Queue是个接口,底层是通过链表实现的
在这里插入图片描述

方法功能
boolean offer(E e)入队列
E poll()出队列
peek()获取队头元素
int size()获取队列中有效元素个数
boolean isEmpty()检测队列是否为空

注意:Queue是个接口,在实例化时必须实例化LinkedList的对象,因为LinkedList实现了Queue接口。
在这里插入图片描述
上面是Queue接口的一些方法。add方法和offer方法都是用来新增元素的。remove方法和poll方法都是用来弹出元素的。element方法和peek方法都是用来获取队头元素的。那他们有什么区别呢?
在这里插入图片描述

注释翻译:
add方法

如果可以立即插入到此队列中,则在不违反容量限制的情况下插入指定的元素,成功后返回 true,如果当前没有可用空间,则引发 IllegalStateException。
参数:
e – 要添加的元素
返回:
true(由 Collection.add 指定)
抛出:
IllegalStateException – 如果由于容量限制而此时无法添加元素
ClassCastException – 如果指定元素的类阻止将其添加到此队列中
NullPointerException – 如果指定的元素为 null,并且此队列不允许 null 元素
IllegalArgumentException – 如果此元素的某些属性阻止将其添加到此队列中
offer方法
如果可以立即插入到此队列中,则将其指定的元素插入到此队列中,而不会违反容量限制。当使用容量受限的队列时,此方法通常比 add 更可取,后者只能通过引发异常来无法插入元素。
参数:
e – 要添加的元素
返回:
如果元素已添加到此队列中,则为 true,否则为 false
抛出:
ClassCastException – 如果指定元素的类阻止将其添加到此队列中
NullPointerException – 如果指定的元素为 null,并且此队列不允许 null 元素
IllegalArgumentException – 如果此元素的某些属性阻止将其添加到此队列中
在这里插入图片描述

注释翻译:
remove方法

检索和删除此队列的头部。此方法与 poll() 的不同之处仅在于如果此队列为空,它会引发异常。
返回:
此队列的头部
抛出:
NoSuchElementException – 如果此队列为空
poll方法
检索并删除此队列的头部,如果此队列为空,则返回 null。
返回:
此队列的头部,如果此队列为空,则为 null

在这里插入图片描述

注释翻译:
element方法

检索但不删除此队列的头部。此方法与 peek 的唯一区别在于,如果此队列为空,它会引发异常。
返回:
此队列的头部
抛出:
NoSuchElementException – 如果此队列为空
peek方法
检索但不删除此队列的头部,如果此队列为空,则返回 null。
返回:
此队列的头部,如果此队列为空,则为 null

使用代码示例

    public static void main(String[] args) {
        Queue<Integer> q=new LinkedList<>();

        q.offer(1);//入队列
        q.offer(2);
        q.offer(3);
        System.out.println(q.poll());//出队列
        System.out.println(q.poll());
        System.out.println(q.element());//查看第一个队列元素
        System.out.println(q.element());
        System.out.println(q.isEmpty());//队列判空
    }

8. 模拟队列的实现

队列中既然可以存储元素,那底层肯定要有能够保存元素的空间,通过前面线性表的学习了解到常见的空间类型有两种:顺序结构和链式结构

8.1 链式队列

在这里插入图片描述
我们使用双向链表来实现链式队列。实现代码如下:

public class MyQueue {
    static class ListNode{//队列节点
        public ListNode prev;
        public ListNode next;
        public int val;
        public ListNode(int val){
            this.val=val;
            this.prev=null;
            this.next=null;
        }
    }

    public ListNode head;
    public ListNode last;
	//入队列
    public void offer(int val) {
        ListNode node = new ListNode(val);//创建节点
        //尾插法入队列
        if(head==null){
            head=node;
            last=node;
        }else {
            last.next=node;
            node.prev=last;
            last=node;
        }
    }
	//出队列
    public int poll(){
        if(head==null){
            return -1;
        }
        //头删法出队列
        int ret=head.val;
        if(head.next==null){
            head=last=null;
        }else {
            head=head.next;
            head.prev=null;
        }
        return ret;
    }
	//查看队头元素
    public int peek(){
        if(head==null){
            return -1;
        }
        //如果队头不为空,返回队头的值
        return head.val;
    }
	//判断队列是否为空
    public boolean isEmpty(){
    	//如果头节点为null,队列为空
        return head==null;
    }
}

8.2 顺序队列

使用顺序表来实现队列,如果不移动元素的位置来进行出队列和入队列就会造成一个问题:假设first为队头(可以出数据的下标),last为队尾(可以存放数据的下标),入队过程中last到顺序表的最后一个位置,而first端元素在出队列,这样就会使队列的前一段空出来了而没有存储数据。示例图如下:
在这里插入图片描述
如果将last重新回到0下标的空间,这样会使队列不连续。因此,我们通过数组来实现环形队列。
在这里插入图片描述
环形队列的连续问题解决了,但是当队尾走到顺序表的尽头,此时我们一直让fist++或者last++可能会造成数组越界,我们可以在每次入队列或者出队列时加一个判断,当first==len或者last==len时让他们的下标设置为0,。我们也可以通过表达式来设置下标,first=(first+1)%len或者last=(last+1)%len,通过这个表达式就不用担心数组越界的问题了。
在这里插入图片描述
考虑完数组越界问题后,我们如何区分队列的空与满?单纯依靠头尾相遇并不能解决这个问题,因为环形链表头尾相遇时可能为空,也可能为满。我们有下面三种解决方案。题目:力扣循环队列。

  1. 使用usedSize,当usedSize==len时就为满。
class MyCircularQueue {
    public int[] elem;//存放队列元素
    public int first;//队列头
    public int last;//队列尾
    public int usedSize;//元素个数
    //构造方法
    public MyCircularQueue(int k) {
        elem=new int[k];
        this.usedSize=0;
        this.first=0;
        this.last=0;
    }
    //入队列 
    public boolean enQueue(int value) {
        if(isFull()){//判满,如果队列满了返回false
            return false;
        }
        //元素入队列
        elem[last]=value;
        //队尾位置往后移一个
        last=(last+1)%elem.length;
        //元素个数加1
        usedSize++;
        //成功入队列,返回true
        return true;
    }
    //出队列
    public boolean deQueue() {
        if(isEmpty()){//判空,如果队列为空返回false
            return false;
        }
        //出队列直接让对头往后移动一个
        first=(first+1)%elem.length;
        //元素个数减1
        usedSize--;
        //出队列成功,返回true
        return true;
    }
    //看队头元素
    public int Front() {
        if(isEmpty()){//判空,如果为空返回-1
            return -1;
        }
        //不为空,first下标即为队头元素
        return elem[first];
    }
    //看队尾元素
    public int Rear() {
        if(isEmpty()){//判空,如果为空返回-1
            return -1;
        }
        int index;
        if(last==0) {//如果last为0,队尾元素下标就为elem.length-1
            index = elem.length-1;
        }else {//否则,队尾元素下标为last-1
            index = last-1;
        }
        //返回对应下标的元素
        return elem[index];
    }
    //判空
    public boolean isEmpty() {
    //如果usedSize为0,队列尾空
        return usedSize==0;
    }
    //判满
    public boolean isFull() {
    //如果usedSize等于数组长度队列为满
        return usedSize==elem.length;
    }
}

  1. 使用一个boolean类型的标记,。
class MyCircularQueue {
    public int[] elem;//存放队列元素
    public int first;//队列头
    public int last;//队列尾
    public boolean flag;//标记
    //构造方法
    public MyCircularQueue(int k) {
        elem=new int[k];
        this.flag=false;//flag为false时,队列不满
        this.first=0;
        this.last=0;
    }
    //入队列
    public boolean enQueue(int value) {
        if(isFull()){//判满,如果队列满了返回false
            return false;
        }
        //元素入队列
        elem[last]=value;
        //队尾位置往后移一个
        last=(last+1)%elem.length;
        if(last==first){//入队列时,last走完一圈回到first队列就满了
            flag=true;
        }
        //成功入队列,返回true
        return true;
    }
    //出队列
    public boolean deQueue() {
        if(isEmpty()){//判空,如果队列为空返回false
            return false;
        }
        //出队列直接让对头往后移动一个
        first=(first+1)%elem.length;
        flag=false;//出队列时,队列就不满,标志设为false
        //出队列成功,返回true
        return true;
    }
    //看队头元素
    public int Front() {
        if(isEmpty()){//判空,如果为空返回-1
            return -1;
        }
        //不为空,first下标即为队头元素
        return elem[first];
    }
    //看队尾元素
    public int Rear() {
        if(isEmpty()){//判空,如果为空返回-1
            return -1;
        }
        int index;
        if(last==0) {//如果last为0,队尾元素下标就为elem.length-1
            index = elem.length-1;
        }else {//否则,队尾元素下标为last-1
            index = last-1;
        }
        //返回对应下标的元素
        return elem[index];
    }
    //判空
    public boolean isEmpty() {
        //如果last==first且flag为false,队列为空
        return last==first&&!flag;
    }
    //判满
    public boolean isFull() {
        //如果队列为满,flag为true
        return flag;
    }
}
  1. 浪费一个空间,当first+1==last时,为满。
class MyCircularQueue {

    public int[] elem;//存放队列元素
    public int first;//队列头
    public int last;//队列尾
    //构造方法
    public MyCircularQueue(int k) {
        //因为浪费了一个空间,所以为了保证能够存够k个元素就需要开辟k+1个空间
        elem=new int[k+1];
        this.first=0;//队头
        this.last=0;//队尾
    }
    //入队列
    public boolean enQueue(int value) {
        if(isFull()){//判满,如果队列满了返回false
            return false;
        }
        //元素入队列
        elem[last]=value;
        //队尾位置往后移一个
        last=(last+1)%elem.length;
        //成功入队列,返回true
        return true;
    }
    //出队列
    public boolean deQueue() {
        if(isEmpty()){//判空,如果队列为空返回false
            return false;
        }
        //出队列直接让对头往后移动一个
        first=(first+1)%elem.length;
        //出队列成功,返回true
        return true;
    }
    //看队头元素
    public int Front() {
        if(isEmpty()){//判空,如果为空返回-1
            return -1;
        }
        //不为空,first下标即为队头元素
        return elem[first];
    }
    //看队尾元素
    public int Rear() {
        if(isEmpty()){//判空,如果为空返回-1
            return -1;
        }
        int index;
        if(last==0) {//如果last为0,队尾元素下标就为elem.length-1
            index = elem.length-1;
        }else {//否则,队尾元素下标为last-1
            index = last-1;
        }
        //返回对应下标的元素
        return elem[index];
    }
    //判空
    public boolean isEmpty() {
    //头等于尾时为空
        return last==first;
    }

    public boolean isFull() {
    //浪费一个元素,尾的下一个为头就视为满
        return (last+1)%elem.length==first;
    }
}

9. 双端队列

双端队列(deque)是指允许两端都可以进行入队和出队操作的队列,deque 是 “double ended queue” 的简称。
那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。
在这里插入图片描述
Deque是一个接口,使用时必须创建LinkedList的对象。
在这里插入图片描述
在实际工程中,使用Deque接口是比较多的,栈和队列均可以使用该接口。

//下面这两个类也可以当做链表栈使用,也可以当做队列使用
Deque<Integer> stack = new ArrayDeque<>();//双端队列的线性实现
Deque<Integer> queue = new LinkedList<>();//双端队列的链式实现

下面是Deque的一些方法。
在这里插入图片描述
栈和队列相关练习题链接

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

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

相关文章

C++和OpenGL实现3D游戏编程【连载6】——不规则图形的纹理贴图

C++和OpenGL实现3D游戏编程【连载6】——不规则图形的纹理贴图 1、本节实现的内容 上一节我们讨论了纹理贴图的相关基础操作,但上一节的纹理贴图操作基本上都是规则图形,包括圆形和球形虽然复杂一点,但是它也是规则的。这一节课我们要讨论一下,怎么在不规则图形上纹理贴图…

​polarctf靶场[web]upload1​

[web]upload1 考点&#xff1a;文件上传漏洞 不信邪&#xff0c;先上传php&#xff0c;发现被拦截 在上传jpg和png图片&#xff0c;发现也被拦截 所以先拦截抓包&#xff0c;上传个有一句话木马的png图片 将文件后缀改为php&#xff0c;先在重发器发送&#xff0c;发现上传成…

MATLAB 计算凹凸多边形的面积(85)

MATLAB 计算凹凸多边形的面积(84) 一、算法介绍二、算法实现1.代码一、算法介绍 计算凹凸多边形的面积,并输出计算结果,可视化 二、算法实现 1.代码 % 设置多边形的顶点坐标 % 这里以一个五边形为例 x = [1, 3, 4

深入理解DPO(Direct Preference Optimization)算法

目录 1. 什么是DPO&#xff1f;2. Bradley-Terry模型2.1 奖励模型的训练 3. 从PPO到DPO4. DPO的简单实现5. 梯度分析Ref 1. 什么是DPO&#xff1f; 直接偏好优化&#xff08;Direct Preference Optimization, DPO&#xff09;是一种不需要强化学习的对齐算法。由于去除了复杂的…

数分基础(03-2)客户特征分析-简单可视化

文章目录 简单可视化1. 并排柱状图2. 堆叠柱状图2.1 画图2.2 对数刻度 简单可视化 接上一篇 数分基础&#xff08;03-1&#xff09;客户特征分析&#xff0c;运行本篇代码之前&#xff0c;先运行上一篇的代码。 为了能够对比和总览三个客户群体Cluster 0 - Cluster 1 的特征&…

冯·诺依曼计算机:现代计算机的“DNA”

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

XSS LABS - Level 16 过关思路

关注这个靶场的其他相关笔记&#xff1a;XSS - LABS —— 靶场笔记合集-CSDN博客 0x01&#xff1a;过关流程 进入靶场&#xff0c;右击页面&#xff0c;查看网页源码&#xff0c;搜索关键词 test 查看页面回显点&#xff1a; 页面只有一个回显点&#xff0c;跟前面关卡不同&am…

Python实时聊天室架构与API实战应用

尊敬的各位读者&#xff0c;欢迎参与本次共享研讨项目——利用Python构建实时聊天室。在本项目中&#xff0c;我们将引进一款前沿工具——发布订阅频道API&#xff0c;以实现聊天室内的实时交互功能。 在当今信息泛滥的社会环境下&#xff0c;实时交流已成为人们日常生活中不可…

探秘半枝莲:花语寓意深解、传奇传说追溯与卓越功效展现

在大自然的神秘宝藏中&#xff0c;有一种看似平凡却蕴含着无尽魅力的植物——半枝莲。它那娇小而鲜艳的花朵&#xff0c;仿佛是大自然精心雕琢的艺术品&#xff0c;散发着独特的魅力。当我们深入探寻半枝莲的世界时&#xff0c;会惊喜地发现它不仅有着迷人的花语寓意和传奇的传…

ES 根据条件删除文档

随着业务量的增多&#xff0c;es中数据越来越多&#xff0c;但有些数据其实后期并无业务用途&#xff0c;可直接做物理删除&#xff0c;程序里做兼容&#xff0c;但历史每个月的索引里的数据需要处理这部分冗余数据。 es提供_delete_by_query 根据查询条件进行删除的操作&…

ZooKeeper 实战(六) - 分布式ID实现方案

ZooKeeper 实战(六) - 生成分布式ID 文章目录 ZooKeeper 实战(六) - 生成分布式ID1.何为分布式ID2.分布式ID方案3.创建ZooKeeper节点4.获取序列ID5.处理序列ID6.使用分布式ID7.完整代码8.功能优化8.1.问题思考&#xff1f;1.容量问题2.并发问题3.内存问题 8.2.解决并发问题8.3.…

[Algorithm][综合训练][合唱团][跳台阶扩展问题][矩阵最长递增路径]详细讲解

目录 1.合唱团1.题目链接2.算法原理详解 && 代码实现 2.跳台阶扩展问题1.题目链接2.算法原理详解 && 代码实现 3.矩阵最长递增路径1.题目链接2.算法原理详解 && 代码实现 1.合唱团 1.题目链接 合唱团 2.算法原理详解 && 代码实现 解法&#…

爆火的《黑神话:悟空》对LabVIEW软件开发的启示

近期&#xff0c;《黑神话&#xff1a;悟空》在全球范围内爆火&#xff0c;引发了游戏行业和玩家群体的广泛关注。作为一款由中国开发团队Game Science历时多年打造的动作角色扮演游戏&#xff0c;它的成功不仅源于卓越的技术创新和对中国传统文化的深度挖掘&#xff0c;更在于…

本地部署Xinference实现智能体推理工作流(一)

提示&#xff1a;没有安装Docker的需要先提前安装好Docker 第一篇章 使用AutoDL平台快速部署xinference 备注&#xff1a;若使用AutoDL平台&#xff0c;以下过程使用无卡模型开机即可(省钱) 1. 下载Dify源码 Github下载Dify:https://github.com/langgenius/dify 2. 快速启动…

HTML粒子爱心

目录 写在前面 完整代码 代码分析 系列文章 写在最后 写在前面 教你用HTML语言实现粒子爱心动画的效果。 HTML&#xff0c;全称为HyperText Markup Language&#xff0c;即超文本标记语言&#xff0c;是构建网页的基本markup语言&#xff0c;它通过一系列标签tags来定义…

CMake Error at CMakeLists.txt (find_package)幕后真凶

竹杖芒鞋轻胜马,谁怕?一蓑烟雨任平生~ 个人主页&#xff1a; rainInSunny | 个人专栏&#xff1a; C那些事儿、 Learn OpenGL In Qt 文章目录 写在前面find_package报错解决Module模式Config模式 find_package()用法Module模式Config模式 写在前面 本文从CMake中find_packag…

AI无损放大工具 AI lossless zoomer 3.1.0.0

这款工具是作者基于腾讯开源免费的AI算法而开发的&#xff0c;腾讯开源算法地址&#xff1a;GitHub.com/xinntao/Real-ESRGAN 打开软件的主页面是黑色为主调的界面。把需要无损放大的图片直接拖入到软件中&#xff0c;再点【开始任务】&#xff0c;软件就会自动处理图片&#…

【论文阅读|cryoET】本周粗读汇总

论文1&#xff1a;CryoDRGN-ET&#xff1a;深度重建生成网络以可视化细胞内动态生物分子 Abstract 虽然冷冻电子断层扫描可以以分子分辨率揭示结构&#xff0c;但图像处理算法仍然是解决原位生物分子结构异质性的瓶颈。本文介绍CryoDRGN-ET用于cryoET断层图的异质重建。CryoD…

大厂产品经理面试:阿里、字节、百度、腾讯、拼多多等全国顶级大厂面试题一网打尽!

在互联网行业蓬勃发展的今天&#xff0c;产品经理作为连接技术、设计和市场的核心角色&#xff0c;其重要性日益凸显。想要进入国内顶尖的互联网大厂&#xff0c;如阿里巴巴、字节跳动、百度、腾讯、拼多多等&#xff0c;产品经理岗位的面试无疑是一场硬仗。本文将为你揭秘这些…

stm32定时器同步(二)

本文介绍使用一个定时器使能另一个定时器。 旧瓶装新酒&#xff0c;就是门控模式加一个TRGO&#xff0c;如果看到这里你还没有明白&#xff0c;那就去看看我前面的文章 代码部分也是旧瓶装新酒 void Timer3_Config(void) {TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM…