实现AVL树

目录

AVL树概念

AVL树结构

AVL树插入

LL型 - 右单旋

RR型 - 左单旋

LR型 - 左右双旋

RL型 - 右左双旋

插入代码实现

AVL树测试

 附AVL树实现完整代码


AVL树概念

前面的博客介绍了搜索二叉树,二叉搜索树-CSDN博客

在某些特定的情况下,⼆叉搜索树是会退化成单链表的,并且各种操作的效率也会明显的下降,因此我们需要⼀些特别的⼿段保证这个⼆叉搜索树的“平衡”,进⽽保证各种操作的 效率。这就是我们接下来要学习的平衡⼆叉树

为了保证⼆叉搜索树的性能,规定在插⼊和删除结点时,要保证任意结点的左、⼦树⾼度差的绝对值不超过1 ,这样的⼆叉树称为平衡⼆叉树(简称AVL树)。

其中结点左⼦树与右⼦树的⾼度差定义为该结点的平衡因⼦(⼀般是左⼦树的⾼度减去右⼦树的⾼ 度。当然,反过来也是可以的)

由此可⻅,平衡⼆叉树中,每⼀个结点的平衡因⼦只可能是 0/1/-1,如下图所⽰:结点上⽅的数字表⽰平衡因⼦。左图是⼀棵平衡⼆叉树,右图不是⼀棵平衡⼆叉树

AVL树结构

我们采用三叉链的结构实现节点,因为AVL树调平衡的过程需要向上找父节点,因此需要存储父节点的指针信息

template<class K, class V>
struct AVLTreeNode
{//三叉链AVLTreeNode<K, V>* _left;AVLTreeNode<K, V>* _right;AVLTreeNode<K, V>* _parent;pair<K, V> _kv;int _bf; //平衡因子AVLTreeNode(const pair<K, V>& kv):_left(nullptr), _right(nullptr), _parent(nullptr), _kv(kv), _bf(0){}
};template<class K, class V>
class AVLTree
{typedef AVLTreeNode<K, V> Node;
private:Node* _root = nullptr;
};

AVL树插入

在⼆叉搜索树中插⼊新结点之后,插⼊路径的点中,可能存在很多平衡因⼦的绝对值⼤于1的,此时找到距离插⼊结点最近的不平衡的点,以这个点为根的字树就是不平衡子树。如下图:

插⼊之后,会导致三个结点失衡,其中距离最近的 结点为根的⼦树,就是最小不平衡子树。可以发现,仅需让最⼩不平衡⼦树平衡,所有结点就都平衡了,感性认知如下:

1. 本来整棵树就是平衡⼆叉树,如果来了⼀个结点导致失衡,那么失衡结点的平衡因⼦只能是2或者 -2;

2 .当我们把最⼩平衡⼦树调整平衡之后,那么这棵⼦树的⾼度就会减 ,向上传递的过程中,会让 整个路径⾥⾯的平衡因⼦都向0靠近⼀位,原来的-2会变成-1,原来的2会变成1,整棵树就变得平衡了。

而最⼩不平衡⼦树的出现可以细分成4种情况,因此调整策略也会分为4种情况讨论。为了方便叙述, 设最小不平衡子树的根节点为T。

LL型 - 右单旋

 LL 表示:新结点由于插⼊在T结点的左孩⼦(L)的左⼦树(LL)中,从⽽导致失衡。如下图所示:

此时需要将L右旋:

• 将结点L向右上旋转代替结点T作为根结点;

• 将节点T向右下旋转作为结点L的右⼦树的根结点;

• 结点L的原右⼦树(LR)则作为结点T的左⼦树

旋转之后,依旧满⾜平衡⼆叉树的特性:LL < L < LR < T < R

案例:下列AVL树中插⼊1

最⼩不平衡⼦树是以 13 为根的⼦树,引起不平衡的原因是 13的左孩⼦的左⼦树上插⼊⼀个新的结点,因此需要右旋⼀次。右旋的结点为10

代码实现:

void RotateR(Node *parent)
{Node *subL = parent->_left;Node *subLR = subL->_right;parent->_left = subLR;if (subLR)subLR->_parent = parent;Node *parentParent = parent->_parent;subL->_right = parent;parent->_parent = subL;if (_root == parent){_root = subL;subL->_parent = nullptr;}else{if (parentParent->_left == parent){parentParent->_left = subL;}else{parentParent->_right = subL;}subL->_parent = parentParent;}subL->_bf = parent->_bf = 0;
}
RR型 - 左单旋

