【數據結構】棧和隊列-----數據結構中的雙生花

文章目錄

    • @[toc]
  • 棧與隊列:數據結構中的雙生花
    • 1. 棧:后進先出的有序世界
      • 1.1 概念及結構剖析
      • 1.2 實現方式深度解析
        • 數組 vs 鏈表實現
      • 1.3 動態棧實現詳解(附程序源碼)
        • 1.定義一個動態棧
        • 2.初始化
        • 3.銷毀
        • 4.入棧
        • 5.出棧
        • 6.取棧頂數據
        • 7.判空
        • 8.獲取數據個數
        • 9.訪問棧
        • 10.程序源碼
      • 1.4 棧的應用場景
        • 1. 函數調用棧
        • 2. 表達式求值
        • 3. 瀏覽器歷史記錄
        • 4. 撤銷操作(Undo)
    • 2. 隊列:先進先出的公平之師
      • 2.1 概念及結構剖析
      • 2.2 實現方式
        • 為什么鏈表實現更優?
      • 2.3 隊列實現詳解(附程序源碼)
        • 核心數據結構定義
        • 1.初始化
        • 2.隊列的銷毀
        • 3.隊尾插入
        • 4.隊頭刪除
        • 5.統計隊列中數據個數
        • 6.取隊頭數據
        • 7.取隊尾數據
        • 8.判空
        • 9.訪問隊列
        • 10.程序源碼
      • 2.4 隊列的應用場景
        • 1. 消息隊列系統
        • 2. 打印機任務調度
        • 3. 廣度優先搜索(BFS)
        • 4. CPU任務調度
    • 3. 棧與隊列的對比分析
    • 4. 高級變體與應用
      • 4.1 雙端隊列(Deque)
      • 4.2 優先隊列(Priority Queue)
    • 5. 總結:選擇合適的數據結構

在這里插入圖片描述

棧與隊列:數據結構中的雙生花

在計算機科學的世界里,棧和隊列如同雙生花般存在——它們看似相似卻各有千秋,共同構成了最基本也是最強大的數據結構工具集。

1. 棧:后進先出的有序世界

1.1 概念及結構剖析

棧(Stack)是一種特殊的線性表,其核心特性是只允許在固定一端(棧頂)進行插入和刪除操作。這種結構遵循**后進先出(LIFO)**原則:最后進入的元素最先被移除。

關鍵術語解析

  • 壓棧/入棧(Push):在棧頂插入新元素
  • 出棧(Pop):從棧頂刪除元素
  • 棧頂(Top):唯一允許操作的一端
  • 棧底(Bottom):不允許操作的一端

結構可視化

棧頂 → D → C → B → A ← 棧底
出棧順序:D → C → B → A

在這里插入圖片描述

在這里插入圖片描述

1.2 實現方式深度解析

數組 vs 鏈表實現

在棧的實現中,數組和鏈表各有優劣:

特性數組實現鏈表實現
內存使用連續內存空間非連續內存空間
擴容成本較高(需重新分配)較低(動態分配)
訪問速度O(1) 隨機訪問O(n) 順序訪問
緩存友好性
實現復雜度簡單中等

為什么數組實現更優?
對于棧這種主要在尾部操作的數據結構,數組的尾部插入/刪除操作時間復雜度為O(1),且CPU緩存預取機制對連續內存訪問更友好。雖然擴容時需要重新分配內存,但通過倍增策略可以攤還這一成本。

在這里插入圖片描述

在這里插入圖片描述

1.3 動態棧實現詳解(附程序源碼)

跟鏈表一樣,我們采用多文件操作

在這里插入圖片描述

1.定義一個動態棧
typedef int STDataType;
typedef struct Stack {STDataType* _a;     // 動態數組int _top;           // 棧頂位置int _capacity;      // 容量
} ST;
2.初始化
void STInit(ST* pst)
{assert(pst);pst->a = 0;pst->capacity = 0;pst->top = 0;
}

在這有兩種寫法,第一種是top指向棧頂,第二種是top指向棧頂的下一個位置

我個人更推薦第二種寫法 這種寫法的top類似于鏈表中的size在這里插入圖片描述


