当前位置: 首页 > news >正文

【数据结构】第八节:链式二叉树

个人主页: NiKo

数据结构专栏: 数据结构与算法

 源码获取:Gitee——数据结构

一、二叉树的链式结构

typedef int BTDataType;
typedef struct BinaryTreeNode {BTDataType data;struct BinaryTreeNode* left;  // 左子树根节点struct BinaryTreeNode* right; // 右子树根节点
}BTNode;

        每一颗二叉树都是由左子树、根、右子树构成的,在实现二叉树的链式结构时我们也要将二叉树看作这三部分。

二、二叉树的遍历

学习二叉树结构,最简单的方式就是遍历。所谓 二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的结点进行相应的操作,并且每个结点只操作一次。访问结点所做的操作依赖于具体的应用问题。 遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。 遍历是通过递归实现的。
按照规则,二叉树的遍历有: 前序/中序/后序的递归结构遍历
  1. 前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点的操作发生在遍历其左右子树之前。
  2. 中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中(间)。
  3. 后序遍历(Postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后。

图1-1

已经创建的二叉树如图1-1。

1.前序遍历 

        前序遍历访问根结点的操作发生在遍历其左右子树之前,访问顺序为根、左子树、右子树。根据概念,在访问二叉树时,需要将二叉树看作根、左子树、右子树,左右子树又可以分为根、左子树、右子树,直到访问的节点为空(NULL)即证明访问到了二叉树的最底层。

        如图1-1所示,首先访问的根是1,这是第一层递归,然后递归访问此根的左子树,根节点为2,这是第二层递归;而以2为根的子树又可以分为以3为根的左子树、NULL,访问完根节点2后应继续递归访问左子树根节点3,这是第三层递归;此时根节点3的左子树为空,右子树为空无法再递归下去,以3为根节点的子树访问完毕,结束第三层递归返回到第二层递归并访问根节点2的右子树,右子树为空无法递归,以2为根节点的子树访问完毕结束第二层递归返回到第一层递归并访问根节点1的右子树,同理根据遍历左子树的方式遍历右子树。

void PrevOrder(BTNode* root) {// 不符合递归条件,结束此层递归if (root == NULL) {printf("N ");return;}printf("%d ", root->data); // 访问根节点PrevOrder(root->left);     // 访问根节点的左子树PrevOrder(root->right);    // 访问根节点的右子树
}

        根据代码前序遍历的结果示意图:

 

2.中序遍历

        中序遍历访问根结点的操作发生在遍历其左右子树之中(间)。访问顺序为左子树、根、右子树。同前序遍历的分析方式一样,访问一棵树应从他的左子树开始访问,然后再访问根和右子树。

        如图1-1,首先访问以1为根的左子树(根节点2),进入第一层递归;以根节点为2的左子树又可以分为左子树(根节点3)、右子树(NULL),进入第二层递归;此时正在访问的是根节点为3的子树,根据中序遍历的规则应按照左子树、根、右子树的顺序访问,进入第三层递归。3的左右子树都为空不符合递归条件结束第三层递归,返回到第二层递归并访问根节点2,然后访问根节点2的右子树,右子树为空结束第二层递归,返回到第一层递归并访问根节点1,随后访问根节点1的右子树,同理根据遍历左子树的方式遍历右子树。

void InOrder(BTNode* root) {if (root == NULL) {printf("N ");return;}InOrder(root->left);        // 访问根的左子树printf("%d ", root->data);  // 访问根InOrder(root->right);       // 访问根的右子树
}

      根据代码中序遍历的结果示意图:


3.后序遍历

        后序遍历访问根结点的操作发生在遍历其左右子树之后。访问顺序为左子树、右子树、根,后序遍历访问一棵树时,根节点是最后访问的。

        如图1-1,首先访问根节点1的左子树(根节点2)进入第一层递归,这颗子树还可以分为左右子树,则进入第二层递归访问根节点2的左右子树。随后进入第三层递归先访问根节点3的左子树,然后是右子树,最后是根节点3,结束第三层递归返回第二层递归并访问根节点2的右子树之后在访问根节点2,结束第二层递归返回第一层递归,访问根节点1的右子树,最后访问根节点1。

void PostOrder(BTNode* root) {if (root == NULL) {printf("N ");return;}PostOrder(root->left);      // 访问左子树PostOrder(root->right);     // 访问右子树printf("%d ", root->data);  // 访问根
}

        根据代码后序遍历的结果示意图:

 三、节点个数


  • 对于一棵树而言,他的节点分为两种情况:
  1. 根节点为空,返回0。
  2. 根节点不为空,这颗树的节点数=左子树节点个数+右子树节点个数+根节点(1)。
  • 根据这两种情况写出的代码如下:
int TreeSize(BTNode* root) {return root == NULL ? 0 :TreeSize(root->left) + TreeSize(root->right) + 1;
}

  • 分析:第一个访问的根节点1不为空根据表达式先计算左子树的节点个数,通过TreeSize(root->left)进入第一层递归访问到根节点2,在第二层递归中通过TreeSize(root->left)进入第二层递归访问根节点3,根节点3不为空通过TreeSize(root->left)访问左子树进入第三层递归,左子树为空返回0,右子树为空返回0,第三层递归的返回值为0+0+1=1结束第三层递归,返回到第二层递归的TreeSize(root->left)的值就是1,然后在第二层递归中通过TreeSize(root->right)访问根节点2的右子树,右子树为空返回0,第二层递归的返回值1+0+1=2,结束第二层递归并将值返回到第一层递归的TreeSize(root->left),这样左子树的节点个数计算完毕为2,紧接着再计算第一层递归的TreeSize(root->right),同理可得TreeSize(root->right)的值为3,最后得出这棵树的节点个数是6。

四、叶子节点个数

        叶子节点是指不含有任何子树的节点(度为0),即root->left和root->right均为NULL。判断叶子节点的个数需要我们找到度为0的节点。


  • 对于一颗子树,它的叶子节点有三种情况:
  1. 根节点为空,返回0
  2. 根节点不为空,左右子树均为空,它本身就是叶子节点,返回1
  3. 根节点不为空,左右子树至少有一个不为空,这棵树的叶子节点树=左子树叶子节点数+右子树叶子节点数
  • 根据这三种情况写出的代码如下:
int TreeLeafSize(BTNode* root) {if (root == NULL) {return 0;}else if (root->left == NULL && root->right == NULL) {return 1;}else {return TreeLeafSize(root->left) + TreeLeafSize(root->right);}
}

  • 分析:进入第一层递归访问根节点1,根节点1不为空且左右子树不为空,通过TreeLeafSize(root->left)进入第二层递归访问根节点2,根节点2不为空且左子树不为空,通过TreeLeafSize(root->left)进入第三层递归访问根节点3,根节点3不为空但是此时左右子树为空,说明节点3是叶子节点,结束第三层递归返回1到第二层递归,在第二层递归中通过TreeLeafSize(root->right)访问根节点2的右子树,为空返回0,则以2为根节点的子树叶子节点个数0+1=1,结束第二层递归返回1到第一层递归,同理可得右子树的叶子节点为1+1=2,则这棵树的叶子节点数1+2=3。

五、高度

        树的高度是指树中节点的最大层次,在二叉树中,左右两棵子树的高度较大者作为这棵树的高度。


  • 求树的高度有两种情况:
  1. 根节点为空,返回0
  2. 根节点不为空,这棵树的高度=max(左子树高度,右子树高度)+1
  • 根据这两种情况写出的代码如下:
int TreeHeight(BTNode* root) {if (root == NULL) {return 0;}else {return max(TreeHeight(root->left), TreeHeight(root->right)) + 1;}
}

  • 分析:进入第一层递归访问根节点1,不为空通过TreeHeight(root->left)进入第二层递归访问根节点2,不为空通过TreeHeight(root->left)访问根节点3进入第三层递归,此时TreeHeight(root->left)和TreeHeight(root->right)的返回值都为0,第三层递归返回0+0+1=1到第二层递归并结束第三层递归。第二层递归返回1+0+1=2到第一层递归,同理再访问右子树得TreeHeight(root->right)的返回值为2,max(TreeHeight(root->left),TreeHeight(root->right))+1的结果为3,故此树的高度就是3。

六、第k层的节点个数

        求二叉树的第k层节点可以向下转化为求这棵树的左右子树的第k-1层节点,当k=1时就到达了这棵树的第k层。


  • 在二叉树中每次向下递归一层的情况有三种:
  1. 根节点为空,返回0
  2. 根节点不为空且k不等于1,继续向下递归直到k等于1
  3. 根节点不为空且k等于1,说明到达目标层,返回1
  • 根据这三种情况写出的代码如下:
int TreeLevelKSize(BTNode* root, int k) {if (root == NULL) {return 0;}if (k == 1) {return 1;}else {return TreeLevelKSize(root->left, k - 1) + TreeLevelKSize(root->right, k - 1);}
}

  • 分析:假设k=3,进入第一层递归访问根节点1,不为空且k不等于1(k=3);通过TreeLevelKSize(root->left, k - 1)进入第二层递归访问根节点2,不为空且k不等于1(k=2);通过TreeLevelKSize(root->left, k - 1)进入第三层递归访问根节点3,不为空,此时k=1说明到达目标层,返回1结束第三层递归。在第二层递归中通过TreeLevelKSize(root->right, k - 1)访问右子树,为空返回0,结束第二层递归返回1到第一层递归,同理通过TreeLevelKSize(root->right, k - 1)可到达根节点1的右子树且第k层节点数是2,所以这棵树的第三层有1+2=3个节点。

七、查找值为x的节点

        遍历二叉树找到值为x的节点返回即可。


  • 遍历的结果有四种情况:
  1. 根节点为空,返回NULL
  2. 根节点不为空,节点的值等于x,返回这个节点(地址)
  3. 如果在左子树中找到了目标节点,不用再遍历右子树
  4. 左右子树都没有找到这个节点,返回NULL
  • 根据这四种情况写出的代码如下:
BTNode* TreeFind(BTNode* root, BTDataType x) {if (root == NULL) {return NULL;}if (root->data == x) {return root;}BTNode* ptr = TreeFind(root->left, x);if (ptr != NULL) {return ptr;}else {BTNode* ptr = TreeFind(root->right, x);if (ptr == NULL) {return NULL;}else {return ptr;}}
}

  • 分析:假设x=6,进入第一层递归访问根节点1,1不等于6且不为空通过TreeFind(root->left, x)进入第二层递归访问根节点2,2不等于6且不为空进入第三层递归访问根节点3,3不等于6,此时结束第三层递归返回值NULL,根节点2的左子树没有找到,向右子树遍历,右子树也没有找到结束第二层递归返回NULL,说明在左子树中没有找到目标节点,这时候查找右子树,在右子树中找到了就返回这个节点。

八、创建二叉树

        已知一个字符数组,根据这个字符数组创建二叉树;创建二叉树的顺序应该是根、左子树、右子树。


  • 假设给出这样一个数组:"abc##de#g##f###",其中"#"表示NULL,字母代表树中节点存储的值,还是用递归的思想,根据这个数组建立一个二叉树。
  • 首先需要遍历这个数组,遍历的结果有两种:
  1. 指针指向的元素为"#",代表这个节点为NULL(左子树或右子树建立完成)
  2. 指针指向非"#"元素,将值赋给这个节点后继续建立这个节点的左子树和右子树
  • 根据这两种情况写出的代码如下:
// abc##de#g##f###
BTNode* CreateTree(BTDataType* arr, int* pi) {if (arr[*pi] == '#') {(*pi)++;return NULL;}BTNode* node = (BTNode*)malloc(sizeof(BTNode));if (node == NULL) {perror("malloc fail!");exit(-1);}node->data = arr[(*pi)++];node->left = CreateTree(arr, pi);node->right = CreateTree(arr, pi);return node;
}

  • 分析:定义一个指针,代表数组的下标,每当创建一个节点或遇到NULL就后移。创建好一个节点后,给节点赋值,然后进入递归,当函数返回NULL时说明这颗子树创建完成,以此类推。

九、销毁二叉树

        销毁二叉树时,采用后序遍历销毁节点,原因是如果采用前序遍历或中序遍历会导致根节点销毁后无法销毁他的左子树或右子树。


  • 销毁二叉树步骤:
  1. 如果当前节点为NULL,直接结束
  2. 不为空,先销毁左子树,再销毁右子树,最后销毁根
  • 代码如下:
void TreeDestory(BTNode* root) {if (root == NULL) {return;}// 采用后序遍历销毁树TreeDestory(root->left);TreeDestory(root->right);free(root);
}

  • 分析:进入函数后先判断这个节点是不是空,如果是代表已经销毁,不是通过递归依次销毁左子树和右子树,最后销毁根。

十、层序遍历 

        层序遍历(广度优先遍历)指的是在一棵二叉树中,依次遍历访问每一层的节点,直到最后一层。层序遍历需要使用到队列结构,相关代码在gitte中。


  • 层序遍历基本步骤:
  1. 如果节点为空,不进队列;节点不为空,进队列
  2. 进入循环,取队列的头节点,头节点的左右节点(非空)入队列,头节点出队列,这时访问了一层节点
  3. 当队列为空时,结束循环
  • 代码如下:
void TreeLevelOrder(BTNode* root) {Queue q;QueueInit(&q);// 不为空进队列if (root) {QueuePush(&q, root);}// 如果队列是空的,代表已经访问完所有元素while (!QueueEmpty(&q)) {BTNode* front = QueueFront(&q);QueuePop(&q);printf("%c ", front->data);if (front->left) {QueuePush(&q, front->left);}if (front->right) {QueuePush(&q, front->right);}}QueueDestroy(&q);
}

  • 分析:初始化队列,如上图,节点1入队列,进入循环,取队头节点并打印在控制台,节点1的左右节点2,4入队列,节点1出队列(队列中剩2,4);开始第二次循环,取队头节点2,2的左节点3入队列,2出队列(队列中剩4,3),以此类推,开始第三次循环后节点4的左右节点进队列,完成层序遍历。

十一、判断完全二叉树

        完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。 完全二叉树就是这样一种特殊的非满二叉树:除了最后一层外其他每一层都是填满的,并且最后一层的节点都尽可能地靠左排列。如上图。


  • 具体实现步骤:判断完全二叉树不能利用递归实现,需要利用队列的相关知识(广度优先遍历)实现。
  1. 创建队列,无论树中的节点是否为空,都进入队列,根据层序遍历,将队头节点的左右子节点带入队列,在进入队列时如果遇到了第一个空节点就停止将节点带入队列,开始判断队列中的节点是否都为空。如果是,代表这棵树是完全二叉树;如果不是,代表这棵树是完全二叉树。
  • 代码:
bool TreeComplete(BTNode* root)
{Queue q;QueueInit(&q);if (root)QueuePush(&q, root);while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);QueuePop(&q);// 遇到第一个空,就可以开始判断,如果队列中还有非空,就不是完全二叉树if (front == NULL){break;}QueuePush(&q, front->left);QueuePush(&q, front->right);}while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);QueuePop(&q);// 如果有非空,就不是完全二叉树if (front){QueueDestroy(&q);return false;}}QueueDestroy(&q);return true;
}

  • 队列的源码可到博主的个人码云中获取(Project_Queue)

