【数据结构-JAVA】栈(Stack)和队列(Queue)

news2024/11/16 10:18:00

1.1 栈的概念

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

举几个栈在现实生活中的例子,如:羽毛球放进羽毛球筒里,第一个放的最后一个拿,而最后放的最先拿到。

再比如,子弹装入弹匣,最先装的最后打出,而最后装的,最先打出。

1.2 栈的方法

方法

功能

Stack()

构造一个空的栈

E push(E e)

将e入栈,并返回e

E pop()

将栈顶元素出栈并返回

E peek()

获取栈顶元素,并且该栈顶元素不动

int size()

获取栈中有效元素个数

boolean empty()

检测栈是否为空

对比其他的数据结构,可以发现栈是一种较为简单的数据结构,主要特征便是先进后出,里面的方法也较其他数据结构数量更少。

import java.util.Stack;

public class Text {
    public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        stack.push(0);
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);
        stack.push(5);
        System.out.println(stack.size());
        System.out.print(stack.pop()+" ");
        System.out.print(stack.pop()+" ");
        System.out.print(stack.pop()+" ");
        System.out.print(stack.peek()+" ");//返回栈顶元素,但该元素依旧留在栈顶
        System.out.print(stack.peek()+" ");
        System.out.print(stack.pop()+" ");//返回栈顶元素,并将该元素出栈
        System.out.print(stack.pop()+" ");
        System.out.println(stack.pop()+" ");
        System.out.println(stack.empty());
    }
}

输出:

6

5 4 3 2 2 2 1 0

true

1.3 栈的模拟实现

栈的实现,可以使用数组,那就是个顺序栈,而如果使用链表,那就是链式栈,而若是使用单链表的话,拿就只能头插头删,只有这样的时间复杂度才都是 O(1);而如果使用的是双向链表的话,也是头插头删:

    public static void main(String[] args) {
        LinkedList<Integer> stack = new LinkedList<>();
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);
        System.out.println(stack.peek());
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack.pop());
    }

输出:

4

4

3

2

1

在 LinkedList 类的源代码中,也有跟栈一样的方法,发现 push 是头插,且 pop 也是头删:

下面的一个模拟实现,是用数组来实现的。

import java.util.Arrays;

public class MyStack {
    public int[] arr;
    public int usedSize;

    public MyStack() {
        arr = new int[10];
    }

    public int push(int data){
        if(isFull()){
            arr = Arrays.copyOf(arr,arr.length + 10);
        }
        arr[usedSize] = data;
        usedSize++;
        return data;
    }

    private boolean isFull(){
        return usedSize == arr.length;
    }

    public boolean isEmpty(){
        return usedSize == 0;
    }
    public int pop(){
        if(isEmpty()){
            throw new EmptyStackException("The Stack is empty!");
        }
//        int val = usedSize-1;
//        usedSize--;
//        return arr[val];
        //又或者写成如下更加简便的形式:
        return arr[--usedSize];
    }

    public int peek(){
        if(isEmpty()){
            throw new EmptyStackException("The Stack is empty!");
        }
        return arr[usedSize-1];
    }

    public int size(){
        return usedSize;
    }
}

题目 最小栈中:

在 push 函数中,else 的代码块中,if(val <= minStack.peek()) ,也就是说,stack 里如果出现相同的最小元素,也要存放到 minStack 中,

而在 pop 函数中, int val = stack.pop (拆箱了),后面if 判断 就可以写成 if(val == minStack.peek())

1.4 栈的使用场景

1.4.1 逆序打印链表

这个题目,采用以下两种方法来求解:

方法一:递归打印

    //递归打印链表
    public static void playList(Node pHead){
        if(pHead == null){
            return ;
        }
        
        if(pHead.next == null){
            System.out.println(pHead.val);
            return ;
        }

        playList(pHead.next);
        System.out.println(pHead.val);
    }

