Day25 栈 队列 二叉树

day25 栈 队列 二叉树


使用栈计算表达式的值

概述

通过两个栈(数值栈和符号栈)实现中缀表达式求值。算法核心是:

  • 遇到数字时,累加并入数值栈;
  • 遇到运算符时,比较其与符号栈顶运算符的优先级:
    • 若当前运算符优先级更高,则直接入栈;
    • 否则,不断弹出符号栈顶运算符与两个数值进行计算,结果重新压入数值栈,直到满足入栈条件。
  • 表达式结束后,处理剩余符号栈中的运算符。

目标表达式示例:20*3+5,预期结果为 65


栈结构定义(链式栈)
#ifndef _LINKSTACK_H_
#define _LINKSTACK_H_// 定义栈中存储的数据类型,可存放数字或字符(运算符)
typedef struct 
{int num;     // 用于存储操作数char sym;    // 用于存储运算符
} DATATYPE;// 链栈节点结构
typedef struct _linkstacknode
{DATATYPE data;                    // 当前节点数据struct _linkstacknode *next;      // 指向下一个节点
} LinkStackNode;// 链栈整体结构
typedef struct 
{LinkStackNode* top;   // 栈顶指针int clen;             // 当前栈中元素个数
} LinkStack;// 函数声明
LinkStack* CreateLinkStack();                    // 创建空栈
int PushLinkStack(LinkStack* ls, DATATYPE* data); // 元素入栈
int PopLinkStack(LinkStack* ls);                 // 栈顶元素出栈
DATATYPE* GetTopLinkStack(LinkStack* ls);        // 获取栈顶元素(不弹出)
int IsEmptyLinkStack(LinkStack* ls);             // 判断栈是否为空
int GetSizeLinkStack(LinkStack* ls);             // 获取栈中元素个数
int DestroyLinkStack(LinkStack*);                // 销毁整个栈(释放内存)#endif // !_LINKSTACK_H_

说明:该头文件定义了一个通用链式栈,支持存储整数和字符类型数据,适用于数值栈和符号栈。