RR表⽰:新结点由于插⼊在T结点的右孩⼦(R)的右⼦树(RR)中,从⽽导致失衡。如下图所⽰:

此时需要⼀次向左的旋转操作,将R左旋:

• 将结点R向左上旋转代替结点T作为根结点;

• 将节点T向左下旋转作为结点R的左⼦树的根结点;

• 结点R的原左⼦树(RL)则作为结点T的右⼦树。 如下图:

案例:下列AVL树中插⼊64

最⼩不平衡⼦树是以 49 为根的⼦树,引起不平衡的原因是 49 的右孩⼦的右⼦树上插⼊⼀个新的结 点,因此需要左旋⼀次。左旋的结点为59

代码实现

void RotateL(Node *parent)
{Node *subR = parent->_right;Node *subRL = subR->_left;parent->_right = subRL;subR->_left = parent;// 旋转之后整棵子树的根变了, 需要重新链接Node *parentParent = parent->_parent;parent->_parent = subR;if (subRL)subRL->_parent = parent;if (_root == parent){_root = subR;subR->_parent = nullptr;}else{if (parentParent->_left == parent){parentParent->_left = subR;}else{parentParent->_right = subR;}subR->_parent = parentParent;}parent->_bf = subR->_bf = 0;
}
LR型 - 左右双旋

LR表⽰:新结点由于插⼊在T结点的左孩⼦(L)的右⼦树(LR)中,从⽽导致失衡。如下图所⽰:

此时需要两次旋转操作,先将LR左旋,再将LR右旋。

将LR左旋:

• 将结点LR向左上旋转代替结点L作为根结点;

• 将节点L向左下旋转作为结点LR的左⼦树的根结点;

• 结点LR的原左⼦树(LRL)则作为结点L的右⼦树。

将LR右旋:

• 将结点LR向右上旋转代替结点T作为根结点;

• 将节点T向右下旋转作为结点LR的右⼦树的根结点;

• 结点LR的原右⼦树(LRR)则作为结点T的左⼦树。

案例:下列AVL树中插⼊1

最⼩不平衡⼦树是以49为根的⼦树,引起不平衡的原因是49的左孩⼦的右⼦树上插⼊⼀个新的结点,因此需要左旋⼀次,然后右旋⼀次。旋转的结点为45:

void RotateLR(Node *parent)
{Node *subL = parent->_left;Node *subLR = subL->_right;int bf = subLR->_bf; // subLR不可能为nullptr,因为subL的平衡因子是-1RotateL(subL);RotateR(parent);// 3、更新平衡因子if (bf == 1){subLR->_bf = 0;subL->_bf = 0;parent->_bf = -1;}else if (bf == -1){subLR->_bf = 0;subL->_bf = 1;parent->_bf = 0;}else if (bf == 0){subLR->_bf = subL->_bf = parent->_bf = 0;}else{assert(false); // 在旋转前树的平衡因子就有问题}
}
RL型 - 右左双旋

RL表⽰:新结点由于插⼊在T结点的右孩⼦(R)的左⼦树(RL)中,从⽽导致失衡。如下图所⽰:

此时需要两次旋转操作,先将RL右旋,再将RL左旋。将RL右旋:

• 将结点RL向右上旋转代替结点R作为根结点;

• 将节点R向右下旋转作为结点RL的右⼦树的根结点;

• 结点RL的原右⼦树(RLR)则作为结点R的右⼦树。

将RL左旋:

• 将结点RL向左上旋转代替结点T作为根结点;

• 将节点T向左下旋转作为结点RL的左⼦树的根结点;

• 结点RL的原左⼦树(RLL)则作为结点T的右⼦树。

案例:下列AVL树中插⼊52

最⼩不平衡⼦树是以49为根的⼦树,引起不平衡的原因是49的右孩⼦的左⼦树上插⼊⼀个新的结点,因此需要右旋⼀次,然后再左旋⼀次。旋转的结点为55

代码实现