十二、补充二叉树的性质

  1. 若规定根结点的层数为1,则一棵非空二叉树的第i层上最多有2的i-1次方个结点.

  2. 若规定根结点的层数为1,则深度为h的二叉树的最大结点数是2的h次方减1.
  3. 对任何一棵二叉树, 如果度为0其叶结点个数为 n0, 度为2的分支结点个数为n2 ,则有n0 =n2 +1​​​​​​​
  4. 若规定根结点的层数为1,具有n个结点的满二叉树的深度h=log2(n+1). (ps:log2(n+1)是log以2为底,n+1为对数)
  5. 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有结点从0开始编号,则对于序号为i的结点有:​​​​​​​
  • ​​​​​​​若i>0,i位置结点的双亲序号:(i-1)/2;i=0,i为根结点编号,无双亲结点  
  • 若2i+1<n,左孩子序号:2i+1,2i+1>=n否则无左孩子
  • 若2i+2<n,右孩子序号:2i+2,2i+2>=n否则无右孩子

针对性质3:

/*
* 假设二叉树有N个结点
* 从总结点数角度考虑:N = n0 + n1 + n2 ①
* 
* 从边的角度考虑,N个结点的任意二叉树,总共有N-1条边
* 因为二叉树中每个结点都有双亲,根结点没有双亲,每个节点向上与其双亲之间存在一条边
* 因此N个结点的二叉树总共有N-1条边
* 
* 因为度为0的结点没有孩子,故度为0的结点不产生边; 度为1的结点只有一个孩子,故每个度为1的结
点* * 产生一条边; 度为2的结点有2个孩子,故每个度为2的结点产生两条边,所以总边数为:
n1+2*n2 
* 故从边的角度考虑:N-1 = n1 + 2*n2 ②
* 结合① 和 ②得:n0 + n1 + n2 = n1 + 2*n2 - 1
* 即:n0 = n2 + 1
*/