方法二:使用栈来打印

    //使用栈来逆着打印单向链表
    public static void playList1(){
        Stack<Node> stack = new Stack<>();
        Node cur = head;
        while(cur != null){
            stack.push(cur);
            cur = cur.next;
        }
        while(!stack.isEmpty()){
            Node temp = stack.pop();
            System.out.print(temp.val+" ");
        }
        System.out.println();
    }

1.4.2 括号匹配

给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。

左括号必须以正确的顺序闭合。

每个右括号都有一个对应的相同类型的左括号

class Solution {
    public boolean isValid(String s) {
        Stack<Character> stack = new Stack<>();
        for(int i = 0; i < s.length() ;i++){
            char ch = s.charAt(i);
            if(ch == '(' || ch == '{'||ch == '['){
                stack.push(ch);
            }else{
                if(stack.empty()){
                    return false;
                }
                char ch2 = stack.peek();
                if(ch == ')' && ch2 == '(' || ch == '}' && ch2 == '{' || ch == ']' && ch2 == '['){
                    stack.pop();
                    }else{
                        return false;
                    }
            }
        }
        
        if(!stack.empty()){
            return false;
        }

        return true;
    }
}

1.4.3 逆波兰表达式求值

给你一个字符串数组 tokens ,表示一个根据 逆波兰表达式 表示的算术表达式。

请你计算该表达式。返回一个表示表达式值的整数。

class Solution {
    public boolean isOperation(String x){
        if(x.equals("+")  || x.equals("-") || x.equals("*") || x.equals("/")){
            return true;
        }
        return false;
    }
    public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<>();
        for(String x : tokens){
            if(isOperation(x)){
                int num2 = stack.pop();
                int num1 = stack.pop();
                switch(x){
                case "+":
                stack.push(num1 + num2);
                break;
                case "-":
                stack.push(num1 - num2);
                break;
                case "*":
                stack.push(num1 * num2);
                break;
                case "/":
                stack.push(num1 / num2);
                break;                    
                }

            }else{
                stack.push(Integer.parseInt(x));
            }
        }
        return stack.pop();
    }
}

1.4.4 栈的压入、弹出序列

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。

import java.util.ArrayList;
import java.util.Stack;

public class Solution {
    public boolean IsPopOrder(int [] pushA,int [] popA) {
      int j = 0;
      Stack<Integer> stack = new Stack<>();
      for(int i = 0; i < pushA.length;i++){
        stack.push(pushA[i]);
        while(j < popA.length && !stack.empty() && stack.peek().equals(popA[j])){
            stack.pop();
            j++;
        }
      }
      if(!stack.empty()){
        return false;
      }
      return true;
    }
}

注意:stack.peek() == popA[j] 最好修改成 stack.peek().equals(popA[j])

1.4.5 最小栈

设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

实现 MinStack 类:

MinStack() 初始化堆栈对象。

void push(int val) 将元素val推入堆栈。

void pop() 删除堆栈顶部的元素。

int top() 获取堆栈顶部的元素。

int getMin() 获取堆栈中的最小元素。

class MinStack {
    private Stack<Integer> stack ;
    private Stack<Integer> minStack; 
    
 
    public MinStack() {
        stack = new Stack<>();
        minStack = new Stack<>();

    }
    
    public void push(int val) {
        stack.push(val);
        if(minStack.empty()){
            minStack.push(val);
        }else{
            if(val <= minStack.peek()){
                minStack.push(val);
            }
        }
    }
    
    public void pop() {
        if(!stack.empty()){
            Integer val = stack.pop();
            if(val.equals(minStack.peek())){
                minStack.pop();
            }
        }

    }
    
    public int top() {
        if(!stack.empty()){
            return stack.peek();
        }
        return -1;
    }
    
    public int getMin() {
        return minStack.peek();

    }
}

1.5 栈、虚拟机栈和栈帧的区别

栈是一种先进后出的数据结构,虚拟机栈是运行程序时的内存,而方法在虚拟机栈开辟的内存就叫栈帧。

2. 队列(Queue)