void RotateRL(Node *parent)
{Node *subR = parent->_right;Node *subRL = subR->_left;int bf = subRL->_bf;RotateR(parent->_right);RotateL(parent);if (bf == 0){parent->_bf = subR->_bf = subRL->_bf = 0;}else if (bf == -1){parent->_bf = 1;subRL->_bf = 0;subR->_bf = 0;}else if (bf == 1){parent->_bf = 0;subRL->_bf = 0;subR->_bf = -1;}else{assert(false);}
}
插入代码实现
bool Insert(const pair<K, V> &kv)
{if (_root == nullptr){_root = new Node(kv);return true;}Node *parent = nullptr;Node *cur = _root;while (cur){if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(kv);if (parent->_kv.first < kv.first){parent->_right = cur;cur->_parent = parent;}else{parent->_left = cur;cur->_parent = parent;}while (parent){// 平衡因子的变化if (cur == parent->_left){parent->_bf++;}else{parent->_bf--;}if (parent->_bf == 0) // 之前为-1/1, cur填到了较低的一边,树高不变,不需要继续调整了!{break;}else if (parent->_bf == 1 || parent->_bf == -1) // 之前为0, 当前树高+1, 可能不再平衡了,向上调整!{cur = parent;parent = parent->_parent;}else if (parent->_bf == 2 || parent->_bf == -2) // 失衡了, 需要重新调平衡{if (parent->_bf == 2 && cur->_bf == 1){RotateR(parent);}else if (parent->_bf == -2 && cur->_bf == -1){RotateL(parent);}else if (parent->_bf == 2 && cur->_bf == -1){RotateLR(parent);}else if (parent->_bf == -2 && cur->_bf == 1){RotateRL(parent);}// 1、旋转让这颗子树平衡了// 2、旋转降低了这颗子树的高度,恢复到跟插入前一样的高度,所以对上一层没有影响,不用继续更新break;}else{assert(false);}}return true;
}

● 首先和二叉搜索树一样,先找到合适的插入位置,再进行插入

● 插入后更新当前子树的平衡因子,然后根据平衡因子的特点执行不同的操作

● 如果当前子树的平衡因子是0,说明依旧平衡,不需要调平衡;如果当前子树的平衡因子是1/-1,需要继续向上找最小不平衡子树;如果当前子树的平衡因子是2/-2,说明找到了最小不平衡子树,根据平衡因子的特点,执行不同的旋转操作,只要最小不平衡子树调平衡了,整棵树就平衡了,直接跳出循环即可

AVL树测试

判断是否是平衡二叉树:

public:bool IsBalance(){return _IsBalance(_root);}private:bool _IsBalance(Node* root){if (root == nullptr)return true;int leftHeight = _Height(root->_left);int rightHeight = _Height(root->_right);if (leftHeight - rightHeight != root->_bf){cout << root->_kv.first << "平衡因子异常" << endl;return false;}return abs(leftHeight - rightHeight) < 2&& _IsBalance(root->_left)&& _IsBalance(root->_right);}int _Height(Node* root){if (root == nullptr)return 0;int leftHeight = _Height(root->_left);int rightHeight = _Height(root->_right);return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;}

中序遍历

public:void InOrder(){_InOrder(_root);cout << endl;}
private:void _InOrder(Node* root){if (root == nullptr)return;_InOrder(root->_left);cout << root->_kv.first << " ";_InOrder(root->_right);}

main函数测试

#include <iostream>
#include <assert.h>
using namespace std;#include "AVL.h"void test1()
{int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };AVLTree<int, int> t;for (auto e : a){t.Insert(make_pair(e, e));}t.InOrder();cout << t.IsBalance() << endl;
}void test2()
{int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };AVLTree<int, int> t;for (auto e : a){t.Insert(make_pair(e, e));}t.InOrder();cout << t.IsBalance() << endl;
}#include <vector>
void test3()
{const int N = 30;vector<int> v;v.reserve(N);srand(time(0));for (size_t i = 0; i < N; i++){v.push_back(rand());cout << v.back() << endl;}AVLTree<int, int> t;for (auto e : v){t.Insert(make_pair(e, e));cout << "Insert:" << e << "->" << t.IsBalance() << endl;}cout << t.IsBalance() << endl;
}int main()
{test1();test2();test3();return 0;
}

 附AVL树实现完整代码