相关文章:

【数据结构】第八节:链式二叉树

个人主页&#xff1a; NiKo 数据结构专栏&#xff1a; 数据结构与算法 源码获取&#xff1a;Gitee——数据结构 一、二叉树的链式结构 typedef int BTDataType; typedef struct BinaryTreeNode {BTDataType data;struct BinaryTreeNode* left; // 左子树根节点struct BinaryT…...

Fair Graph RepresentationLearning via Diverse Mixture-of-Experts

发表于&#xff1a;WWW23 推荐指数&#xff1a; #paper/⭐⭐ 问题背景&#xff1a; 背景 现实世界的数据很多样&#xff0c;阻止GNN学习公平的表示。当去偏见化后&#xff0c;他们面临着可学知识不足且属性有限的重大问题 解决方法&#xff1a; 应对公平训练导致可学习知识…...

电机驱动开发之驱动板

目录 1.主要器件选型2.原理图设计3.PCB绘制电源调理驱动电路电流反馈位置反馈 4.PCB绘制5.打板验证6.总结 1.主要器件选型 器件参数封装理由LDOLM317DCYR &#xff08;24V-12V 12V-5V&#xff09;SOT-223小电流应用 LDO比DCDC噪声小响应快更为稳定预驱FD6288TTssop-20常见无刷…...