2.1 队列的概念

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出的原则。(FIFO——First In First Out)

入队列:进行插入操作的一端称为队尾(Tail/Rear) 出队列:进行删除操作的一端称为队头 (Head/Front)

2.2 队列的方法

在Java中,Queue是个接口,底层是通过链表实现的。

方法

功能

boolean offer(E e)

入队列

E poll()

出队列

E peek()

获取队头元素

int size()

获取队列有效元素个数

boolean isEmpty()

检测队列是否为空

注意:Queue是个接口,在实例化时必须实例化LinkedList的对象,因为LinkedList实现了Queue接口。

    public static void main(String[] args) {
        Queue<Integer> queue = new LinkedList<>();
        queue.offer(6);
        queue.offer(7);
        queue.offer(8);
        queue.offer(9);
        queue.offer(10);
        System.out.println(queue.toString());
        System.out.println(queue.size());
        System.out.println(queue.peek());
        System.out.println(queue.poll());
        System.out.println(queue.poll());
        System.out.println(queue.poll());
        System.out.println(queue.poll());
        System.out.println(queue.poll());
    }

输出:

[6, 7, 8, 9, 10]

5

6

6

7

8

9

10

LinkedList 重写 Queue 里面的方法,发现 offer 是尾插:

而 poll 是头删:

2.3 队列的模拟实现

单链表实现队列,首先得记录尾部,并且只能尾部插入,头部删除,而不能头部插入,尾部删除,因为此时,尾部的前一个节点不可知。

public class MyQueue {
    static class Node{
        public int val;
        public Node next;

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

    public Node head;
    public Node last;
    public int usedSize;

    //入队列
    public void offer(int data){
        Node node = new Node(data);
        //队列为空时:
        if(head == null){
            head = node;
            last = node;
        }else{
            //队列不为空时,单向链表的尾部入队列:
            last.next = node;
            last = node;
        }
        usedSize++;
    }

    //出队列
    public int poll(){
        //队列为空时:
        if(empty()){
            throw new EmptyQueueException("队列为空,出队列失败!");
        }
        int val = head.val;
        //队列只有一个元素时:
        if(head.next == null){
            last = last.next;
        }
        head = head.next;
        usedSize--;
        return val;
    }

    public int peek(){
        if(empty()){
            throw new EmptyQueueException("队列为空,队头的首个元素获取失败!");
        }
        return head.val;
    }

    public boolean empty(){
        return usedSize == 0;
    }

    public int getUsedSize(){
        return usedSize;
    }
}
public class Text {
    public static void main(String[] args) {
        MyQueue myQueue = new MyQueue();
        myQueue.offer(1);
        myQueue.offer(5);
        myQueue.offer(8);
        myQueue.offer(13);
        myQueue.offer(19);
        System.out.println(myQueue.getUsedSize());
        System.out.println(myQueue.peek());
        System.out.println(myQueue.poll());
        System.out.println(myQueue.poll());
        System.out.println(myQueue.poll());
        System.out.println(myQueue.poll());
        System.out.println(myQueue.poll());
    }
}

输出:

5

1

1

5

8

13

19

而双向链表实现队列,头删尾插 ,或头插尾删的时间复杂度都是 O(1) ,下面的模拟实现,是头插尾删:

public class MyQueue2 {
    static class Node{
        public int val;
        public Node prev;
        public Node next;

        public Node(int val) {
            this.val = val;
        }
    }
    public Node head;
    public Node last;
    public int usedSize;

    public void offer(int data){
        Node node = new Node(data);
        if(head == null){
            last = node;
        }else{
            node.next = head;
            head.prev = node;
        }
        head = node;
        usedSize++;
    }

    public int poll(){
        if(empty()){
            throw new EmptyQueueException("队列为空,出队列失败!");
        }
        int ret = last.val;
        if(last == head){
            last = null;
            head = null;
        }else{
            last = last.prev;
            last.next.prev = null;
            last.next = null;
        }
        usedSize--;
        return ret;
    }

