【数据结构与算法篇】一文详解数据结构之二叉树

树的介绍及二叉树的C++实现

  • 一 . 树的概念
  • 二 . 相关术语
  • 三 . 树的表示
  • 四 . 什么是二叉树
    • 1> 二叉树的特性
    • 2> 特殊的二叉树
    • 3> 二叉树的性质
  • 五 . 二叉树的存储结构
    • 1> 二叉树的顺序存储
    • 2> 二叉树的链式存储
  • 六 . 堆
    • 1> 什么是堆
    • 2> 用堆存储数据
    • 3> 堆的Cpp代码实现
      • 1) 堆的初始化
      • 2) 堆的销毁
      • 3) 堆的遍历
      • 4) 向上(或向下)调整建大堆(或小堆)
        • 小堆中向上调整
        • 小堆中向下调整
        • 大堆中向上调整
        • 大堆中向下调整
      • 5) 堆的插入
      • 6) 堆删除
      • 7) 返回堆顶元素
      • 8) 返回堆中元素个数
      • 9) 判断堆是否为空
    • 4> 堆排序
      • 1) 排升序
      • 2) 排降序
    • 5> TOP - K问题
  • 七 . 二叉树的链式存储结构
    • 1> 链式二叉树的代码实现
      • 1) 链式二叉树的四种遍历方式
        • 前序遍历
        • 中序遍历
        • 后序遍历
        • 层序遍历
      • 2) 返回二叉树中节点的个数
        • 返回二叉树中节点的总个数
        • 返回二叉树中叶子节点的个数
        • 返回二叉树中第k层节点的总个数
      • 3) 二叉树中的查找
      • 4) 返回二叉树的高度
      • 5) 判断是否为完全二叉树
      • 6) 二叉树的销毁

一 . 树的概念

    树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一
个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,
也就是说它是根朝上,而叶朝下的。
  • 根结点: 树中的从上开始的第一个节点, 是树中的特殊节点
    • 根节点没有前驱结点
    • 有至少一个或者n个后继节点
  • 其余结点: 除根节点之外的节点 。 它们被分成M(M>0)个互不相交的集合T1、T2、……、Tm,其中每一个集合Ti(1<= i
    <= m)又是一棵结构与树类似的子树。
  • 每棵子树的根结点
    • 有且只有一个前驱(所有子树的根节点)
    • 可以有0个或多个后继
  • 因此,树是递归定义的
    • 递归 : 复杂问题拆解成多个类似的小问题进行求解。
  • 注意:树形结构中,子树之间不能有交集,否则就不是树形结构

二 . 相关术语

在这里插入图片描述

  • 节点的度 :
    • 一个节点含有的子树的个数称为该节点的度
    • 如上图:A节点的度为6
  • 叶节点(又叫终端节点):
    • 度为0的节点称为叶节点
    • 如上图:B、C、H、I…等节点为叶节点
  • 子树 :
    • 根节点之下的节点所形成的树。树由多个子树构成
  • 分支节点(又叫非终端节点):
    • 度不为0的节点
    • 如上图:D、E、F、G…等节点为分支节点
  • 父节点(又叫双亲节点):
    • 若一个节点含有子节点,则这个节点称为其子节点的父节点
    • 如上图:A是B的父节点
  • 子节点(又叫孩子节点):
    • 一个节点含有的子树的根节点称为该节点的子节点
    • 如上图:B是A的孩子节点
  • 兄弟节点:
    • 具有相同父节点的节点互称为兄弟节点
    • 如上图:B、C是兄弟节点
  • 树的度:
    • 一棵树中,最大的节点的度称为树的度
    • 如上图:A节点的度为6,是最大的度 因此树的度为 6
  • 节点的层次
    • 从根开始定义起,根为第1层,根的子节点为第2层,以此类推
  • 树的高度(也称深度):
    • 树中节点的最大层次
    • 如上图:树的高度为4
  • 堂兄弟节点:
    • 双亲在同一层的节点互为堂兄弟
    • 如上图:H、I互为兄弟节点
  • 节点的祖先:
    • 从根到该节点所经分支上的所有节点
    • 如上图:A是所有节点的祖先
  • 子孙:
    • 以某节点为根的子树中任一节点都称为该节点的子孙
    • 如上图:所有节点都是A的子孙
  • 森林:
    • 由m 加粗样式(m>0) 棵互不相交的树的集合称为森林