STM32F1 HAL库笔记2_HAL 系统驱动程序

1、HAL 固件驱动程序 API 1.1、如何使用此驱动程序 通用 HAL 驱动程序包含一组通用的 API&#xff0c;PPP 外设驱动程序可以使用这些 API 来开始使用 HAL。HAL 包含两个 API 类别&#xff1a; • 常见的 HAL API • 服务 HAL API 1.2、初始化和去初始化函数 本节提供的功能&a…...

el-table实现当内容过多时,el-table显示滚动条,页面不显示滚动条

估计有不少小伙伴在开发公司的ERP使用el-table都会遇到这么一个问题&#xff0c;就是产品经理提出&#xff0c;页面不出现滚动条&#xff0c;因为不美观。但是当el-table内容过多&#xff0c;超过页面的宽度时候&#xff0c;页面就会有滚动条。那应该如何解决呢?能不能让滚动条…...

Java面试篇基础部分-Java中的异常以及异常处理

导语   在实际的开发过程中,往往会遇到各种各样的编程异常,如何处理这些异常,直接会影响到整个程序和系统的稳定性,如果不能在合适的地方抛出合适的异常或者是对异常进行捕获。那么就会影响到整个程序的运行。所以如何处理异常,是作为每个开发者来说必不可少的开发技能。…...