    public int getUsedSize(){
        return usedSize;
    }
    public boolean empty(){
        return usedSize == 0;
    }

    public int peek(){
        return  last.val;
    }
}
    public static void main(String[] args) {
        MyQueue2 myQueue2 = new MyQueue2();
        myQueue2.offer(9);
        myQueue2.offer(6);
        myQueue2.offer(4);
        myQueue2.offer(3);
        myQueue2.offer(2);
        System.out.println(myQueue2.getUsedSize());
        System.out.println(myQueue2.peek());
        System.out.println(myQueue2.poll());
        System.out.println(myQueue2.poll());
        System.out.println(myQueue2.poll());
        System.out.println(myQueue2.poll());
        System.out.println(myQueue2.poll());
    }

输出:

5

9

9

6

4

3

2

2.4 循环队列

实际中我们有时还会使用一种队列叫循环队列。如操作系统中,讲解生产者消费者模型时可以就会使用循环队列。 循环队列通常使用数组实现。

如果我们使用数组去实现队列,就会遇到这样一个问题:一旦这个数组满了,即使释放了队列前面的元素,我们也无法插入新的元素。但是使用循环队列,我们能使用这些空间去存储新的值。

循环队列的实现思路:

  1. 用 front 和 rear 引用来分别存储队列的头元素和尾部的下一个元素,当队列为空时,front 和 rear 指向数组下标为 0 的位置:

  1. 从 rear 位置处插入第一个元素 666 , front 不变,而 rear 往后走一个:

  1. 以此类推,将整个队列装满元素:

不知同学们发现没有,数组下标为 7 的位置是空的,但我在上面却说“满”,这是为何?

如果连下标为 7 的地方也放了元素,那么 rear 和 front 又重新指向同一个地方了,那如何与空区别?

上面两个问题,让我来一一解答:

其实判断循环队列是否满了,有很多方法,这里讲解两种。

第一种,牺牲一个空间,为后续判断是否满了做准备。

在这里我们先思考一个问题,循环队列,如何循环呢? 0 -> 1 -> 2 -> 3 - >4 ->5 ->6 -> 7 ->0 ,所以不管对于 front 还是 rear ,下标7 的下一个是 0 ,而不是8 ,也就是说,我们不能再使用 front++ ,或 rear++,而是

front = (front + 1) % arr.length
rear = (rear + 1) % arr.length

而最后一个空间不去用,就是为了区分空和满的状态,空是 front == rear, 而满就是 (rear + 1) % arr.length == front ,即 rear 的下一个位置,与 front 相同。此时队列为满,不再添加。除非在头部进行删除,这样 front = (front + 1) % arr.length , front 来到下一个:

这时,又可以在尾部进行添加了。

而第二种判断循环队列是否满的方法,是利用一个 size 变量,来记录队列已存储的总个数,这时候整个数组都可以放满。

下面的代码实现,是通过牺牲一个空间来判断满否:

class MyCircularQueue {
    private int[] elem;
    private int front;//表示队列的头
    private int rear;//表示队列的尾

        public MyCircularQueue(int k) {
            //如果是以牺牲一个空间来作为判断是否满了的标准,这里可以多申请一个空间
            elem = new int[k+1];
        }

        //入队列
        public boolean enQueue(int value) {
            if(isFull()){
                return false;
            }
            elem[rear] = value;
            rear = (rear + 1) % elem.length;
            return true;
        }

        //出队列
        public boolean deQueue() {
            if(isEmpty()){
                return false;
            }
            front = (front + 1) % elem.length;
            return true;
        }

        public int Front() {
            if(isEmpty()){
                return -1;
            }
            return elem[front];
        }

        public int Rear() {
            if(isEmpty()){
                return -1;
            }
            return rear == 0 ? elem[elem.length - 1] :elem[rear - 1];
        }

        public boolean isEmpty() {
            return rear == front;
        }