三 . 树的表示

  • 树有很多种表示方式, 例如:
    • 双亲表示法
    • 孩子表示法
    • 孩子双亲表示法
    • 孩子兄弟表示法等
  • 孩子兄弟表示法是最常用的一种表示法, 介绍如下:
  • 树中的任意一个节点的组成
    • 值域 : 存储数据
    • 孩子节点 : 指向其第一个孩子节点
    • 兄弟节点 : 指向它的下一个兄弟节点
typedef int DataType
struct TreeNode
{struct TreeNode* firstChild1;   // 指向其第一个孩子节点struct TreeNode* nextBrother;  // 指向其下一个兄弟节点DataType _data;              // 节点中的数据域
}左孩子右兄弟表示法 : 指向左边第一个孩子节点(子节点), 指向右边第一个兄弟节点

高度为h的完全二叉树 : 前h-1层为满的, 第h层不一定满, 但是第h层一定是从左到右连续的

四 . 什么是二叉树

一棵二叉树是节点的有限集合

  • 节点可以为空, 此时为空树
  • 可以只有一个节点, 该节点被称为根节点
  • 也可以由根与子树构成(左子树和右子树, 子树可为空)

在这里插入图片描述

1> 二叉树的特性

  • 二叉树的度最大为2
  • 每个父节点所拥有子节点的个数为 1或2
  • 不存在子节点的节点是二叉树中的叶节点
  • 二叉树的子树有左右之分, 不可以颠倒。 因此二叉树也被称为有序树

对于任意的二叉树都是由以下情况复合而成的
在这里插入图片描述

2> 特殊的二叉树

  • 二叉树:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是 ,则它就是满二叉树。
    • 在这里插入图片描述
  • 完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对
    应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树
    • 在这里插入图片描述

3> 二叉树的性质

  1. 若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有 2^(i-1个结点.
  2. **若规定根节点的层数为1,则深度为h的二叉树的最大结点数是 2^h - 1)
  3. 对任何一棵二叉树, 如果其叶结点个数为 n0 , 度为2的分支结点个数为 n1, 则有 n0= n1 +1
  4. 若规定根节点的层数为1,具有n个结点的满二叉树的深度,h= log(n+1) (ps: 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代表无右孩子

五 . 二叉树的存储结构

二叉树一般可以使用两种结构存储,一种顺序结构,一种链式结构。

1> 二叉树的顺序存储

  • 顺序结构存储就是使用数组来存储
  • 一般使用数组只适合表示完全二叉树,因为非完全二叉树会有空间的浪费
  • 在现实中使用中 只有数据结构 - 堆(完全二叉树)才会使用数组来存储
  • 二叉树的顺序存储在物理上通过数组来实现,在逻辑上是一颗二叉树的结构
  • 完全二叉树的顺序存储:
    完全二叉树的顺序存储
  • 非完全二叉树的顺序存储:
    在这里插入图片描述

2> 二叉树的链式存储

二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是:

  • 链表中每个结点由三个域组成,数据域和左右指针域
  • 左右指针分别用来指向该结点的左孩子节点和右孩子节点
  • 链式结构又分为二叉链和三叉链,在本篇文章中讲述的是二叉链
  • 二叉链:
    • 在这里插入图片描述
  • 三叉链:
    • 在这里插入图片描述

六 . 堆

1> 什么是堆

完全二叉树的顺序存储结构被称之为堆
堆分为大堆和小堆:

  • 大堆 : 父节点 >= 子节点 (指的是节点中存储的值)
  • 小堆 : 父节点 <= 子节点 (指的是节点中存储的值)

2> 用堆存储数据

堆是一种数据结构, 可以看作是一种容器, 用来存放数据, 若要将数据存入堆中, 那么要通过以下步骤:

    1. 将数据按照完全二叉树的顺序存储方式存入到一维数组中,
  • 2 . 调整数组中元素的关系, 必须满足 父节点 >=(<=) 子节点
  • 3 . 当数组中的元素满足在二叉树中 父节点 >= 子节点时, 这是相当于将数据存入大堆中
  • 4 . 如果满足 父节点 <= 子节点, 这是相当于将数据存入小堆中。
  • 堆示例图:
    • 在这里插入图片描述

3> 堆的Cpp代码实现

1) 堆的初始化