win11 MySQL的坑

最近升级了系统&#xff0c;导致以前的安装的两个版本MySQL服务无法启动&#xff0c;只能在mysql的bin目录&#xff0c;执行mysqld --console才能启动&#xff0c;mysqld都无法启动&#xff0c; 所幸进行了数据库初始化&#xff0c;这次在MySQL的bin目录执行 mysqld或者mysqld …...

stm32单片机个人学习笔记1(简单介绍)

前言 本篇文章属于stm32单片机&#xff08;以下简称单片机&#xff09;的学习笔记&#xff0c;来源于B站教学视频。下面是这位up主的视频链接。本文为个人学习笔记&#xff0c;只能做参考&#xff0c;细节方面建议观看视频&#xff0c;肯定受益匪浅。 STM32入门教程-2023版 细…...

python中@staticmethod、@classmethod用法

1、类的基础介绍 类对象&#xff1a;定义的类就是类对象 类属性&#xff1a;定义在__init__ 外部的变量 类方法&#xff1a;定义在类中&#xff0c;且被classmethod 装饰的方法 实例对象&#xff1a;类对象实例化后就是实例对象 实例属性&#xff1a;定义在__init__内部带…...

Harmony Next 文件命令操作(发送、读取、媒体文件查询)

查询文件位置 hdc shell mediatool query IMG_20240902_204224.jpg 输出示例 拉取文件 hdc file recv /storage/cloud/100/files/Photo/4/IMG_1725281044_036.jpg aa.jpg 发送文件 hdc file send aa.jpg /storage/media/100/local/files/Docs/Download/ab.jpg 下载目录位置…...