        public boolean isFull() {
            return (rear + 1) % elem.length == front;
        }
}

2.5 双端队列(Deque)

双端队列(deque)是指允许两端都可以进行入队和出队操作的队列,deque 是 “double ended queue” 的简称。 那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。

3. 栈和队列的相互实现

3.1 利用栈去实现队列

3.1.1 实现思路

  1. 申请两个栈:

  1. offer 时,如果是首次 offer,那么指定一个栈用来存放元素入队列,这里是 stack1 入队列,往后入队列就都往 stack1 去放。

  1. poll 时,找到非空的那个栈,这里是 stack2 ,往 stack2 依次放入 stack1 里的所有元素,最后 stack2 栈顶的元素就是队列 poll 的元素。

  1. 继续往队列中放元素,放入 stack1 中:

  1. 队列中继续删掉 22 和 41,那么 stack2 中依次出栈,为空:

  1. 队列继续出队列,由于 stack2 为空,而 stack1 不为空,那么将 stack1 中的元素依次放于 stack2 中,再依次出栈,一直到两个栈都没有元素为止。

3.1.2 具体代码实现

import java.util.Stack;

public class MyQueue {
    private Stack<Integer> stack1 ;
    private Stack<Integer> stack2 ;

    public MyQueue() {
        stack1 = new Stack<>();
        stack2 = new Stack<>();
    }

    //选择 stack1 存放入队列时的数据
    public void push(int x) {
        stack1.push(x);
    }

    //选择 stack2 存放出队列时的数据
    public int pop() {
        if(empty()){
            return -1;
        }
        if(stack2.empty()){
            while(!stack1.empty()){
                stack2.push(stack1.pop());
            }
        }     
            return stack2.pop();
        
    }

    public int peek() {
        if(empty()){
            return -1;
        }
        if(stack2.empty()){
            while(!stack1.empty()){
                stack2.push(stack1.pop());
            }
        }    
            return stack2.peek();
    }

    public boolean empty() {
        return stack1.empty() && stack2.empty();
    }
}

3.2 利用队列去实现栈

3.2.1 实现思路

  1. 申请两个队列,queue1 和 queue2 :

  1. 入栈时,若是首次入栈,则选一个空的队列存放入栈数据即可,这里选择了 queue1 :

  1. 出栈时,找到那个非空的队列,如 queue1,队头元素 queue1.size() - 1 次出队列到一个空的队列中,如 queue2。然后让 queue1 中最后一个元素出队列,这就是出栈的元素。

  1. 此时若是再入栈,那么将元素入队列到非空的队列中,如 queue2

  1. 若是再出栈,便如步骤3 所示。

  1. 3、4 反复操作,一直到两个队列为空为止。

3.2.2 代码

public class MyStack {
    private Queue<Integer> queue1 ;
    private Queue<Integer> queue2 ;

    public MyStack() {
        queue1 = new LinkedList<>();
        queue2 = new LinkedList<>();
    }

    public void push(int x) {
        if(!queue1.isEmpty()){
            queue1.offer(x);
        }else if(!queue2.isEmpty()){
            queue2.offer(x);
        }else{
            queue1.offer(x);
        }
    }

    public int pop() {
        if(empty()){
            return -1;
        }
        if(!queue1.isEmpty()){
            int size = queue1.size();
            for (int i = 0; i < size - 1 ; i++) {
                queue2.offer(queue1.poll());
            }
            return queue1.poll();
        }else{
            int size = queue2.size();
            for (int i = 0; i < size - 1 ; i++) {
                queue1.offer(queue2.poll());
            }
            return queue2.poll();
        }
    }

    public int top() {
        if(empty()){
            return -1;
        }
        int val = -1;
        if(!queue1.isEmpty()){
            int size = queue1.size();

            for (int i = 0; i < size  ; i++) {
                val = queue1.poll();
                queue2.offer( val);
            }
            return val;
        }else{
            int size = queue2.size();
            for (int i = 0; i < size  ; i++) {
                val = queue2.poll();
                queue1.offer( val);
            }
            return val;
        }
    }