// 堆的初始化
void HPInit(HP* php)
{assert(php);php->_arr = new HPDataType[4];php->capacity = 4;php->size = 0;
}

2) 堆的销毁

// 堆的销毁
void HPDestroy(HP* php)
{assert(php);if (!php){return;}delete[] php->_arr;php->_arr = NULL;php->capacity = php->size = 0;
}

3) 堆的遍历

// 堆的遍历
void HPPrint(HP* php)
{for (int i = 0; i < php->size; i++){cout << php->_arr[i] << " ";}cout << endl;
}

4) 向上(或向下)调整建大堆(或小堆)

小堆中向上调整
// 堆向上调整 (堆中插入或互换元素向上调整) (小堆)
void AdjustUpS(HPDataType* a, int child)
{while (child){int parent = (child - 1) / 2;if (a[parent] < a[child])return;else{HPSwap(a[parent], a[child]);child = parent;}}
}
小堆中向下调整
// 堆向下调整 (堆中插入或互换元素向下调整) (小堆)
void AdjustDownS(HPDataType* a, int n, int parent)
{int child = parent * 2 + 1;while (child < n){if (child + 1 < n && a[child + 1] < a[child]){++child;}if (a[child] < a[parent]){HPSwap(a[child], a[parent]);parent = child;child = parent * 2 + 1;}elsebreak;}
}
大堆中向上调整
// 堆向上调整 (堆中插入或互换元素向上调整) (大堆)
void AdjustUpB(HPDataType* a, int child)
{while (child){int parent = (child - 1) / 2;if (a[parent] > a[child])return;else{HPSwap(a[parent], a[child]);child = parent;}}
}
大堆中向下调整
// 堆向下调整 (堆中插入或互换元素向下调整) (大堆)
void AdjustDownB(HPDataType* a, int n, int parent)
{int child = parent * 2 + 1;while (child < n){if (child + 1 < n && a[child + 1] > a[child]){++child;}if (a[child] > a[parent]){HPSwap(a[child], a[parent]);parent = child;child = parent * 2 + 1;}elsebreak;}
}

5) 堆的插入

// 堆的插入 (小堆 插入元素向上调整)
void HPPush(HP* php, HPDataType val)
{assert(php);if (php->size == php->capacity){HPDataType* newHP = new HPDataType[php->capacity * 2];for (int i = 0; i < php->size; i++){newHP[i] = php->_arr[i];}delete[] php->_arr;php->_arr = newHP;}php->_arr[php->size] = val;++php->size;AdjustUpS(php->_arr, php->size - 1);       // 对新插入堆中的值 val 进行比较排序, 直至符合小堆为止
}

6) 堆删除

// 堆删除 (小堆, 删除 向上调整)
void HPPop(HP* php)
{assert(php);assert(php->size > 0);HPSwap(php->_arr[0], php->_arr[php->size - 1]);--php->size;AdjustDownS(php->_arr, php->size, 0);      // 再进行向下调整
}

7) 返回堆顶元素

// 返回堆顶元素
HPDataType HPTop(HP* php)
{assert(php);assert(php->size > 0);return php->_arr[0];
}

8) 返回堆中元素个数

// 返回堆中元素的个数
int HPSize(HP* php)
{assert(php);return php->size;
}

9) 判断堆是否为空

// 判断堆是否为空
bool HPEmpty(HP* php)
{return php->size == 0;
}

4> 堆排序

1) 排升序

排升序 : 将待排序序列排为升序, 步骤如下:

    1. 将待排序序列构造为一个大堆
    1. 利用堆顶元素, 也就是根元素是堆中最大值的特点, 将堆顶元素换至堆末尾
    1. 然后将新的堆顶元素进行向下调整
      注意:此时向下调整时, 原堆顶元素(被换至末尾的堆顶元素)不参与向下调整
    1. 之后再次进行如上步骤
    1. 直至待排序序列完全为升序

2) 排降序