Go语言中的链表与双向链表实现

链表基础 链表是一种由有限元素组成的数据结构&#xff0c;其中每个元素至少使用两个内存空间&#xff1a;一个存储实际数据&#xff0c;另一个存储指向下一个元素的指针&#xff0c;从而形成一个元素序列构成链表。链表的第一个元素称为头结点&#xff0c;而最后一个元素通常…...

开始一个WPF项目时的记忆重载入

目前在工业软件的UI开发方案选择中&#xff0c;WPF仍然是一个重要的选项。 但是其固有的复杂性&#xff0c;对于像我这样&#xff0c;并不是一直在从事界面开发的人来说&#xff0c;每次重启&#xff0c;都需要一两天的适应的时间。所以这里稍微写一个笔记。 还是老办法&…...

用go语言实现树和哈希表算法

算法复杂度 判断一个算法的效率通常基于其计算复杂度&#xff0c;这主要与算法访问输入数据的次数有关。计算机科学中常用大O表示法来描述算法的复杂度。例如&#xff0c;O(n)的算法只需访问一次输入数据&#xff0c;因此优于O(n)的算法&#xff0c;后者则优于O(n)的算法&…...

基于SpringBoot+Vue+MySQL的校园健康驿站管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 本文设计并实现了一个基于SpringBoot后端、Vue前端与MySQL数据库的校园健康驿站管理系统。该系统旨在通过数字化手段&#xff0c;全面管理学生的健康信息&#xff0c;包括体温监测、疫苗接种记录、健康状况申报等&#xff0c;为…...

深入理解MATLAB中的事件处理机制

在MATLAB中&#xff0c;事件处理机制是一种强大的工具&#xff0c;它允许对象之间的交互和通信。这种机制基于观察者设计模式&#xff0c;其中一个对象&#xff08;观察者&#xff09;监听另一个对象&#xff08;发布者&#xff09;的状态变化。当发布者的状态发生变化时&#…...

线程--线程同步

这里写目录标题 同步概念线程同步概念数据混乱原因 互斥量原理锁的注意事项1、cpu时间轮片2、建议锁总结 使用锁来管理线程同步问题产生主要函数init、destorylock、unlock代码注意事项&#xff08;锁的粒度&#xff09; try锁死锁出现原因图解 读写锁特性图解函数总览init、de…...

【QT】Qt窗口

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;QT 目录 &#x1f449;&#x1f3fb;菜单栏设置&#x1f449;&#x1f3fb;QToolBar练习 &#x1f449;&#x1f3fb;QStausBar&#x1f449;&#x1f3fb;Q…...

场外个股期权怎么给股票加杠杆?

今天期权懂带你了解场外个股期权怎么给股票加杠杆&#xff1f;场外期权交易通过向证券公司支付一定额度的股票期权费&#xff0c;然后买入大额的股票持仓&#xff0c;从而实现的杠杆交易。 买入看涨期权 操作&#xff1a;支付权利金购买看涨期权。 杠杆作用&#xff1a; 期…...

【Docker部署ELK】(7.15)

1、拉取镜像 docker pull docker.elastic.co/elasticsearch/elasticsearch:7.15.0 docker pull docker.elastic.co/kibana/kibana:7.15.0 docker pull docker.elastic.co/logstash/logstash:7.15.02、配置文件&#xff08;解压资源到D盘DOCKER目录下&#xff09; 2.1 配置文件…...

UE4_后期处理_后期处理材质及后期处理体积一

后期处理效果 在渲染之前应用于整个渲染场景的效果。 后期处理效果&#xff08;Post-processing effect&#xff09;使美术师和设计师能够对影响颜色、色调映射、光照的属性和功能进行组合选择&#xff0c;从而定义场景的整体外观。要访问这些功能&#xff0c;可以将一种称为…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

ServerTrust 并非唯一

NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

Go语言多线程问题

打印零与奇偶数&#xff08;leetcode 1116&#xff09; 方法1&#xff1a;使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...

华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)

题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...