    public boolean empty() {
        return queue1.isEmpty() && queue2.isEmpty();
    }
}

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

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

相关文章

【从零开始学习深度学习】41. 算法优化之RMSProp算法【基于AdaGrad算法的改进】介绍及其Pytorch实现

上一篇文章AdaGrad算法中提到&#xff0c;因为调整学习率时分母上的变量st\boldsymbol{s}_tst​一直在累加按元素平方的小批量随机梯度&#xff0c;所以目标函数自变量每个元素的学习率在迭代过程中一直在降低&#xff08;或不变&#xff09;。因此&#xff0c;当学习率在迭代早…

LeetCode 45. 跳跃游戏 II

45. 跳跃游戏 II - 力扣&#xff08;LeetCode&#xff09; 解法1&#xff1a;&#xff08;动态规划 贪心&#xff09; 果然代码越短&#xff0c;思路越难。这题用的是动态规划贪心的思想。首先分析题意我们可以知道&#xff0c;从索引0这个点开始&#xff0c;我们走一步可以…

redis命令第二弹

1、redis命令-hash类型练习2、redis命令-list类型练习3、redis命令-set类型练习

YOLOV5环境搭建以及训练COCO128数据集

前言记录了自己训练coco128的全过程手把手教你YOLOV5环境搭建以及训练COCO128数据集。相关配置文件在百度网盘中。如果懒得话可以直接全部用我的数据一、准备工作1.1创建环境打开anaconda power shell&#xff08;最好以管理员身份运行&#xff0c;免得到后面相关文件权限进不去…

sentinel-介绍(一)

Sentinel Website&#xff08;Sentinel 官网网站&#xff09; Sentinel: 分布式系统的流量防卫兵 Sentinel 是什么&#xff1f; 随着微服务的流行&#xff0c;服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点&#xff0c;从流量控制、流量路由、熔断降级、系…

ansible配置yum源仓库

1.挂载本地光盘到/mnt 2.配置yum源仓库文件通过多种方式实现 仓库1 &#xff1a; Name: RH294_Base Description&#xff1a; RH294 base software Base urt: file:///mnt/BaseOS 不需要验证钦件包 GPG 签名 启用此软件仓库 仓库 2: Name: RH294_S…

LeetCode刷题模版:41 - 50

目录 简介41. 缺失的第一个正数42. 接雨水43. 字符串相乘44. 通配符匹配45. 跳跃游戏 II46. 全排列47. 全排列 II48. 旋转图像49. 字母异位词分组50. Pow(x, n)结语简介 Hello! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出~ ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标…

axios系列之取消请求

文章の目录写在最后使用 cancel token 取消请求 Axios 的 cancel token API 基于cancelable promises proposal&#xff0c;它还处于第一阶段。 可以使用 CancelToken.source 工厂方法创建 cancel token&#xff0c;像这样&#xff1a; const CancelToken axios.CancelToken;…

Revit二次开发小技巧(十七)实时监控模型线的生成

前言&#xff1a;项目中需要一个需求&#xff0c;用户想调用出Revit中自带的绘制模型线方法&#xff0c;然后再绘制结束时&#xff0c;可以拿到绘制的模型线&#xff0c;然后实现后面的算法。这里记录一种方法&#xff0c;通过DocumentChange事件修改Tag的PropertyChanged事件来…

【Python】pandas获取全省人口数据并作可视化分析

前言 今天我们看看自己所在的省份的人口人数&#xff0c;使用pandas并作可视化分析。 环境使用 python 3.9pycharm 模块使用 pandasPandas 是基于NumPy的一种工具&#xff0c;该工具是为解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型&#xff0c;提供…

java和vue募捐网水滴筹项目捐款爱心系统筹款系统

简介 募捐网&#xff0c;注册用户实名认证通过后可以发布募捐&#xff0c;管理员审核募捐通过后&#xff0c;前台用户可以看到该募捐信息&#xff0c;进行募捐或者举报&#xff08;管理审核举报成功后&#xff0c;会拉黑该募捐发起人&#xff09;&#xff0c;前台展示公告、爱…

83. 删除排序链表中的重复元素(链表)

文章目录题目描述方法一 暴力法方法二 递归法参考文献题目描述 给定一个已排序的链表的头 head &#xff0c; 删除所有重复的元素&#xff0c;使每个元素只出现一次 。返回 已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,1,2] 输出&#xff1a;[1,2] 示例 2…

酷开系统——家庭场景下的智能营销系统!

随着人们生活方式的改变&#xff0c;以往传统的营销资源和渠道正在慢慢陷入一个“无用”的尴尬境地&#xff0c;而作为家庭娱乐中心的智能大屏&#xff0c;近两年所表现出来的数据和效果却逐渐备受企业和品牌方关注&#xff0c;有数据显示&#xff0c;智能大屏的家庭覆盖规模正…

bug 站在一个测试的角度看bug

如何描述一个bug ?如何定义bug的级别 ?bug的生命周期 ?如何开始第一次测试 ?测试的执行和bug管理 ?产生争执怎么办 ?如何描述一个bug?作为一名测试人员&#xff0c;提bug是最基础的工作&#xff0c;那我们如何才能把bug提的清晰易懂呢?发现问题的版本 开发人员获取对应…

k8s之基于kubeadm搭建k8s集群

写在前面 你可能知道搭建k8s集群的kind&#xff0c;minikube工具&#xff0c;但是他们都太简单了&#xff0c;不能满足生产级的要求&#xff0c;想要真正的部署生产级别的k8s集群&#xff0c;我们还需要另外一个集群管理工具kubeadm ,本文就一起看下如何使用该工具来搭建k8s集…

STM32MP157驱动开发——Linux下的单总线驱动

STM32MP157驱动开发——Linux下的单总线驱动0.前言一、DS18B20 及工作时序简介1.DS18B20 简介2.DS18B20 时序简介4.DS18B20温度读取流程二、DHT11 及工作时序简介1.DHT11 简介2.DHT11 工作时序简介三、驱动开发1.DS18B20驱动1&#xff09;修改设备树2&#xff09;驱动编写2.测试…

IB生物:干细胞与生命的各种功能

国际学校生物老师解读IB生物&#xff0c;感兴趣的同学记得收藏哦~IB生物分为SL(standard level)和HL(higher level)SL有6个topic∶细胞生物&#xff0c;分子生物&#xff0c;遗传学&#xff0c;生态学&#xff0c;物种进化以及多样性和人体生理。HL除了上述6个topic外还要加上∶…

Python入门基础实例讲解——两个数字比大小,并输出最大值

嗨害大家好鸭&#xff01; 我是小熊猫~ 今天也是给大家带来干货的一天~ pycharm永久激活码可以从这里找到我&#xff1a; 输出&#xff1a;print&#xff08;&#xff09; print() 方法用于打印输出&#xff0c;最常见的一个函数。 比较运算符 >&#xff1a; 大于&#…

关于校园网的各种连接问题

校园网网络使用异常&#xff0c;掉线、卡顿以及无法连接网络&#xff0c;经网络上收据的信息&#xff0c;大致分为五类&#xff1a;1.能获取到校园网地址如10.*.*.*&#xff0c;但无法跳出认证界面。2.物理链路故障&#xff1b;3.IP配置故障&#xff1b;4. 网络正常&#xff0c…

SpringCloud高级应用-1(SpringCloud技术栈概览)

1、SpringCloud技术栈 开发分布式系统可能具有挑战性&#xff0c;复杂性已从应用程序层转移到网络层&#xff0c;并要求服务之间进行更多的交互。将代码设为“cloud-native”就需要解决12-factor&#xff0c;例如外部配置&#xff0c;服务无状态&#xff0c;日志记录以及连接…