#pragma once
#include<assert.h>
#include <iostream>
using namespace std;//AVL树:
//1.本质还是一颗二叉搜索树
//2.增加了平衡因子,任何一颗子树的左右子树高度差绝对值不超过1template<class K, class V>
struct AVLTreeNode
{//三叉链AVLTreeNode<K, V>* _left;AVLTreeNode<K, V>* _right;AVLTreeNode<K, V>* _parent;pair<K, V> _kv;int _bf; //平衡因子AVLTreeNode(const pair<K, V>& kv):_left(nullptr), _right(nullptr), _parent(nullptr), _kv(kv), _bf(0){}
};template<class K, class V>
class AVLTree
{typedef AVLTreeNode<K, V> Node;
public:bool Insert(const pair<K, V>& kv){if (_root == nullptr){_root = new Node(kv);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(kv);if (parent->_kv.first < kv.first){parent->_right = cur;cur->_parent = parent;}else{parent->_left = cur;cur->_parent = parent;}while (parent) {//平衡因子的变化if (cur == parent->_left){parent->_bf++;}else{parent->_bf--;}if (parent->_bf == 0) //之前为-1/1, cur填到了较低的一边,树高不变,不需要继续调整了!{break;}else if (parent->_bf == 1 || parent->_bf == -1) //之前为0, 当前树高+1, 可能不再平衡了,向上调整!{cur = parent;parent = parent->_parent;}else if (parent->_bf == 2 || parent->_bf == -2)  //失衡了, 需要重新调平衡{if (parent->_bf == 2 && cur->_bf == 1) {RotateR(parent);}else if (parent->_bf == -2 && cur->_bf == -1){RotateL(parent);}else if (parent->_bf == 2 && cur->_bf == -1){RotateLR(parent);}else if (parent->_bf == -2 && cur->_bf == 1){RotateRL(parent);}// 1、旋转让这颗子树平衡了// 2、旋转降低了这颗子树的高度,恢复到跟插入前一样的高度,所以对上一层没有影响,不用继续更新break;}else{assert(false);}}return true;}void RotateL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;subR->_left = parent;//旋转之后整棵子树的根变了, 需要重新链接Node* parentParent = parent->_parent;parent->_parent = subR;if (subRL)subRL->_parent = parent;if (_root == parent){_root = subR;subR->_parent = nullptr;}else{if (parentParent->_left == parent){parentParent->_left = subR;}else{parentParent->_right = subR;}subR->_parent = parentParent;}parent->_bf = subR->_bf = 0;}void RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR)subLR->_parent = parent;Node* parentParent = parent->_parent;subL->_right = parent;parent->_parent = subL;if (_root == parent){_root = subL;subL->_parent = nullptr;}else{if (parentParent->_left == parent){parentParent->_left = subL;}else{parentParent->_right = subL;}subL->_parent = parentParent;}subL->_bf = parent->_bf = 0;}void RotateRL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RotateR(parent->_right);RotateL(parent);if(bf == 0){parent->_bf = subR->_bf = subRL->_bf = 0;}else if (bf == -1){parent->_bf = 1;subRL->_bf = 0;subR->_bf = 0;}else if (bf == 1){parent->_bf = 0;subRL->_bf = 0;subR->_bf = -1;}else{assert(false);}}//左右双旋void RotateLR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;int bf = subLR->_bf; //subLR不可能为nullptr,因为subL的平衡因子是-1RotateL(subL);RotateR(parent);//3、更新平衡因子if (bf == 1){subLR->_bf = 0;subL->_bf = 0;parent->_bf = -1;}else if (bf == -1){subLR->_bf = 0;subL->_bf = 1;parent->_bf = 0;}else if (bf == 0){subLR->_bf = subL->_bf = parent->_bf = 0;}else{assert(false); //在旋转前树的平衡因子就有问题}}void InOrder(){_InOrder(_root);cout << endl;}bool IsBalance(){return _IsBalance(_root);}private:bool _IsBalance(Node* root){if (root == nullptr)return true;int leftHeight = _Height(root->_left);int rightHeight = _Height(root->_right);if (leftHeight - rightHeight != root->_bf){cout << root->_kv.first << "平衡因子异常" << endl;return false;}return abs(leftHeight - rightHeight) < 2&& _IsBalance(root->_left)&& _IsBalance(root->_right);}int _Height(Node* root){if (root == nullptr)return 0;int leftHeight = _Height(root->_left);int rightHeight = _Height(root->_right);return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;}void _InOrder(Node* root){if (root == nullptr)return;_InOrder(root->_left);cout << root->_kv.first << " ";_InOrder(root->_right);}
private:Node* _root = nullptr;
};

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

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

相关文章

极客说|微软 Phi 系列小模型和多模态小模型

作者&#xff1a;胡平 - 微软云人工智能高级专家 「极客说」 是一档专注 AI 时代开发者分享的专栏&#xff0c;我们邀请来自微软以及技术社区专家&#xff0c;带来最前沿的技术干货与实践经验。在这里&#xff0c;您将看到深度教程、最佳实践和创新解决方案。关注「极客说」&am…

React+redux项目搭建流程

1.创建项目 create-react-app my-project --template typescript // 创建项目并使用typescript2.去除掉没用的文件夹&#xff0c;只保留部分有用的文件 3.项目配置&#xff1a; 配置项目的icon 配置项目的标题 配置项目的别名等&#xff08;craco.config.ts&…

HTML+CSS+JS制作高仿小米官网网站(内附源码,含6个页面)

一、作品介绍 HTMLCSSJS制作一个高仿小米官网网站&#xff0c;包含首页、商品详情页、确认订单页、订单支付页、收货地址管理页、新增收获地址页等6个静态页面。其中每个页面都包含一个导航栏、一个主要区域和一个底部区域。 二、页面结构 1. 顶部导航栏 包含Logo、主导航菜…

obs directx11

创建逻辑 obs 在windows 下分为Opengl 和 directx 两种渲染模式&#xff0c;默认使用的是directx &#xff0c;兼容性更好&#xff1b; 代码路径&#xff1a; E:\opensrc\obs_studio_src\obs-studio\UI\obs-app.cpp 选择渲染模式 const char* OBSApp::GetRenderModule() con…

QT实现 端口扫描暂停和继续功能 3

上篇QT给端口扫描工程增加线程2-CSDN博客 为按钮pushButton_Stop添加clicked事件&#xff0c;功能为暂停扫描&#xff0c;并在暂停后显示继续按钮&#xff0c;点击继续按钮之后继续扫描 1.更新UI 添加继续按钮 点击转到槽则会自动声明 2. 更新 MainWindow.h 需要新增的部分…

nginx-限流(请求/并发量)

一. 简述&#xff1a; 在做日常的web运维工作中&#xff0c;难免会遇到服务器流量异常&#xff0c;负载过大等情况。恶意攻击访问/爬虫等非正常性请求&#xff0c;会带来带宽的浪费&#xff0c;服务器压力增大&#xff0c;影响业务质量。 二. 限流方案&#xff1a; 对于这种情…

分布式ID生成-雪花算法实现无状态

雪花算法这里不再赘述&#xff0c;其缺点是有状态&#xff08;多副本隔离时&#xff0c;依赖手动配置workId和datacenterId&#xff09;&#xff0c;代码如下&#xff1a; /*** 雪花算法ID生成器*/ public class SnowflakeIdWorker {/*** 开始时间截 (2017-01-01)*/private st…

Edge SCDN高效防护与智能加速

当今数字化时代&#xff0c;网络安全和内容分发效率已成为企业业务发展的关键因素。酷盾安全推出了Edge SCDN解决方案&#xff0c;为企业提供全方位的安全防护和高效的内容分发服务。 一、卓越的安全防护能力 1.DDoS攻击的精准防御&#xff1a;Edge SCDN具备强大的DDoS攻击检测…

在vscode上

第一步 安装插件 &#xff08;1&#xff09;从菜单处打开vscode&#xff0c;之后点击左侧“拓展”&#xff0c;在搜索栏输入“platform”&#xff0c;安装这个插件。 注&#xff1a;安装过程可能会慢一点&#xff0c;可以尝试连接自己的热点 &#xff08;2&#xff09;安装完…

产品心、用户脑、押重注......解读vivo穿越周期之道

出品 | 何玺 排版 | 叶媛 国内科技企业中&#xff0c;vivo绝对算个“异类”。给人以平和谦逊、稳健踏实的印象&#xff0c;却极具实力&#xff01; 回望vivo发展历程&#xff0c;这家拥有近30年历史的超大型全球化产业科技生态型公司&#xff0c;从功能机到智能机一路走来&am…

jenkins入门4 --window执行execute shell

1、启动关闭jenkins 在Windows环境下&#xff0c;如果你需要关闭Jenkins服务&#xff0c;可以通过以下几种方式&#xff1a; 1、使用Windows服务管理器&#xff1a; 打开“运行”对话框&#xff08;Win R&#xff09;&#xff0c;输入services.msc&#xff0c;然后回车。 在服…

矩阵碰一碰发视频源码搭建全解析,支持OEM

在数字化营销与互动体验需求日益增长的当下&#xff0c;矩阵碰一碰发视频功能以其独特的交互性和高效的信息传播能力&#xff0c;正逐渐成为吸引用户、提升品牌影响力的有力工具。本文将深入探讨如何搭建矩阵碰一碰发视频的源码&#xff0c;帮助开发者实现这一创新功能。 一、技…

软件确认测试和验收测试有什么区别?

在当今快速发展的软件行业中&#xff0c;软件确认测试与验收测试是软件产品生产周期中的重要步骤&#xff0c;但很多人容易混淆&#xff0c;那么这两者之间究竟有什么区别呢? 软件确认测试是一个旨在确保软件产品符合用户需求规格的过程。它对软件的功能、性能和可用性进行深…

cat命令详解

cat 是 Linux/Unix 中的一个非常常用的命令&#xff0c;主要用于 连接 文件并显示文件内容。它的名称来源于 concatenate&#xff08;连接&#xff09;&#xff0c;不仅可以查看文件内容&#xff0c;还能将多个文件合并为一个文件&#xff0c;或用作其他数据流操作。 以下是对 …

[sdx12] Qualcomm SDX12查看基线版本

about.html文件 Build部分 Product SDX12.LE.1.0-00263-NBOOT.NEFS.PROD-1.90789.1 Distribution SDX12.LE.1.0|AMSS|Standard|OEM: Build Components部分 从以上截图可以看到以下模块的版本号及格式 BOOT 基线版本号 BOOT.BF.3.1.c3-00010-SDX12AAAAANAZB-1 Distr…

基于CLIP和DINOv2实现图像相似性方面的比较

概述 在人工智能领域&#xff0c;CLIP和DINOv2是计算机视觉领域的两大巨头。CLIP彻底改变了图像理解&#xff0c;而DINOv2为自监督学习带来了新的方法。 在本文中&#xff0c;我们将踏上一段旅程&#xff0c;揭示定义CLIP和DINOv2的优势和微妙之处。我们的目标是发现这些模型…

LS1046 XFI网口接近10Gbps

硬件平台&#xff1a; CPU LS1046A 1.8GHZ 软件平台&#xff1a; LINUX 4.19.32 BUILDROOT 测试软件&#xff1a; ipferf 整个过程比较曲折&#xff0c;网口默认不能达到这个速度&#xff0c;只有2Gbps以内。需要FMC配置后才能达到9.4Gbps。

一则问答:211集成电路专业,转互联网还是FPGA?

问&#xff1a; 我于2016年毕业于西安电子科技大学集成电路设计与集成系统专业。毕业后&#xff0c;我在一家不知名私企从事PCB绘制和单片机调试工作&#xff0c;持续了一年半。之后&#xff0c;我受律师职业光鲜外表的吸引&#xff0c;尝试了两年的司法考试&#xff0c;但未能…

嵌入式linux系统中QT信号与槽实现

第一:Qt中信号与槽简介 信号与槽是Qt编程的基础。因为有了信号与槽的编程机制,在Qt中处理界面各个组件的交互操作时变得更加直观和简单。 槽函数与一般的函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行。 案例操作与实现: #ifndef …

Java Web开发进阶——Spring Boot基础

Spring Boot是基于Spring框架的新一代开发框架&#xff0c;旨在通过自动化配置和简化的开发方式提升生产效率。它将复杂的配置抽象化&#xff0c;让开发者专注于业务逻辑实现&#xff0c;而无需关注繁琐的基础配置。 1. Spring Boot简介与优势 Spring Boot 是 Spring 家族中的…