链栈实现(LinkStack.c)
#include "LinkStack.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>/*** 创建一个新的链栈* @return 成功返回栈指针,失败返回 NULL*/
LinkStack* CreateLinkStack()
{LinkStack* ls = malloc(sizeof(LinkStack));  // 分配栈控制块内存if (NULL == ls){perror("CreateLinkStack malloc error\n");return NULL;}ls->top = NULL;   // 初始化栈顶为空ls->clen = 0;     // 初始元素个数为 0return ls;
}/*** 元素入栈(头插法)* @param ls 待操作的栈* @param data 要入栈的数据(指针)* @return 0 成功,非 0 失败*/
int PushLinkStack(LinkStack* ls, DATATYPE* data)
{LinkStackNode* newnode = malloc(sizeof(LinkStackNode));if (NULL == newnode){perror("PushLinkStack malloc error\n");return 1;}memcpy(&newnode->data, data, sizeof(DATATYPE));  // 复制数据newnode->next = ls->top;                         // 新节点指向原栈顶ls->top = newnode;                               // 更新栈顶ls->clen++;                                      // 元素个数加一return 0;
}/*** 出栈操作(头删法)* @param ls 待操作的栈* @return 0 成功,非 0 失败(栈空)*/
int PopLinkStack(LinkStack* ls)
{if (IsEmptyLinkStack(ls)){printf("linkstack is empty\n");return 1;}LinkStackNode* tmp = ls->top;         // 临时保存栈顶节点ls->top = ls->top->next;              // 栈顶下移free(tmp);                            // 释放原栈顶节点ls->clen--;                           // 元素个数减一return 0;
}/*** 获取栈顶元素(不弹出)* @param ls 待操作的栈* @return 指向栈顶数据的指针,栈空时返回 NULL*/
DATATYPE* GetTopLinkStack(LinkStack* ls)
{if (IsEmptyLinkStack(ls)){return NULL;}return &ls->top->data;  // 返回栈顶数据地址
}/*** 判断栈是否为空* @param ls 待检查的栈* @return 1 表示空,0 表示非空*/
int IsEmptyLinkStack(LinkStack* ls)
{return 0 == ls->clen;
}/*** 获取栈中元素个数* @param ls 待查询的栈* @return 元素个数*/
int GetSizeLinkStack(LinkStack* ls)
{return ls->clen;
}/*** 销毁整个链栈(释放所有节点及控制块)* @param ls 要销毁的栈* @return 0(固定返回值)*/
int DestroyLinkStack(LinkStack* ls)
{while (!IsEmptyLinkStack(ls)){PopLinkStack(ls);  // 循环出栈,自动释放节点}free(ls);  // 释放栈控制块return 0;
}

表达式求值主程序(main.c)
#include <stdio.h>
#include <string.h>
#include "LinkStack.h"int num = 0;  // 用于临时存储正在解析的数字/*** 将字符数字累加到全局变量 num 中* @param c 当前字符('0'-'9')*/
void get_num(char c)
{num = num * 10 + c - '0';  // 构造多位整数
}/*** 获取运算符优先级* @param c 运算符字符* @return 优先级:+,- 为 1;*,/ 为 2;其他为 0*/
int get_priority(char c)
{switch (c){case '+':case '-':return 1;case '*':case '/':return 2;default:return 0;}
}/*** 执行两个数之间的基本运算* @param num1 第一个操作数* @param num2 第二个操作数* @param c 运算符* @return 计算结果*/
int get_result(int num1, int num2, char c)
{switch (c){case '+':return num1 + num2;case '-':return num1 - num2;case '*':return num1 * num2;case '/':return num1 / num2;}return 0;  // 默认返回值(理论上不会执行)
}/*** 主函数:计算中缀表达式 "20*3+5"*/
int main(int argc, char** argv)
{char* express = "20*3+5";                    // 输入表达式LinkStack* ls_num = CreateLinkStack();       // 数值栈LinkStack* ls_sym = CreateLinkStack();       // 符号栈char* tmp = express;                         // 遍历指针DATATYPE* top;                               // 临时指针DATATYPE data;                               // 临时数据变量while (*tmp){bzero(&data, sizeof(data));  // 清空临时数据// 处理数字字符if (*tmp >= '0' && *tmp <= '9'){get_num(*tmp);tmp++;continue;}// 遇到运算符前,将已解析的数字压入数值栈data.num = num;num = 0;PushLinkStack(ls_num, &data);// 处理当前运算符,与符号栈顶比较优先级while (1){top = GetTopLinkStack(ls_sym);// 条件1:符号栈为空,直接入栈// 条件2:当前运算符优先级高于栈顶,直接入栈if (IsEmptyLinkStack(ls_sym) ||(top != NULL && get_priority(top->sym) < get_priority(*tmp))){bzero(&data, sizeof(data));data.sym = *tmp;PushLinkStack(ls_sym, &data);break;}else{// 否则:弹出两个数值和一个运算符进行计算top = GetTopLinkStack(ls_num);int num2 = top->num;PopLinkStack(ls_num);top = GetTopLinkStack(ls_num);int num1 = top->num;PopLinkStack(ls_num);top = GetTopLinkStack(ls_sym);char op = top->sym;PopLinkStack(ls_sym);int result = get_result(num1, num2, op);bzero(&data, sizeof(data));data.num = result;PushLinkStack(ls_num, &data);  // 结果压回数值栈}}tmp++;}// 处理最后一个数字(循环外)data.num = num;num = 0;PushLinkStack(ls_num, &data);// 处理剩余符号栈中的运算符(从左到右)while (!IsEmptyLinkStack(ls_sym)){top = GetTopLinkStack(ls_num);int num2 = top->num;PopLinkStack(ls_num);top = GetTopLinkStack(ls_num);int num1 = top->num;PopLinkStack(ls_num);top = GetTopLinkStack(ls_sym);char op = top->sym;PopLinkStack(ls_sym);int result = get_result(num1, num2, op);bzero(&data, sizeof(data));data.num = result;PushLinkStack(ls_num, &data);}// 最终结果在数值栈顶top = GetTopLinkStack(ls_num);int result = top->num;PopLinkStack(ls_num);printf("result %d\n", result);  // 输出结果// 释放资源DestroyLinkStack(ls_num);DestroyLinkStack(ls_sym);return 0;
}

理想运行结果

result 65

说明:表达式 20*3+5 按照优先级先算乘法 20*3=60,再加 5,最终得 65


队列

概念与特性
  • 定义:只允许在一端(队尾)插入,另一端(队头)删除的线性表。
  • 核心特性先进先出(FIFO)。
  • 应用场景:缓冲区(解决生产者与消费者速度不匹配问题)。
  • 主要类型
    • 顺序队列
    • 循环队列(避免假溢出)
常用操作
  • 入队(EnterSeqQue):队尾插入
  • 出队(QuitSeqQue):队头删除
  • 获取队头元素(GetHeadSeqQue
  • 判空(IsEmptySeqQue)、判满(IsFullSeqQue

循环队列结构定义(seqque.h)
#ifndef __SEQQUE__H__
#define __SEQQUE__H__typedef int DATATYPE;  // 数据类型别名/*** 循环队列结构体* array: 存储数据的数组* head:  队头索引(指向第一个元素)* tail:  队尾“下一个空位”索引* tlen:  数组总长度*/
typedef struct
{DATATYPE* array;int head;int tail;int tlen;
} SeqQue;// 函数声明
SeqQue* CreateSeqQue(int len);               // 创建队列
int EnterSeqQue(SeqQue* sq, DATATYPE* data); // 入队
int QuitSeqQue(SeqQue* sq);                  // 出队
DATATYPE* GetHeadSeqQue(SeqQue* sq);         // 获取队头元素
int IsEmptySeqQue(SeqQue* sq);               // 判断空
int IsFullSeqQue(SeqQue* sq);                // 判断满
int DestroySeqQue(SeqQue* sq);               // 销毁队列#endif  // !__SEQQUE__H__

循环队列实现(seqque.c)
#include "seqque.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>/*** 创建长度为 len 的循环队列* @param len 队列容量(实际可存 len-1 个元素)* @return 成功返回队列指针,失败返回 NULL*/
SeqQue* CreateSeqQue(int len)
{SeqQue* sq = malloc(sizeof(SeqQue));if (NULL == sq){perror("CreateSeqQue malloc");return NULL;}sq->array = malloc(sizeof(DATATYPE) * len);if (NULL == sq->array){perror("CreateSeqQue malloc2");free(sq);return NULL;}sq->head = 0;sq->tail = 0;sq->tlen = len;return sq;
}/*** 元素入队(队尾)* @param sq 队列* @param data 要插入的数据* @return 0 成功,1 失败(队满)*/
int EnterSeqQue(SeqQue* sq, DATATYPE* data)
{if (IsFullSeqQue(sq)){printf("queue is full\n");return 1;}memcpy(&sq->array[sq->tail], data, sizeof(DATATYPE));sq->tail = (sq->tail + 1) % sq->tlen;  // 循环移动return 0;
}/*** 元素出队(队头)* @param sq 队列* @return 0 成功,1 失败(队空)*/
int QuitSeqQue(SeqQue* sq)
{if (IsEmptySeqQue(sq)){printf("queue is empty\n");return 1;}sq->head = (sq->head + 1) % sq->tlen;  // 循环移动return 0;
}/*** 获取队头元素地址(不删除)* @param sq 队列* @return 指向队头元素的指针*/
DATATYPE* GetHeadSeqQue(SeqQue* sq)
{return &sq->array[sq->head];
}/*** 判断队列是否为空* @param sq 队列* @return 1 为空,0 非空*/
int IsEmptySeqQue(SeqQue* sq)
{return sq->head == sq->tail;
}/*** 判断队列是否为满* @param sq 队列* @return 1 为满,0 非满*/
int IsFullSeqQue(SeqQue* sq)
{return (sq->tail + 1) % sq->tlen == sq->head;
}/*** 销毁队列(释放内存)* @param sq 队列* @return 0*/
int DestroySeqQue(SeqQue* sq)
{free(sq->array);free(sq);return 0;
}

队列测试程序(main.c)
#include <stdio.h>
#include "seqque.h"int main(int argc, char** argv)
{SeqQue* sq = CreateSeqQue(10);  // 创建容量为 10 的队列(最多存 9 个)int i = 0;for (i = 0; i < 10; i++){EnterSeqQue(sq, &i);  // 0~9 依次入队}// 第10次入队会失败,打印 "queue is full"i = 0;while (!IsEmptySeqQue(sq)){DATATYPE* tmp = GetHeadSeqQue(sq);printf("%d %d\n", i++, *tmp);  // 打印序号和值QuitSeqQue(sq);                // 出队}// 实际输出 0~8,共 9 个数(因队列满,最后一个未入)DestroySeqQue(sq);return 0;
}

理想运行结果

0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8

说明:循环队列容量为 10,但最多只能存 9 个元素(tail+1 == head 判满),因此 i=9 时入队失败。


树与二叉树核心要点总结

一、树的基本概念
  • 定义:由 n(n ≥ 0)个结点组成的有限集合。n = 0 时为空树。
  • 根结点:有且仅有一个根结点(无前驱)。
  • 子树:n > 1 时,其余结点可划分为 m 个互不相交的子树,每棵子树也是树。
  • 结点度数
    • 度:结点拥有的子树个数。
    • 叶结点(终端结点):度为 0。
    • 分支结点(非终端结点):度不为 0。
  • 树的度:树中所有结点的最大度数。
  • 深度/高度:从根开始定义,根为第 1 层,逐层递增。
  • 存储结构:顺序存储、链式存储。
二、二叉树的基本概念
  • 定义:n 个结点的有限集合,为空树或由根结点 + 左子树 + 右子树(互不相交)组成。
  • 特点
    • 每个结点最多有两个子树。
    • 左右子树有序,不可颠倒。
    • 单子树必须明确是左或右。
三、特殊二叉树
  • 斜树
    • 左斜树:所有结点仅有左子树。
    • 右斜树:所有结点仅有右子树。
  • 满二叉树:所有分支结点都有左右子树,且所有叶子在同一层。
  • 完全二叉树:按层序编号后,与同深度满二叉树对应位置完全一致。
四、二叉树重要性质
  1. 第 i 层最多有 2i−12^{i-1}2i1 个结点(i ≥ 1)。
  2. 深度为 k 的二叉树最多有 2k−12^k - 12k1 个结点(k ≥ 1)。
  3. 任意二叉树中,叶子结点数 n0=n2+1n_0 = n_2 + 1n0=n2+1n2n_2n2 为度为 2 的结点数)。
  4. n 个结点的完全二叉树深度为 ⌊log⁡2n⌋+1\lfloor \log_2 n \rfloor + 1log2n+1
五、二叉树遍历方式
  • 前序遍历:根 → 左 → 右
  • 中序遍历:左 → 根 → 右
  • 后序遍历:左 → 右 → 根
  • 层序遍历:按层次从上到下、从左到右(广度优先)

二叉树构建与遍历代码实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>typedef char DATATYPE;  // 数据类型为字符// 二叉树结点结构
typedef struct _treenode
{DATATYPE data;                    // 存储数据struct _treenode* left;           // 左孩子指针struct _treenode* right;          // 右孩子指针
} Treenode;// 先序扩展序列(# 表示空节点),用于重建树
char data[] = "abd##eh###cf#i##g##";
int idx = 0;  // 全局索引,用于遍历 data 数组/*** 根据扩展先序序列构建二叉树* @param root 当前子树根节点的双重指针*/
void CreateTree(Treenode** root)
{char c = data[idx++];  // 读取当前字符if ('#' == c){*root = NULL;  // 空节点}else{*root = malloc(sizeof(Treenode));if (NULL == *root){perror("CreateTree malloc error\n");return;}(*root)->data = c;                   // 填充数据CreateTree(&(*root)->left);          // 递归构建左子树CreateTree(&(*root)->right);         // 递归构建右子树}
}/*** 前序遍历:根 → 左 → 右*/
void PreOrrderTravel(Treenode* root)
{if (NULL == root) return;printf("%c", root->data);PreOrrderTravel(root->left);PreOrrderTravel(root->right);
}/*** 中序遍历:左 → 根 → 右*/
void MidOrrderTravel(Treenode* root)
{if (NULL == root) return;MidOrrderTravel(root->left);printf("%c", root->data);MidOrrderTravel(root->right);
}/*** 后序遍历:左 → 右 → 根*/
void PosOrderTravel(Treenode* root)
{if (NULL == root) return;PosOrderTravel(root->left);PosOrderTravel(root->right);printf("%c", root->data);
}/*** 销毁二叉树(后序释放)*/
void DestroyTree(Treenode* root)
{if (NULL == root) return;DestroyTree(root->left);DestroyTree(root->right);free(root);
}

理想运行结果(调用三种遍历):

  • PreOrrderTravel: abdehcfgi
  • MidOrrderTravel: dbehafcig
  • PosOrderTravel: dhebfigca

赫夫曼树与赫夫曼编码

赫夫曼算法构造步骤
  1. 给定 n 个权值 {w1,w2,...,wn}\{w_1, w_2, ..., w_n\}{w1,w2,...,wn},构造 n 棵仅含一个根结点的二叉树,形成集合 FFF
  2. 从 F 中选出两棵根结点权值最小的树作为左右子树,构造新二叉树,新根权值为两子树根权值之和。
  3. 将这两棵树从 F 中删除,新树加入 F。
  4. 重复 2~3,直到 F 中只剩一棵树,即为赫夫曼树。
赫夫曼编码规则
  • 以字符集 {d1,d2,...,dn}\{d_1, d_2, ..., d_n\}{d1,d2,...,dn} 为叶子结点,频率 {w1,w2,...,wn}\{w_1, w_2, ..., w_n\}{w1,w2,...,wn} 为权值构造赫夫曼树。
  • 规定:左分支为 0,右分支为 1
  • 从根到叶子的路径上 0/1 序列即为该字符的赫夫曼编码(前缀编码,无歧义)。

特点:带权路径长度最短,实现最优编码。


回顾总结

  • 队列:受限线性表,一端插入(队尾),一端删除(队头),遵循 FIFO 原则;常用于缓冲。
    • 循环队列判空:head == tail
    • 判满:(tail + 1) % len == head
  • :n 个结点的有限集合,有唯一根,其余为子树;包含根、叶、分支结点。
  • 二叉树:度不超过 2 的有序树。
    • 遍历方式:
      • 前序:根左右
      • 中序:左根右
      • 后序:左右根
      • 层序:广度优先

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

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

相关文章

阿里云RDS MySQL数据归档全攻略:方案选择指南

引言在日常数据库管理中&#xff0c;数据归档是必不可少的重要环节。随着业务数据的不断增长&#xff0c;将历史数据从生产数据库迁移到更经济的存储方案中&#xff0c;不仅可以降低存储成本&#xff0c;还能提升数据库性能。阿里云提供了丰富的数据归档解决方案&#xff0c;本…

线性回归学习

一、线性回归简介核心思想&#xff1a;线性回归是一种通过属性的线性组合来做预测的模型。它的目标很明确&#xff0c;就是找到一条合适的直线、平面或者更高维度的超平面&#xff0c;让预测出来的值和实际真实值之间的差距尽可能小。比如在预测房屋价格时&#xff0c;就可以根…

如何使用 DeepSeek 助力工作:全面指南​

一、引言​1.1 DeepSeek 简介​DeepSeek 的定位与目标概述​核心技术亮点&#xff08;大语言模型、多模态能力、AI Agent 框架&#xff09;​1.2 工作场景中应用 AI 的趋势​AI 对职场效率提升的重要性​DeepSeek 在众多 AI 工具中的独特地位​二、DeepSeek 基础功能介绍​2.1 …

车载诊断架构 --- EOL引起关于DTC检测开始条件的思考

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…

JCTools Spmc 单生产者-多消费者的无锁并发有界队列

SpmcArrayQueue 是 JCTools 中为 单生产者-多消费者&#xff08;Single-Producer-Multi-Consumer&#xff09; 场景设计的有界队列。与 SPSC 模型相比&#xff0c;SPMC 的复杂性主要体现在消费者侧&#xff0c;因为多个消费者线程需要以线程安全的方式竞争消费同一个队列中的元…

SpringAI1.0.1实战教程:避坑指南25年8月最新版

Spring AI 1.0.1 使用教程 项目简介 作为一个Java的开发者 听到Java也有ai框架了 很高兴~~~ 本来想学一下SpringAI但是网上卖课的一大堆&#xff0c;并且大部分课程都是五月的&#xff0c;到2025年的8月份&#xff0c;SpringAI的版本做了很多更新&#xff0c;所以我本人参考…

Maven架构的依赖管理和项目构建

​​​​​​什么是依赖管理对第三方依赖包的管理&#xff0c;可以连接互联网下载项目所需第三方jar包。对自己开发的模块的管理&#xff0c;可以像引用第三方依赖包一样引用自己项目的依赖包。Maven的依赖管理方式和传统方式有什么区别传统方式&#xff1a;从官网手动下载jar包…

微信小程序开发(一):使用开发者工具创建天气预报项目

Hi&#xff0c;我是前端人类学&#xff08;之前叫布兰妮甜&#xff09;&#xff01; 从今天开始&#xff0c;我将开启一个全新的微信小程序开发系列教程&#xff0c;通过实际项目带大家系统学习小程序开发。作为系列的第一篇文章&#xff0c;我们将从最基础的环境搭建开始&…

【链表 - LeetCode】24. 两两交换链表中的节点

24. 两两交换链表中的节点 - 力扣&#xff08;LeetCode&#xff09; 题解&#xff1a; - 迭代 首先是直接遍历的做法&#xff0c;这里注意调整指针指向的顺序。 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* List…

爬虫基础学习-链接协议分析,熟悉相关函数

1、urlparse&#xff1a;&#xff08;python标准库中的一个模块&#xff0c;解析和操作url&#xff09;标准的url链接格式&#xff1a;scheme://netloc/path;params?query#fragmentscheme&#xff08;协议&#xff09; http or https netloc&#xff08;网络位置&#xff09; …

kkfileview预览Excel文件去掉左上角的跳转HTML预览、打印按钮

上篇说了使用nginx代理kkfile预览文件&#xff0c;但是又发现个新问题&#xff0c;预览其他文件时都正常&#xff0c;但是预览.xlsx格式的时候&#xff0c;在左上角会有【跳转HTML预览】【打印】两个按钮&#xff0c;如下所示&#xff1a;这篇就来说一下如何去掉。首先这个跟kk…

阿里开源新AI code工具:qoder功能介绍

下载地址&#xff1a; https://qoder.com/ 文档地址&#xff1a; https://docs.qoder.com/ 文章目录1. AI 编码发展趋势2. 真实世界软件开发的挑战3. 我们的方法3.1. 透明度3.1.1. 知识可见性3.1.2. 执行透明度3.2. 增强上下文工程3.3. 规范驱动与任务委托3.3.1. 聊天模式&…

什么是短视频矩阵系统企业立项功能源码开发,支持OEM

短视频矩阵系统企业立项功能源码开发解析在短视频行业蓬勃发展的当下&#xff0c;企业纷纷布局短视频矩阵&#xff0c;以实现多平台、多账号的协同运营。而企业立项作为短视频矩阵项目启动的关键环节&#xff0c;其高效、规范的管理直接影响项目的推进效率与成果。为此&#xf…

当GitHub宕机时,我们如何协作?

问题背景与影响 GitHub作为主流代码托管平台的依赖现状宕机对分布式团队、CI/CD流水线、紧急修复的影响案例其他类似平台&#xff08;GitLab、Bitbucket&#xff09;的潜在连带风险 本地与离线协作方案 利用Git分布式特性&#xff1a;本地仓库继续提交&#xff0c;恢复后同步搭…

【会议跟踪】Model-Based Systems Engineering (MBSE) in Practice 2025

会议主旨与议题 会议宣传链接:https://www.sei.cmu.edu/events/mbse-in-practice/ 本次会议将于2025年8月21日位美国弗吉尼亚州阿灵顿(五角大楼所在地)举行。本次会议主旨为 MBSE in Practice: Bridging the Gap Between Theory and Success(2025)。随着软件定义系统日趋…

浏览器的渲染流程:从 HTML 到屏幕显示

在我们日常使用浏览器浏览网页时&#xff0c;往往忽略了浏览器背后复杂的渲染过程。从输入 URL 到页面最终显示在屏幕上&#xff0c;浏览器需要经过一系列精心设计的步骤。 浏览器渲染的整体流程浏览器的渲染流程可以大致分为两个主要部分&#xff1a;网络 和 渲染。当用户在地…

FastMCP 客户端服务器通信示例:从入门到实战(STDIO 传输)

引言 在现代分布式系统和AI应用中&#xff0c;模型上下文协议&#xff08;MCP&#xff09;扮演着重要角色&#xff0c;它负责协调客户端与服务器之间的通信&#xff0c;尤其是在需要频繁交互的场景中。本文将介绍如何使用FastMCP库快速实现客户端与服务器之间的通信&#xff0c…

宝可梦肉鸽 PC/手机双端 多种存档 全闪光 无限金币 全宝可梦解锁 免安装中文版

网盘链接&#xff1a; 宝可梦肉鸽 免安装中文版 名称&#xff1a;宝可梦肉鸽 PC/手机双端 多种存档 全闪光 无限金币 全宝可梦解锁 免安装中文版 描述&#xff1a;宝可梦肉鸽修改版是一款非常受欢迎的口袋妖怪系列&#xff0c;游戏拥有许多独特的妖怪和玩法。在游戏中&#…

Linux 下的网络编程

1、目的实现不同主机上进程间的通信。2、问题主机与主机之间在物理层面必须互联互通。进程与进程在软件层面必须互联互通。IP地址&#xff1a;计算机的软件地址&#xff0c;用来标识计算机设备。MAC地址&#xff1a;计算机的硬件地址&#xff08;固定&#xff09;。网络的端口号…

Go语言在边缘计算中的网络编程实践:从入门到精通

一、引言 在数字化浪潮席卷全球的今天&#xff0c;边缘计算如同一股清流&#xff0c;正在重新定义我们对网络架构的理解。想象一下&#xff0c;当你在自动驾驶汽车中需要毫秒级响应&#xff0c;或者在偏远工厂中需要实时处理传感器数据时&#xff0c;传统的云计算模式就像是&qu…