派降序: 将待排序序列排为降序, 步骤如下:

    1. 将待排序序列构造为一个小堆
    1. 利用堆顶元素, 也就是根元素是堆中最小值的特点, 将堆顶元素换至堆末尾
    1. 然后将新的堆顶元素进行向下调整
      注意:此时向下调整时, 原堆顶元素(被换至末尾的堆顶元素)不参与向下调整
    1. 之后再次进行如上步骤
    1. 直至待排序序列完全为降序

5> TOP - K问题

TOP-K问题:即求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。

  • 比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。
  • 对于Top-K问题,能想到的最简单直接的方式就是排序,但是:如果数据量非常大,排序就不太可取了(可能数据都不能一下子全部加载到内存中)。最佳的方式就是用堆来解决,基本思路如下:
    1. 用数据集合中前K个元素来建堆
      • 前k个最大的元素,则建小堆
      • 前k个最小的元素,则建大堆
    2. 用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素
    3. 将剩余N-K个元素依次与堆顶元素比完之后,堆中剩余的K个元素就是所求的前K个最小或者最大的元素。

七 . 二叉树的链式存储结构

1> 链式二叉树的代码实现

1) 链式二叉树的四种遍历方式

前序遍历
// 链式二叉树的前序遍历
void PreOrder(BTNode* root)
{if (!root){cout << " ";return;}cout << root->data << " ";PreOrder(root->left);PreOrder(root->right);
}
中序遍历
// 链式二叉树的中序遍历
void InOrder(BTNode* root)
{if (!root){//cout << " ";return;}PreOrder(root->left);cout << root->data << " ";PreOrder(root->right);
}
后序遍历
// 链式二叉树的后序遍历
void EpilOgue(BTNode* root)
{if (!root){//cout << " ";return;}PreOrder(root->left);PreOrder(root->right);cout << root->data << " ";
}
层序遍历

链式二叉树的层序遍历需要依靠队列这一种数据结构

// 链式二叉树的层序遍历
void Sequence(BTNode* root)
{queue<BTNode*> que;if (root){que.push(root);}while (!que.empty()){BTNode* front = que.front();cout << front->data << " ";que.pop();if(front->left)que.push(front->left);if(front->right)que.push(front->right);}cout << endl;
}

2) 返回二叉树中节点的个数

返回二叉树中节点的总个数
// 返回链式二叉树中节点的总个数 (后序递归遍历)
int TreeSize(BTNode* root)
{// return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;if (!root){return 0;}return TreeSize(root->left) + TreeSize(root->right) + 1;
}
返回二叉树中叶子节点的个数
// 返回链式二叉树中叶子节点的个数
int TreeLeafSize(BTNode* root)
{if (!root){return 0;}if (root->left == NULL && root->right == NULL){return 1;}return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}
返回二叉树中第k层节点的总个数
// 返回链式二叉树第k层所有节点的个数 (非完全二叉树)
int TreeKLevel(BTNode* root, int k)
{assert(k > 0);if (!root)return 0;if (k == 1)return 1;return TreeKLevel(root->left, k - 1) + TreeKLevel(root->right, k - 1);
}

3) 二叉树中的查找

//  链式二叉树中查找值为val的节点 并返回其地址
BTNode* TreeFind(BTNode* root, BTDataType val)
{if (!root)return NULL;if (root->data == val)return root;BTNode* ret = TreeFind(root->left, val);if (ret)return ret;ret = TreeFind(root->right, val);if (ret)return ret;return NULL;
}

4) 返回二叉树的高度

// 返回二叉树的高度(或者说 最大深度)
int TreeHight(BTNode* root)
{if (!root)return 0;int left = TreeHight(root->left);int right = TreeHight(root->right);return left >= right ? left + 1 : right + 1;
}

5) 判断是否为完全二叉树

// 判断是否为完全二叉树
int TreeComplete(BTNode* root)
{queue<BTNode*> q1;if (root)q1.push(root);while (!q1.empty()){BTNode* front = q1.front();if (!front)break;q1.push(front->left);q1.push(front->right);q1.pop();}while (!q1.empty()){if (q1.front())return false;q1.pop();}return true;
}

6) 二叉树的销毁