3.銷毀
void STDestroy(ST* pst)
{assert(pst);free(pst->a);pst->a = NULL;pst->top = pst->capacity = 0;
}
4.入棧
void STPush(ST* pst, STDataType x)
{assert(pst);//擴容if (pst->top == pst->capacity){int newcapcacity =pst->capacity==0 ? 4 : pst->capacity * 2;//起始空間為0則申請4個空間 不為0則二倍STDataType* tmp = (STDataType*)ralloc(pst->a, newcapcacity * sizeof(STDataType));//pst->a為NULL時,realloc相當與mallocif (tmp == NULL){perror("realloc fail");}pst->a = tmp;pst->capacity = newcapcacity;}pst->a[pst->top] = x;pst->top++;//top指向棧頂下一個元素}
5.出棧
void STPop(ST* pst)
{assert(pst);pst->top--;
}
6.取棧頂數據
STDataType STTop(ST* pst)
{assert(pst);assert(pst->top > 0);//top大于0才能取return pst->a[pst->top - 1];//top是棧頂的下一個數據 所以要-1
}
7.判空
bool STEmpty(ST* pst)
{assert(pst);return pst->top == 0;//==0就是空
}
8.獲取數據個數
int STSize(ST* pst)
{assert(pst);return pst->top;//也就是獲取top 因為這里的top相當于size
}
9.訪問棧
#define _CRT_SECURE_NO_WARNINGS
#include"Stack.h"
int main()
{ST s;STInit(&s);STPush(&s, 1);STPush(&s, 2);STPush(&s, 3);STPush(&s, 4);while (!STEmpty(&s)){printf("%d ", STTop(&s));STPop(&s);//打印一刪除一個}STDestroy(&s);return 0;
}
10.程序源碼

Stack.h ———函數聲明

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>typedef int STDataType;typedef struct Stack
{STDataType* a;int top;int capacity;
}ST;
//初始化和銷毀
void STInit(ST* pst);
void STDestroy(ST* pst);//入棧出棧
void STPush(ST* pst, STDataType x);
void STPop(ST* pst);//取棧頂數據
STDataType STTop(ST* pst);//判空
bool STEmpty(ST* pst);
//獲取數據個數
int STSize(ST* pst);

Stack.c———函數的實現

#define _CRT_SECURE_NO_WARNINGS
#include"Stack.h"
//初始化和銷毀
void STInit(ST* pst)
{assert(pst);pst->a = 0;pst->capacity = 0;pst->top = 0;
}
void STDestroy(ST* pst)
{assert(pst);free(pst->a);pst->a = NULL;pst->top = pst->capacity = 0;
}//入棧出棧
void STPush(ST* pst, STDataType x)
{assert(pst);//擴容if (pst->top == pst->capacity){int newcapcacity =pst->capacity==0 ? 4 : pst->capacity * 2;//起始空間為0則申請4個空間 不為0則二倍STDataType* tmp = (STDataType*)realloc(pst->a, newcapcacity * sizeof(STDataType));//pst->a為NULL時,realloc相當與mallocif (tmp == NULL){perror("realloc fail");}pst->a = tmp;pst->capacity = newcapcacity;}pst->a[pst->top] = x;pst->top++;//top指向棧頂下一個元素}
void STPop(ST* pst)
{assert(pst);pst->top--;
}//取棧頂數據
STDataType STTop(ST* pst)
{assert(pst);assert(pst->top > 0);return pst->a[pst->top - 1];
}//判空
bool STEmpty(ST* pst)
{assert(pst);return pst->top == 0;//==0就是空
}
//獲取數據個數
int STSize(ST* pst)
{assert(pst);return pst->top;
}

test.c——測試

#define _CRT_SECURE_NO_WARNINGS
#include"Stack.h"
int main()
{ST s;STInit(&s);STPush(&s, 1);STPush(&s, 2);STPush(&s, 3);STPush(&s, 4);while (!STEmpty(&s)){printf("%d ", STTop(&s));STPop(&s);}STDestroy(&s);return 0;
}

1.4 棧的應用場景

1. 函數調用棧

程序執行時,每次函數調用都會在棧中創建一個棧幀(Stack Frame),存儲:

  • 返回地址

  • 局部變量

  • 函數參數

  • 寄存器狀態

    void funcA() {int a = 10; // 棧幀創建funcB();// 返回后棧幀銷毀
    }void funcB() {int b = 20; // 新棧幀
    }
    
    2. 表達式求值

    棧用于處理各種表達式:

    • 中綴轉后綴:操作數棧和運算符棧
    • 括號匹配:遇到左括號入棧,右括號出棧
    • 計算后綴表達式:操作數入棧,遇到運算符出棧計算

    示例:(1 + 2) * 3的后綴表達式 1 2 + 3 *

    3. 瀏覽器歷史記錄

    瀏覽器的后退功能使用棧實現:

    class BrowserHistory:def __init__(self):self.back_stack = []   # 后退棧self.forward_stack = [] # 前進棧def visit(self, url):self.back_stack.append(url)self.forward_stack = []  # 清空前進棧def back(self):if len(self.back_stack) > 1:self.forward_stack.append(self.back_stack.pop())return self.back_stack[-1]
    
    4. 撤銷操作(Undo)

    文本編輯器中的撤銷機制:

    public class TextEditor {private StringBuilder text = new StringBuilder();private Stack<String> history = new Stack<>();public void type(String words) {history.push(text.toString()); // 保存狀態text.append(words);}public void undo() {if (!history.isEmpty()) {text = new StringBuilder(history.pop());}}
    }
    

2. 隊列:先進先出的公平之師

2.1 概念及結構剖析

隊列(Queue)是一種只允許在一端(隊尾)插入,在另一端(隊頭)刪除的線性表。這種結構遵循**先進先出(FIFO)**原則:最先進入的元素最先被移除。

關鍵術語解析

  • 入隊(Enqueue):在隊尾插入新元素
  • 出隊(Dequeue):從隊頭刪除元素
  • 隊頭(Front):刪除操作端
  • 隊尾(Rear):插入操作端

結構可視化

在這里插入圖片描述

隊頭 → A → B → C → D → E ← 隊尾
出隊順序:A → B → C → D → E

2.2 實現方式

在這里插入圖片描述

實現方案:隊列也可以數組和鏈表的結構實現,使用鏈表的結構實現更優一些,因為如果使用數組的結構,出隊列在數組頭上出數據,效率會比較低。

為什么鏈表實現更優?

對于隊列這種需要在兩端操作的數據結構:

  • 數組實現問題
    • 出隊操作需要移動所有元素(O(n)時間復雜度)
    • 假溢出問題(實際空間可用但無法入隊)
    • 需要復雜的環形緩沖區處理
  • 鏈表實現優勢
    • O(1)時間復雜度的入隊/出隊操作
    • 動態內存分配,無固定大小限制
    • 自然避免假溢出問題

2.3 隊列實現詳解(附程序源碼)

核心數據結構定義
typedef int QDataType;typedef struct QueueNode
{struct QueueNode* next;QDataType val;
}QNode;// 隊列結構
typedef struct Queue {QNode* phead;  // 隊頭指針QNode* ptail;   // 隊尾指針int size;//用來計數
} Queue;//用一個結構題體來放頭節點跟尾節點,這樣傳參就可以只傳一個
1.初始化
void QueueInit(Queue* pq)
{assert(pq);pq->phead = NULL;pq->ptail = NULL;pq->size = 0;
}
2.隊列的銷毀
void QueueDestroy(Queue* pq)
{assert(pq);QNode* cur = pq->phead;while (cur){QNode* next = cur->next;free(cur);cur = next;}pq->phead = pq->ptail = NULL;pq->size = 0;
}
3.隊尾插入
void QueuePush(Queue* pq, QDataType x)
{QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc fail");return;}newnode->next = NULL;newnode->val = x;if (pq->ptail == NULL){pq->phead = pq->ptail = newnode;}else{pq->ptail->next = newnode;pq->ptail = newnode;}pq->size++;
}
4.隊頭刪除
void QueuePop(Queue* pq)
{assert(pq);assert(pq->phead);if (pq->phead->next == NULL)//一個節點{free(pq->phead);pq->phead = pq->ptail = NULL;}else//多個節點{QNode* next = pq->phead->next;free(pq->phead);pq->phead = next;}pq->size--;
}
5.統計隊列中數據個數
int QueueSize(Queue* pq)
{assert(pq);return pq->size;
}
6.取隊頭數據
QDataType QueueFront(Queue* pq)
{assert(pq);assert(pq->phead);return pq->phead->val;
}
7.取隊尾數據
QDataType QueueBack(Queue* pq)
{assert(pq);assert(pq->phead);return pq->ptail->val;
}
8.判空
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->size == 0;
}
9.訪問隊列
int main()
{Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);while (!QueueEmpty(&q)){printf("%d ", QueueFront(&q));//取隊頭數據QueuePop(&q);}printf("\n");return 0;
}
10.程序源碼

Queue.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>typedef int QDataType;typedef struct QueueNode
{struct QueueNode* next;QDataType val;
}QNode;typedef struct Queue
{QNode* phead;QNode* ptail;int size;
}Queue;//初始化
void QueueInit(Queue* pq);
//隊列的銷毀
void QueueDestroy(Queue* pq);
//隊尾插入
void QueuePush(Queue* pq, QDataType x);
//隊頭刪除
void QueuePop(Queue* pq);
//統計隊列中數據的個數
int QueueSize(Queue* pq);
//取隊頭數據
QDataType QueueFront(Queue* pq);
//取隊尾數據
QDataType QueueBack(Queue* pq);//判空
bool QueueEmpty(Queue* pq);

Queue.c

#define _CRT_SECURE_NO_WARNINGS
#include"Queue.h"void QueueInit(Queue* pq)
{assert(pq);pq->phead = NULL;pq->ptail = NULL;pq->size = 0;
}
void QueuePush(Queue* pq, QDataType x)
{QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc fail");return;}newnode->next = NULL;newnode->val = x;if (pq->ptail == NULL){pq->phead = pq->ptail = newnode;}else{pq->ptail->next = newnode;pq->ptail = newnode;}pq->size++;
}int QueueSize(Queue* pq)
{assert(pq);return pq->size;
}void QueuePop(Queue* pq)
{assert(pq);assert(pq->phead);if (pq->phead->next == NULL)//一個節點{free(pq->phead);pq->phead = pq->ptail = NULL;}else//多個節點{QNode* next = pq->phead->next;free(pq->phead);pq->phead = next;}pq->size--;
}
QDataType QueueFront(Queue* pq)
{assert(pq);assert(pq->phead);return pq->phead->val;
}
QDataType QueueBack(Queue* pq)
{assert(pq);assert(pq->phead);return pq->ptail->val;
}
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->size == 0;
}
void QueueDestroy(Queue* pq)
{assert(pq);QNode* cur = pq->phead;while (cur){QNode* next = cur->next;free(cur);cur = next;}pq->phead = pq->ptail = NULL;pq->size = 0;
}

test.c

#define _CRT_SECURE_NO_WARNINGS
#include"Queue.h"
int main()
{Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);QueuePush(&q, 3);QueuePush(&q, 4);while (!QueueEmpty(&q)){printf("%d ", QueueFront(&q));//取隊頭數據QueuePop(&q);}printf("\n");return 0;
}

2.4 隊列的應用場景

1. 消息隊列系統

現代分布式系統的核心組件:

public class MessageQueue {private Queue<Message> queue = new LinkedList<>();public synchronized void enqueue(Message msg) {queue.add(msg);notifyAll(); // 喚醒等待的消費者}public synchronized Message dequeue() throws InterruptedException {while (queue.isEmpty()) {wait(); // 等待消息到達}return queue.remove();}
}
2. 打印機任務調度

多任務打印的公平處理:

class Printer:def __init__(self):self.print_queue = deque()self.current_task = Nonedef add_document(self, document):self.print_queue.append(document)print(f"Added document: {document}")def print_next(self):if self.print_queue:self.current_task = self.print_queue.popleft()print(f"Printing: {self.current_task}")else:print("No documents to print")
3. 廣度優先搜索(BFS)

圖遍歷算法核心:

void BFS(Graph* graph, int start) {bool visited[MAX_VERTICES] = {false};Queue queue;QueueInit(&queue);visited[start] = true;QueuePush(&queue, start);while (!QueueEmpty(&queue)) {int current = QueueFront(&queue);QueuePop(&queue);printf("Visited %d\n", current);// 遍歷所有鄰接節點for (int i = 0; i < graph->vertices; i++) {if (graph->adjMatrix[current][i] && !visited[i]) {visited[i] = true;QueuePush(&queue, i);}}}
}
4. CPU任務調度

操作系統核心調度算法:

struct Task {int pid;int priority;// 其他任務信息
};void scheduleTasks(Queue* highPriority, Queue* normalQueue) {while (!QueueEmpty(highPriority) || !QueueEmpty(normalQueue)) {Task* task;// 優先處理高優先級隊列if (!QueueEmpty(highPriority)) {task = QueueFront(highPriority);QueuePop(highPriority);} else {task = QueueFront(normalQueue);QueuePop(normalQueue);}executeTask(task);// 任務未完成則重新入隊if (!task->completed) {if (task->priority == HIGH) {QueuePush(highPriority, task);} else {QueuePush(normalQueue, task);}}}
}

3. 棧與隊列的對比分析

特性棧 (Stack)隊列 (Queue)
操作原則LIFO (后進先出)FIFO (先進先出)
插入位置棧頂 (Top)隊尾 (Rear)
刪除位置棧頂 (Top)隊頭 (Front)
典型操作Push, PopEnqueue, Dequeue
實現方式數組(更優)/鏈表鏈表(更優)/循環數組
空間復雜度O(n)O(n)
時間復雜度Push/Pop: O(1)Enqueue/Dequeue: O(1)
應用場景函數調用、表達式求值、回溯消息傳遞、BFS、緩沖、調度
抽象層次遞歸結構管道結構

4. 高級變體與應用

4.1 雙端隊列(Deque)

雙端隊列結合了棧和隊列的特性,允許在兩端進行插入和刪除操作:

typedef struct DequeNode {int data;struct DequeNode* prev;struct DequeNode* next;
} DequeNode;typedef struct {DequeNode* front;DequeNode* rear;
} Deque;// 前端插入
void insertFront(Deque* dq, int data) {DequeNode* newNode = createNode(data);if (dq->front == NULL) {dq->front = dq->rear = newNode;} else {newNode->next = dq->front;dq->front->prev = newNode;dq->front = newNode;}
}// 后端刪除
int deleteRear(Deque* dq) {if (dq->rear == NULL) return -1; // 錯誤值DequeNode* temp = dq->rear;int data = temp->data;if (dq->front == dq->rear) {dq->front = dq->rear = NULL;} else {dq->rear = dq->rear->prev;dq->rear->next = NULL;}free(temp);return data;
}

4.2 優先隊列(Priority Queue)

優先隊列是隊列的變體,元素按優先級出隊:

typedef struct {int* heap;       // 堆數組int capacity;    // 最大容量int size;        // 當前大小
} PriorityQueue;void enqueue(PriorityQueue* pq, int value) {if (pq->size == pq->capacity) {// 擴容邏輯}// 將新元素添加到堆尾int i = pq->size++;pq->heap[i] = value;// 上濾操作while (i != 0 && pq->heap[(i-1)/2] > pq->heap[i]) {swap(&pq->heap[i], &pq->heap[(i-1)/2]);i = (i-1)/2;}
}int dequeue(PriorityQueue* pq) {if (pq->size <= 0) return INT_MIN;int root = pq->heap[0];pq->heap[0] = pq->heap[--pq->size];// 下濾操作int i = 0;while (true) {int smallest = i;int left = 2*i + 1;int right = 2*i + 2;if (left < pq->size && pq->heap[left] < pq->heap[smallest])smallest = left;if (right < pq->size && pq->heap[right] < pq->heap[smallest])smallest = right;if (smallest != i) {swap(&pq->heap[i], &pq->heap[smallest]);i = smallest;} else {break;}}return root;
}

5. 總結:選擇合適的數據結構

棧和隊列作為基礎數據結構,在算法設計和系統開發中無處不在:

  1. 選擇棧的場景
    • 需要回溯操作(如撤銷功能)
    • 遞歸算法實現
    • 深度優先搜索(DFS)
    • 語法解析和表達式求值
  2. 選擇隊列的場景
    • 需要公平處理(如任務調度)
    • 廣度優先搜索(BFS)
    • 緩沖區和數據傳輸
    • 消息傳遞系統
  3. 混合使用場景
    • 使用隊列實現棧(需要兩個隊列)
    • 使用棧實現隊列(需要兩個棧)
    • 雙端隊列滿足雙向操作需求
    • 優先隊列處理帶優先級的任務

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/91356.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/91356.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/91356.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Mybatis-2快速入門

學習主線 必學必會屬于優化的東西。 快速入門需求說明 要求&#xff1a;開發一個MyBatis項目&#xff0c;通過MyBatis的方式可以完成對monster表的crud操作 1.創建mybatis數據庫-monster表 主鍵Primary Key默認非空Not null&#xff0c;就省略了 create database mybatis us…

Web基礎 -java操作數據庫

一、JDBCJDBC&#xff1a;&#xff08;Java DataBase Connectivity&#xff09;&#xff0c;就是使用Java語言操作關系型數據庫的一套API。為了使用JDBC操作數據庫&#xff0c;首先&#xff0c;我們需要在pom.xml文件中引入依賴<dependencies><!-- MySQL JDBC driver …

cell2location復現

https://github.com/BayraktarLab/cell2location/issues/348 根據你已下載的本地 wheel 文件&#xff0c;可以通過以下方式修改安裝命令&#xff0c;優先從本地路徑安裝 jaxlib&#xff0c;同時保持其他依賴的安裝方式不變&#xff1a; 解決方案 # 安裝 jax (從遠程 PyPI 源) p…

什么是 npm、Yarn、pnpm? 有什么區別? 分別適應什么場景?

什么是 npm、Yarn、pnpm? 有什么區別? 分別適應什么場景? 在前端開發中&#xff0c;包管理工具扮演著非常重要的角色。它們幫助開發者高效地管理項目的依賴&#xff0c;確保項目中所需的所有第三方庫和工具都能按時安裝&#xff0c;并且兼容版本。npm、Yarn 和 pnpm 是三款…

深度隱匿源IP:高防+群聯AI云防護防繞過實戰

隱蔽性挑戰 黑客常通過以下手段繞過基礎防護&#xff1a; HTTPS證書嗅探&#xff1a;訪問 https://源站IP&#xff0c;通過證書域名匹配暴露真實IP歷史解析記錄追蹤&#xff1a;從DNS數據庫獲取舊A記錄CDN緩存滲透&#xff1a;利用邊緣節點回源漏洞定位源站 三重防護方案 高防I…

如何加快golang編譯速度

跟著我的步驟來&#xff1a;第一步&#xff1a;(點擊edit)第二步&#xff1a;將go tool arguments設置為-p4&#xff0c;初始值設為4&#xff0c; 代表最多同時編譯4個包&#xff08;非文件&#xff09;。電腦性能好時&#xff0c;可設為CPU最大核心數&#xff08;充分利用多核…

瀏覽器自動化方案

B端后臺列表頁自動新增素材方案 我設計了一套完整的瀏覽器自動化方案&#xff0c;使用 Puppeteer 實現B端后臺列表頁的自動新增素材功能。該方案包含數據組織、瀏覽器操作、錯誤處理等完整流程。 一、技術選型 瀏覽器自動化工具&#xff1a;Puppeteer (https://pptr.dev)任務調…

MPPT電路設計

反激的具體計算過程要寫好起碼要一天&#xff0c;所以本次先更MPPT。這章不計算具體參數&#xff0c;只做分析。 目錄 一、電路作用 二、電路設計 采樣電路和輸入電路 主體電路 驅動電路 一、電路作用 MPPT電路是一種廣泛應用于光伏發電、風力發電等新能源系統中的關鍵電…

【基于飛漿訓練車牌識別模型】

基于飛漿訓練車牌識別模型 基于飛漿訓練車牌識別模型 LPRNet&#xff08;License Plate Recognition via Deep Neural Networks&#xff09;是一種輕量級卷積神經網絡&#xff0c;專為端到端車牌識別設計&#xff0c;由Intel IOTG Computer Vision Group的Sergey Zherzdev于201…

No module named ‘sklearn‘

1、運行python數據分析庫時報錯 No module named sklearn2、原因 虛擬環境未安裝 sklearn 庫&#xff08;即 scikit-learn&#xff09;。 3、解決方案 pip install scikit-learn使用國內鏡像源&#xff1a; pip install scikit-learn -i https://mirrors.aliyun.com/pypi/simpl…

XPath注入攻擊詳解:原理、危害與防御

什么是XPath注入&#xff1f; XPath注入&#xff08;XPath Injection&#xff09;是一種針對使用XPath查詢語言的應用程序的安全攻擊技術&#xff0c;類似于SQL注入。當應用程序使用用戶提供的輸入來構造XPath查詢而沒有進行適當的過濾或轉義時&#xff0c;攻擊者可以通過構造惡…

網絡編程(套接字)

目錄 一、套接字 1、套接字的作用 2、關于TCP和UDP協議 1. TCP協議 2. UDP協議 3. 兩者的區別 2、套接字函數 1&#xff09;函數 socket&#xff08;創建套接字同文件描述符&#xff09; 2&#xff09;準備套接字用結構體 1. 套接字的結構體 2. 客戶端的套接字&…

R語言安裝包

# 在安裝過程中指定源地址 install.packages("RCurl", repos "https://mirrors.tuna.tsinghua.edu.cn/CRAN/") # 查看當前鏡像 options()$repos # 設置為中科大鏡像 options("repos" c(CRAN"https://mirrors.ustc.edu.cn/CRAN/")…

微服務引擎 MSE 及云原生 API 網關 2025 年 5 月產品動態

點擊此處&#xff0c;了解微服務引擎 MSE 產品詳情。

性能測試過程中監控linux服務器資源情況

文章目錄1. cpu使用情況&#xff08;1&#xff09;性能瓶頸類型CPU密集型瓶頸??I/O或等待瓶頸?&#xff08;2&#xff09;資源分配與競爭?資源爭用分析?虛擬化環境資源分配?&#xff08;3&#xff09;系統穩定性與異常??異常波動與毛刺??過熱降頻影響?&#xff08;4…

使用defineExpose暴露子組件的屬性和方法、頁面生命周期onLoad和onReady的使用

歡迎來到我的UniApp技術專欄&#xff01;&#x1f389; 在這里&#xff0c;我將與大家分享關于UniApp開發的實用技巧、最佳實踐和項目經驗。 專欄特色&#xff1a; &#x1f4f1; 跨平臺開發一站式解決方案 &#x1f680; 從入門到精通的完整學習路徑 &#x1f4a1; 實戰項目經…

新手必看!VSCodePyCharm 配置 OpenCV 超詳細教程(支持 Python 和 C++ 雙語言)

新手必看&#xff01;VSCode&PyCharm 配置 OpenCV 超詳細教程&#xff08;支持 Python 和 C 雙語言&#xff09; 適用對象&#xff1a;初學者&#xff0c;希望在 VSCode 與 PyCharm 兩款常用 IDE 中&#xff0c;學會配置并使用 OpenCV&#xff0c;分別實現 Python 與 C 環境…

PyTorch深度學習框架入門案例實戰

PyTorch深度學習框架詳解與實戰 1. PyTorch簡介與環境配置 1.1 安裝與導入 # 基礎導入 import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim from torch.utils.data import DataLoader, TensorDataset import numpy as np import…

Spring Boot - Spring Boot 集成 MyBatis 分頁實現 手寫 SQL 分頁

一、準備階段 1、依賴引入 pom.xml <properties>...<postgresql.verison>42.5.6</postgresql.verison><mybatis.version>3.0.1</mybatis.version> </properties><dependencies>...<!-- postgresql 驅動 --><dependency>…

李宏毅《生成式人工智能導論》 | 第9講 AI Agent

文章目錄大模型未來趨勢&#xff1a;以大型語言模型打造的AgentAI Agent運行的可能原理有記憶的ChatGPT大模型未來趨勢&#xff1a;以大型語言模型打造的Agent 人類需要做多步驟的復雜任務&#xff0c;AI可以做到這件事嗎&#xff1f; 如果可以我們將其稱為AI Agent&#xff…