// 链式二叉树的销毁
void TreeDestory(BTNode** root)
{if (!(*root))return;TreeDestory(&((*root)->left));TreeDestory(&((*root)->right));delete *root;*root = NULL;
}

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

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

相关文章

木马病毒是怎么进入服务器的,要如何防范

木马病毒通常是基于计算机网络&#xff0c;基于客户端和服务端的通信、监控程序。名称来源于公元前十二世纪希腊和特洛伊之间的一场战争。能够在计算机管理员未发觉的情况下开放系统权限、泄漏用户信息、甚至窃取整个计算机管理使用权限&#xff0c;隐匿性高。 木马病毒的入侵方…

【恋上数据结构】哈夫曼树学习笔记

哈夫曼树 哈夫曼编码&#xff08;Huffman Coding&#xff09; 哈夫曼编码&#xff0c;又称为霍夫曼编码&#xff0c;它是现代压缩算法的基础 假设要把字符串 [ABBBCCCCCCCCDDDDDDEE] 转成二进制编码进行传输。 可以转成 ASCII 编码 (6569&#xff0c;10000011000101) &…

Python脚本模拟真实设备刷视频播放量、浏览量

简述 Python3脚本刷视频播放量 前情提示 系统:centOS7,8阿里云一折优惠云小站_专享特惠_云产品推荐-阿里云 宝塔8.x 一说 部分截图、链接等因过期、更换域名、MD语法等可能不显示,可联系反馈(备注好博文地址),谢谢❤带有#号、删除线、不操作、不执行字样的为提示或者…

C++学习之路(十九)C++ 用Qt5实现一个工具箱(用SQLite数据库来管理粘贴板数据)- 示例代码拆分讲解

上篇文章&#xff0c;我们用 Qt5 实现了在小工具箱中添加了《点击按钮以新窗口打开功能面板》功能。今天我们把粘贴板功能用SQLite数据库来管理&#xff0c;用SQLite来实现增删改查。下面我们就来看看如何来规划开发这样的小功能并且添加到我们的工具箱中吧。 老规矩&#xff…

基于51单片机多功能时钟闹钟系统

**单片机设计介绍&#xff0c;基于51单片机多功能时钟闹钟系统 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于51单片机的多功能时钟闹钟系统是一种基于单片机的电子设备&#xff0c;能够显示时间、设置闹钟、进行计时以及提…

随机链表的复制[中等]

优质博文&#xff1a;IT-BLOG-CN 一、题目 给你一个长度为n的链表&#xff0c;每个节点包含一个额外增加的随机指针random&#xff0c;该指针可以指向链表中的任何节点或空节点。构造这个链表的深拷贝。深拷贝应该正好由n个全新节点组成&#xff0c;其中每个新节点的值都设为…

Hadoop学习笔记(HDP)-Part.18 安装Flink

目录 Part.01 关于HDP Part.02 核心组件原理 Part.03 资源规划 Part.04 基础环境配置 Part.05 Yum源配置 Part.06 安装OracleJDK Part.07 安装MySQL Part.08 部署Ambari集群 Part.09 安装OpenLDAP Part.10 创建集群 Part.11 安装Kerberos Part.12 安装HDFS Part.13 安装Ranger …

sort by modulus of a complex number

描述 复数E包含实部x和虚部y, Exyi;E的模为: 输入n(<1000)和n对(x,y); 按模数升序对复合体进行排序&#xff0c;如果模数相等&#xff0c;则按输入顺序排序。 排序后输出n行of (x_i,y_i,mod_i)&#xff0c;保留2个十进制小数。 输入 输入n和n对(x,y); 输出 输出排序后的n行(…

P=NP?

背景&#xff1a;   2000年5月24日&#xff0c;新罕布什尔州的克莱数学研究所列出了数学和计算机科学中七个未解决的问题。然而&#xff0c;直到今天&#xff0c;这些问题中只有一个被解决了&#xff0c;那就是庞加莱猜想&#xff08;Poincar Conjecture&#xff09;——被俄…

手机如何设置防骚扰电话?

很多人都曾接到过烦人的推销电话&#xff0c;这些电话不仅让人感到烦恼&#xff0c;而且有时候还会接二连三地打来&#xff0c;让人不胜其烦。我们的手机号码似乎已经被泄露&#xff0c;很难避免这些骚扰。 有时&#xff0c;我们因无法忍受骚扰电话而选择立即将其拉黑&#xff…

考研数据结构

851专业课 线性表线性表的定义线性表的顺序表示顺序表代码 线性表的链式存储表示单链表代码 顺序表和链表的比较 栈和队列栈顺序栈链栈 队列顺序队列链队列 串和数组kmp数组广义表 树和二叉树二叉树二叉树代码 线索二叉树线索二叉树代码 树和森林树的存储结构 哈夫曼树 图图的存…

【原创】提升MybatisPlus分页便捷性,制作一个属于自己的分页插件,让代码更加优雅

前言 MybatisPlus的分页插件有一点非常不好&#xff0c;就是要传入一个IPage&#xff0c;别看这个IPage没什么大不了的&#xff0c;最多多写一两行代码&#xff0c;可这带来一个问题&#xff0c;即使用xml的查询没法直接取对象里面变量的值了&#xff0c;得Param指定xml中的变…

探索Selenium的规避检测策略

Selenium之规避检测 背景 ​ 目前很多大网站有对selenium采取了监测机制。在正常情况下我们用浏览器访问相关网站的window.navigator.webdriver的值为 undefined或者为false。而使用selenium访问则该值为true。我们如何伪装&#xff0c;防止被检测出来呢&#xff1f; ​ 这是…

POJ 3233 Matrix Power Series 动态规划(矩阵的幂)

一、题目大意 给出一个矩阵A&#xff0c; 输出矩阵B的每一项对M取余数的值。 二、解题思路 以二维矩阵为例&#xff0c;首先计算K2的情况&#xff0c;我们设结果矩阵为B 有如下表达式 那么不难看出&#xff0c;需要的矩阵其实就是以下的两个矩阵相乘后的左上角的N*N个 然后…

初识Linux——基本指令(详解)1

呀哈喽&#xff0c;我是结衣。 在学习数据结构的同时&#xff0c;也不要忘了Linux的学习啊。今天我们开始Linux的教学&#xff0c;在学习之前我们肯定要会搭建Linux的学习环境&#xff0c;在我们的以前的博客里是有讲解的&#xff0c;所以所以这里我们就不在多说&#xff0c;我…

UDP数据报套接字

文章目录 DatagramSocket APIDatagramPacket API示例一: 请求响应UDP服务端UDP客户端 DatagramSocket API Socket是操作系统中的一个概念&#xff0c;本质上是一种特殊的文件&#xff0c;Socket就属于把“网卡”这个设备给抽象成了文件。往 Socket 文件中写数据&#xff0c;就…

深入探讨Guava的缓存机制

第1章&#xff1a;引言 大家好&#xff0c;我是小黑&#xff0c;今天咱们聊聊Google Guava的缓存机制。缓存在现代编程中的作用非常大&#xff0c;它能提高应用性能&#xff0c;减少数据库压力&#xff0c;简直就是性能优化的利器。而Guava提供的缓存功能&#xff0c;不仅强大…

iptables入门

今天我的工作遇到了巡检网络配置的任务&#xff0c;这次巡检的主机都是运行十多年的机器&#xff0c;并不是新的firewalld&#xff0c;基本都是iptables&#xff0c;上学的时候以为这些都没人用&#xff0c;所以没有认真学习&#xff0c;现在需要用到了&#xff0c;所以写一篇文…

PostGIS学习教程九:空间连接

PostGIS学习教程九&#xff1a;空间连接 空间连接&#xff08;spatial joins&#xff09;是空间数据库的主要组成部分&#xff0c;它们允许你使用空间关系作为连接键&#xff08;join key&#xff09;来连接来自不同数据表的信息。我们认为“标准GIS分析”的大部分内容可以表示…

17.认识下Docker之docker的核心原理(2)

1.容器-我的小世界 不知道大家看没看过小说《完美时间》&#xff0c;里面石昊经常进入一个小世界在里面与世隔绝的修炼或者战斗&#xff0c;总之就是在一个完全封闭的空间里做他想做的事情而与外界隔离&#xff0c;不受侵扰。通过前面的分析我们知道&#xff0c;Namepace让应用…