【初阶数据结构与算法】二叉树链式结构的定义与实现万字笔记(附源码)

在这里插入图片描述

文章目录

  • 一、二叉树链式结构的定义
  • 二、二叉树链式结构功能的基本实现
    • 1.链式二叉树的手动创建
    • 2.链式二叉树的前中后序遍历
      • 前序遍历
      • 中序遍历
      • 后序遍历
    • 3.链式二叉树节点的个数
    • 4.链式二叉树叶子节点的个数
    • 5.链式二叉树的高度/深度
    • 6.链式二叉树第k层节点的个数
    • 7.链式二叉树的查找
    • 8.链式二叉树层序遍历
    • 9.判断链式二叉树是否为完全二叉树
    • 10.链式二叉树的销毁
  • 三、源码

一、二叉树链式结构的定义

   链式二叉树就是⽤链表来表⽰⼀棵⼆叉树,即⽤链来指⽰元素的逻辑关系,通常的⽅法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别⽤来给出该结点左孩⼦和右孩⼦所在的链结点的存储地址,数据域则是当前节点存放的数据,其结构如下:

typedef int BTDataType;typedef struct BinaryTreeNode
{BTDataType data;struct BinaryTreeNode* left;struct BinaryTreeNode* right;
}BTNode;

   当我们使用链式结构来表示二叉树时,这个二叉树并不会有很多限制,它对节点的插入删除等操作要求并不高,所以我们后面会手动来创建链式二叉树,本文重要的不是创建二叉树的方法,而是二叉树各种功能的实现
   那么什么时候我们不能手动创建二叉树了呢?这个就要等我们后面在C++部分讲到二叉搜索树才能揭晓答案,二叉搜索树就只能通过特定的函数创建,而不能手动创建了,接着我们就再次回到我们今天的主题—二叉树链式结构功能的基本实现

二、二叉树链式结构功能的基本实现

1.链式二叉树的手动创建

   链式二叉树的手动创建很简单,就是创建一堆的节点,然后将它们互相连接起来,这里给出一个二叉树的图片,我们按照图片的结构手动创建一颗链式二叉树,如下:
在这里插入图片描述

   为了方便我们直接操作,我们先写一个申请二叉树节点的函数,可以通过传节点的值来帮我们申请一个具有该值的节点,如下:

//申请节点
BTNode* BTBuyNode(BTDataType x)
{BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));if (newnode == NULL){perror("mallc");return NULL;}newnode->data = x;newnode->left = newnode->right = NULL;return newnode;
}

   接下来我们就挨个的申请节点,然后使用左右指针将这些节点串联起来,如下:

//手动创建一颗链式二叉树
//返回根节点
BTNode* CreateBinaryTree()
{BTNode* nodeA = BTBuyNode('A');BTNode* nodeB = BTBuyNode('B');BTNode* nodeC = BTBuyNode('C');BTNode* nodeD = BTBuyNode('D');BTNode* nodeE = BTBuyNode('E');BTNode* nodeF = BTBuyNode('F');BTNode* nodeG = BTBuyNode('G');BTNode* nodeH = BTBuyNode('H');nodeA->left = nodeB;nodeA->right = nodeC;nodeB->left = nodeD;nodeB->right = nodeE;nodeC->left = nodeF;nodeC->right = nodeG;nodeD->left = nodeH;return nodeA;
}

   这样我们手动创建一颗链式二叉树,返回了它的根节点,接下来我们就可以开始对它进行操作了,后面的内容才是今天的重点

2.链式二叉树的前中后序遍历

   链式二叉树的这个结构非常适合递归,它每一次函数调用创建的栈帧就可以看做我们要递归的一个节点,在链式二叉树的接口实现中,我们一定要有抽象能力,当然,我们后面也会给大家画图来解释,这里不再多说
   我们今天第一个重点就是完成链式二叉树的遍历,如果不能实现二叉树的遍历,那么我们连里面存放了什么数据都不知道,所以接下来我们就开始介绍二叉树的前中后序遍历
   首先我们来解释一下前中后序遍历,前序遍历就是根左右,也就是先打印当前子树中的根,再把左右孩子当成另外两颗子树,继续递归执行根左右的思想
   中序遍历就是左根右,也就是先递归打印当前根的左孩子这颗子树,然后再打印根节点,最后再递归打印当前根的右孩子这颗子树
   而后序遍历就是左右根,跟上面两种例子是同样的思想,就是先递归打印当前根的左子树,再递归打印当前根的右子树,最后再打印根
   听到这里你是不是懵了呢?这是很正常的,光听概念是很难学会递归的,我们要在实例中去应用才能掌握,所以下面实现前中后序遍历的过程和思想才是我们要重点掌握的,而不是这里前中后序遍历的概念,我们来一起学习吧!

前序遍历

   前序遍历就是左右根,打印当前子树中的根,左右孩子又分别成一颗子树,于是左右孩子又再次执行上面的根左右的遍历思想,最终这样递归下去就可以实现二叉树的前序遍历
   如果不理解可以先不管,现在我们先把代码写出来,等一下根据代码我们来画图才能将它说清楚,这也是一种学习方法,这种抽象的算法先看代码再理解,否则很难想到,之后我们才能根据理解写出类似的算法,如下:

//前序遍历
void PreOrder(BTNode* root)
{if (root == NULL){//走到空节点开始返回return;}//打印根节点printf("%c ", root->data);//递归左孩子这颗子树PreOrder(root->left);//递归右孩子这颗子树PreOrder(root->right);
}

   接着我们来画图按照这段代码的逻辑来走一遍我们的前序遍历,要仔细理解这里的图,后面才能解决我们的中后序遍历,如图:
在这里插入图片描述
   那么我们分析完前序遍历之后,我们来看看我们前序遍历代码能不能实现我们画图所诉的打印,如图:
在这里插入图片描述
   可以看到代码的运行结果和我们分析的一模一样,这就是我们的前序遍历,是我们第一次接触到递归的暴力美学,所以我们讲的很仔细,要仔细理解
   后面的中后序遍历基本上都是一个思想,所以后面的中后序遍历就不再画图了,可以自行画图来理解,思路大致相同

中序遍历

   中序遍历就是先递归打印左孩子这颗子树,然后打印根节点,最后再递归打印右孩子这颗子树,和前序遍历的思想都很接近,只是说根节点的打印不同
   中序遍历的实现和前序遍历的思想差不多,也是通过递归实现,可以自己尝试画画中序遍历的图,看看自己能不能写出来中序遍历,再来看后面的代码,这里就直接给出中序遍历的实现代码了:

//中序遍历:左根右
void InOrder(BTNode* root)
{if (root == NULL){//走到空节点开始返回return;}//递归左孩子这颗子树InOrder(root->left);//打印根节点printf("%c ", root->data);//递归右孩子这颗子树InOrder(root->right);
}

   我们来看看代码运行结果:
在这里插入图片描述
   可以看到中序遍历和前序遍历代码的实现只有一点点不同,就是打印根节点的位置不同,但是其实结果已经发生了超级多的变化,如果感兴趣可以自行画画图理解,思路和前序遍历差不多

后序遍历

   后序遍历就是先递归打印当前根的左子树,再递归打印当前根的右子树,最后再打印根,跟上面前中序遍历的思路很像
   而现在我们有了前中序遍历思想的启迪,接下来我们实现后序遍历就很简单了,很多同学可能都能直接猜到代码该怎么写,那么在这之前,还是希望大家先画图分析一下,写出代码,再来看看自己写的对不对,代码如下:

//后序遍历:左右根
void PostOrder(BTNode* root)
{if (root == NULL){//走到空节点开始返回return;}//递归左孩子这颗子树PostOrder(root->left);//递归右孩子这颗子树PostOrder(root->right);//打印根节点printf("%c ", root->data);
}

   我们来看看代码运行结果:
在这里插入图片描述
   可以看到后序遍历和前中序遍历代码的实现基本上也是差别很小,也是打印根节点的位置不同,但是其实也发生了很多的变化,希望可以自己画图理解理解,这里就不再画了,接着学习链式二叉树的下一个接口

3.链式二叉树节点的个数

   在上面我们稍微体会到了一点递归的暴力美学,从现在开始,就是真正开始爽的地方,我们就根据之前前中后序的递归思想实现这些接口,代码量都很小,但是却可以实现我们的要求,我们一起来学习
   求二叉树节点的个数不就是求当前根节点的个数,再加上左右子树节点的个数吗?所以我们可以利用递归的思想,当前根节点算1,然后加上左右子树节点的个数
   当然,我们一旦要递归就要考虑返回条件,这里的返回条件就是根节点为空,如果根节点为空了,就直接返回0,于是代码就水灵灵出来了,如下:

//二叉树节点的个数
int BinaryTreeSize(BTNode* root)
{if (root == NULL){return 0;}int leftsize = BinaryTreeSize(root->left);int rightsize = BinaryTreeSize(root->right);return 1 + leftsize + rightsize;
}

   我们来看看代码运行结果:
在这里插入图片描述
   可以看到成功算出了我们二叉树中所有节点的个数

4.链式二叉树叶子节点的个数

   求整颗二叉树叶子节点个数可以猜分为,左子树叶子节点个数加右子树叶子节点个数,这样就可以继续使用我们的递归思想了
   求叶子节点个数相当于比前面要求严格一些,不是只要根节点不为空就要算,而是根节点既不为空,并且这个根节点的左右孩子都为空,这样才算一个
   所以我们最后总结为,如果根节点为空直接返回,如果不为空并且左右孩子都为空就返回1,然后我们整颗二叉树叶子节点个数这个问题就可以拆成,左子树叶子节点个数加右子树叶子节点个数,如下:

//二叉树叶子节点的个数
int BinaryTreeLeaveSize(BTNode* root)
{if (root == NULL){return 0;}if (root->left == NULL && root->right == NULL){return 1;}int leftsize = BinaryTreeLeaveSize(root->left);int rightsize = BinaryTreeLeaveSize(root->right);return leftsize + rightsize;
}

   我们来看看代码运行结果:
在这里插入图片描述
   可以看到得出了我们想要的结果

5.链式二叉树的高度/深度

   在解决这个问题之前,我们要知道如何判断二叉树的高度,就是给我们二叉树,我们要能判断二叉树的高度,如图:
在这里插入图片描述
   我们肉眼可能一下就看出来,二叉树1的高度为4,二叉树2的高度为3,那么它们是怎么来的呢?其实二叉树的高度就是它左右子树中最高的那个,最后再加上根节点,所以我们就还是可以利用递归的算法思想,如下:

//二叉树的高度/深度
int BinaryTreeDepth(BTNode* root)
{if (root == NULL){return 0;}int leftDepth = 1 + BinaryTreeDepth(root->left);int rightDepth = 1 + BinaryTreeDepth(root->right);return leftDepth > rightDepth ? leftDepth : rightDepth;
}

   我们来看看代码运行结果:

在这里插入图片描述
   可以看到得出了我们想要的结果

6.链式二叉树第k层节点的个数

   这个需求就和上面求叶子节点个数类似,求叶子节点个数是如果左右孩子为空返回1,这里就是如果当前节点在k层就返回1
   那么如何判断这个节点是否在第k层呢?首先我们还是使用递归的算法思想,将求二叉树第k层节点的个数,转化为求二叉树左右子树的第k层节点个数的和
   具体判断方法就是,我们每递归一层就让k-1,当k变成了1,那么就说明当前节点就在第k层,这个可以自行尝试,这里就不再多说
   那么有了这个思路我们就可以直接写代码了,如下:

//⼆叉树第k层结点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{if (root == NULL){return 0;}if (k == 1){return 1;}return BinaryTreeLevelKSize(root->left, k-1) + BinaryTreeLevelKSize(root->right, k-1);
}

   我们来看看代码运行结果:
在这里插入图片描述
   可以看到程序帮我们算出了对应层次节点的个数

7.链式二叉树的查找

   这个功能我们还是可以使用递归的思想解决,我们在二叉树中查找某个节点,其实就是看当前根节点是不是要查找的节点,如果是就直接返回
   如果不是就去对应的左子树里面找,如果左子树里面找到了,就直接返回,如果左子树也没有找到,就去右子树中找,如果找到了就直接返回,如果最后左右子树都没有找到就直接返回空,如下:

//查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL){return NULL;}if (root->data == x){return root;}BTNode* left = BinaryTreeFind(root->left, x);if (left){return left;}BTNode* right = BinaryTreeFind(root->right, x);if (right){return right;}return NULL;
}

   我们来测试一下代码能否实现我们的查找功能,首先我们来找找二叉树中有的节点,如图:
在这里插入图片描述
   可以看到程序很好地完成了任务,接下来我们再测试一下如果二叉树没有这个节点会不会被找到,如图:
在这里插入图片描述
   可以看到程序最后没有找到,符合我们的预期,那么我们的查找功能就实现完毕啦

8.链式二叉树层序遍历

   接下来的二叉树的层序遍历和判断是否为完全二叉树相对于之前的结构就会难一些,因为这两个接口不能使用递归完成
   首先我们来介绍一下层序遍历,层序遍历就是按层次来访问各个节点,我们举一个例子:
在这里插入图片描述
   在这颗二叉树中,如果我们按照层序遍历打印节点,那么最后结果一定是ABCDEFGH,每个节点都按照对应的层次依次打印,这就是层序遍历
   那么怎么实现层序遍历呢?这里我也不再卖关子了,实现链式二叉树的层序遍历要使用我们之前学过的一个数据结构—队列,接下来我们就先把队列加入我们的项目
   我们可以直接将队列的头文件和实现文件添加到当前目录下,如果不会的话也可以麻烦一点去把之前写过的队列内容拷贝到我们的项目里,这里就不再多说了
   在讲解原理前,我们先把队列里面的数据类型改成我们的二叉树节点指针类型,这样才能让我们的队列存放我们的二叉树节点
   接着我们就来讲解如何使用队列实现层序遍历,方法就是从先让根节点入队列,随后我们就创建一个循环,只要队列不为空我们就循环执行以下的操作
   我们取出当前队列的头节点,然后打印里面的内容,随后将当前这个节点的左右孩子入队列,让当前节点出队列,当然,我们要注意一点的就是,如果当前节点左孩子或者右孩子为空,那么就没有必要入队列了,所以要进行一下判断
   以上就是我们层序遍历的所有思路,可以自行画图理解一下,这里我们直接根据上面的思路来写代码,如下:


//二叉树层序遍历
void LevelOrder(BTNode* root)
{Queue q;QueueInit(&q);QueuePush(&q, root);while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);printf("%c ", front->data);if (front->left){QueuePush(&q, front->left);}if (front->right){QueuePush(&q, front->right);}QueuePop(&q);}QueueDestroy(&q);
}

   我们来看看代码运行结果:
在这里插入图片描述
   可以看到程序确实帮我们按层次打印了各个节点,那么我们的层序遍历就实现完毕啦

9.判断链式二叉树是否为完全二叉树

   首先我们自己要知道如何判断一颗二叉树是不是完全二叉树,判断方法就是,保证除了最后一层以外,其它层次满了,并且保证最后一层的节点是左右依次排列的,这样才是一颗完全二叉树
   那么我们怎么用程序来判断呢?这里我们需要用到上面我们层序遍历的思想,不同的是层序遍历时不把空节点入队列,而我们这里要把空节点也入队列
   因为我们可以将判断一颗二叉树是否为完全二叉树这个问题转化为,层序遍历时遍历到最后一个节点后,接下来队列中的节点只能是空,换句话说,如果在层序遍历时碰到了空节点,那么队列后面就都只能为空,这样才是完全二叉树
   如果在如果在层序遍历时碰到了空节点,但是队列后面有非空节点,说明这颗树就不是完全二叉树,不信的话可以自己画画图,这里就不再画了,我们直接根据这个思路来写代码,判断层序遍历碰到空节点后,队列后面的节点是否都为空,如下:

//是否为完全二叉树
bool BinaryTreeComplete(BTNode* root)
{Queue q;QueueInit(&q);QueuePush(&q, root);while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);if (front == NULL){break;}QueuePush(&q, front->left);QueuePush(&q, front->right);QueuePop(&q);}while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);if (front){return false;}QueuePop(&q);}QueueDestroy(&q);return true;
}

   我们来看看代码运行结果:
在这里插入图片描述
   可以看到程序成功帮我们判断出当前二叉树是一颗完全二叉树,也可以自行创建一颗非完全二叉树试试,也没有问题

10.链式二叉树的销毁

   由于我们链式二叉树的节点都是动态申请的,所以我们要将它们进行释放,否则会造成内存泄漏,要一个一个地销毁节点,说明我们要遍历整颗二叉树,我们上面学过的遍历方法就起到作用了
   我们就可以直接选择后序遍历来释放节点,先释放左右子树,最后释放掉我们的根节点,并且将根节点置空,如下:

//二叉树的销毁
void BinaryTreeDestroy(BTNode** proot)
{if (*(proot) == NULL){return;}BinaryTreeDestroy(&(*proot)->left);BinaryTreeDestroy(&(*proot)->right);free(*proot);*proot = NULL;
}

三、源码

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "Queue.h"typedef char BTDataType;typedef struct BinaryTreeNode
{BTDataType data;struct BinaryTreeNode* left;struct BinaryTreeNode* right;
}BTNode;//前序遍历
void PreOrder(BTNode* root)
{if (root == NULL){return;}printf("%c ", root->data);PreOrder(root->left);PreOrder(root->right);
}//中序遍历
void InOrder(BTNode* root)
{if (root == NULL){return;}InOrder(root->left);printf("%c ", root->data);InOrder(root->right);
}//后序遍历
void PostOrder(BTNode* root)
{if (root == NULL){return;}PostOrder(root->left);PostOrder(root->right);printf("%c ", root->data);
}//二叉树节点个数
int BinaryTreeSize(BTNode* root)
{if (root == NULL){return 0;}return 1 + BinaryTreeSize(root->left) + BinaryTreeSize(root->right);
}//二叉树叶子节点个数
int BinaryTreeLeaveSize(BTNode* root)
{if (root == NULL){return 0;}if (root->left == NULL && root->right == NULL){return 1;}return BinaryTreeLeaveSize(root->left) + BinaryTreeLeaveSize(root->right);
}//⼆叉树第k层结点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{if (root == NULL){return 0;}if (k == 1){return 1;}return BinaryTreeLevelKSize(root->left, k-1) + BinaryTreeLevelKSize(root->right, k-1);
}//二叉树高度
int BinaryTreeDepth(BTNode* root)
{if (root == NULL){return 0;}int leftDepth = 1 + BinaryTreeDepth(root->left);int rightDepth = 1 + BinaryTreeDepth(root->right);return leftDepth > rightDepth ? leftDepth : rightDepth;
}//查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL){return NULL;}if (root->data == x){return root;}BTNode* left = BinaryTreeFind(root->left, x);if (left){return left;}BTNode* right = BinaryTreeFind(root->right, x);if (right){return right;}return NULL;
}//二叉树的销毁
void BinaryTreeDestroy(BTNode** proot)
{if (*(proot) == NULL){return;}BinaryTreeDestroy(&(*proot)->left);BinaryTreeDestroy(&(*proot)->right);free(*proot);*proot = NULL;
}//二叉树层序遍历
void LevelOrder(BTNode* root)
{Queue q;QueueInit(&q);QueuePush(&q, root);while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);printf("%c ", front->data);if (front->left){QueuePush(&q, front->left);}if (front->right){QueuePush(&q, front->right);}QueuePop(&q);}QueueDestroy(&q);
}//是否为完全二叉树
bool BinaryTreeComplete(BTNode* root)
{Queue q;QueueInit(&q);QueuePush(&q, root);while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);if (front == NULL){break;}QueuePush(&q, front->left);QueuePush(&q, front->right);QueuePop(&q);}while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);if (front){return false;}QueuePop(&q);}QueueDestroy(&q);return true;
}

   那么今天二叉树链式结构的定义与实现就结束啦,后面我们讲完链式二叉树的一些OJ题后初阶数据结构就差不多结束了,可以进入我们的排序算法了,敬请期待吧!
   bye~

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

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

相关文章

基于Pyhton的人脸识别(Python 3.12+face_recognition库)

使用Python进行人脸编码和比较 简介 在这个教程中&#xff0c;我们将学习如何使用Python和face_recognition库来加载图像、提取人脸编码&#xff0c;并比较两个人脸是否相似。face_recognition库是一个强大的工具&#xff0c;它基于dlib的深度学习模型&#xff0c;可以轻松实…

RabbitMq死信队列延迟交换机

架构图 配置 package com.example.demo.config;import org.springframework.amqp.core.*; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;Configuration public class DeadLetterConfig {public String …

十、JavaScript的应用的习题

题目一 在网页中显示一个工作中的 “ 数字时钟 ”&#xff0c;如图所示 运行效果 代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>动态时钟</title><style>.all{width: 660px;height: 350px;margin: 60p…

leetcode 1853 转换日期格式(postgresql)

需求 表: Days ----------------- | Column Name | Type | ----------------- | day | date | ----------------- day 是这个表的主键。 给定一个Days表&#xff0c;请你编写SQL查询语句&#xff0c;将Days表中的每一个日期转化为"day_name, month_name day, year"…

Day26颜色分类

给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums &#xff0c;原地 对它们进行排序&#xff0c;使得相同颜色的元素相邻&#xff0c;并按照红色、白色、蓝色顺序排列。 我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。 必须在不使用库内置的 sort 函数的情况下解决…

网络——HTTP与HTTPS三次握手和四次挥手

HTTP协议本身并不直接处理TCP连接的建立和关闭&#xff0c;这些是由底层的TCP协议来完成的。但是&#xff0c;由于HTTP通常运行在TCP之上&#xff0c;因此理解TCP的三次握手&#xff08;用于建立连接&#xff09;和四次挥手&#xff08;用于关闭连接&#xff09;对于理解HTTP通…

使用历史索引监控 Elasticsearch 索引生命周期管理

作者&#xff1a;来自 Elastic Stef Nestor 大家好&#xff01;在之前的一篇博客中&#xff0c;我们概述了常见的索引生命周期管理 (index lifecycle management - ILM) 问题及其解决方案。此后&#xff0c;我们已将这些常见场景添加到我们的 Elasticsearch 文档中&#xff0c;…

详尽的oracle sql函数

1&#xff0c;CHR 输入整数&#xff0c;返回对应字符。 用法&#xff1a;select chr(65),chr(78) from dual; 2&#xff0c;ASCII 输入字符&#xff0c;返回对应ASCII码。 用法&#xff1a;select ascii(A),ascii(B) from dual; 3&#xff0c;CONCAT 输入两个字符串&#xff0c…

Android 单元测试断言校验方法 org.junit.Assert

判断布尔值 assertTrue assertFalse 判断对象非空 assertNull(object); 案例&#xff1a; PersistableBundle result Util.getCarrierConfig(mockContext, subId);assertNull(result); 判断是否相等 assertEquals("mocked_string", result.toString()); package or…

Python语法之正则表达式详解以及re模块中的常用函数

正则表达式详解及re模块中的常用函数 概念、作用和步骤 概念&#xff1a; 本身也是一个字符串&#xff0c;其中的字符具有特殊含义&#xff0c;将来我们可以根据这个字符串【正则表达式】去处理其他的字符串&#xff0c;比如可以对其他字符串进行匹配&#xff0c;切分&#xf…

Linux 查看系统资源常用命令

目录 Linux 查看系统资源常用命令 一、top 二、htop 三、vmstat 四、iostat 五、mpstat 六、free 七、sar 八、ps 九、pstree 十、lsof 十一、uptime 十二、dmesg 十三、dmidecode 十四、lsblk 十五、blkid 十六、fdisk -l 十七、parted -l 十八、df -h 十…

【计算机网络】实验4:生成树协议STP的功能以及虚拟局域网VLAN

实验 4&#xff1a;生成树协议STP的功能以及虚拟局域网VLAN 一、 实验目的 加深对生成树协议STP的功能的理解。 了解虚拟局域网VLAN。 二、 实验环境 • Cisco Packet Tracer 模拟器 三、 实验内容 1、验证交换机生成树协议STP的功能 (1) 第一步&#xff1a;构建网络拓…

Linux中的常用基本指令(下)

Linux常用基本指令 Linux中的基本指令12.head指令13.tail指令简单解释重定向与管道(重要) 14.date指令(时间相关的指令)15.cal指令(不重要)16.find指令(灰常重要&#xff09;17.grep指令(重要)18.which指令和alias指令19.zip/unzip指令&#xff1a;20.tar指令&#xff08;重要&…

服务器数据恢复—硬盘掉线导致热备盘同步失败的RAID5阵列数据恢复案例

服务器存储数据恢复环境&#xff1a; 华为S5300存储中有12块FC硬盘&#xff0c;其中11块硬盘作为数据盘组建了一组RAID5阵列&#xff0c;剩下的1块硬盘作为热备盘使用。基于RAID的LUN分配给linux操作系统使用&#xff0c;存放的数据主要是Oracle数据库。 服务器存储故障&#…

Vue+vite 组件开发的环境准备

一.nodejs安装 进入Node.js 官网&#xff08;Node.js — Run JavaScript Everywhere&#xff09;&#xff0c;点击下载。 双击打开&#xff0c;进行安装 双击打开后&#xff0c;点击 next&#xff08;下一步&#xff09;,后面也是一直点击 next 无其他设置&#xff0c;直到 …

20241129解决在Ubuntu20.04下编译中科创达的CM6125的Android10出现找不到库文件libtinfo.so.5的问题

20241129解决在Ubuntu20.04下编译中科创达的CM6125的Android10出现找不到库文件libtinfo.so.5的问题 2024/11/29 20:41 缘起&#xff1a;中科创达的高通CM6125开发板的Android10的编译环境需要。 [ 11% 15993/135734] target Java source list: vr [ 11% 15994/135734] target …

react 路由鉴权

权限路由一般两种 1中接口中返回菜单 2 接口中返回权限&#xff0c;前端做匹配 一般都是那种结合&#xff0c;react中没有vue那种钩子函数如何做&#xff1f; 在项目中写一个高阶函数&#xff0c;在高阶函数中判断权限、是否登录等操作app.tsx或者man.tsx中使用 《AuthRouter》…

k8s集群中金丝雀发布 + 声明式资源管理yaml

一、K8S常见的发布方式 旨在降低发布风险并提高发布速度 1、蓝绿发布 两套环境&#xff08;设备&#xff09;交替升级&#xff0c;旧版本保留一定时间便于回滚 优点&#xff1a;对用户无感&#xff0c;是最安全的发布方式&#xff0c;业务稳定 缺点&#xff1a;需要两套系统&…

openssl的运用

一、概述 Opssl是一个用于TLS/SSL协议的工具包&#xff0c;也是一个通用密码库。 包含了国密sm2 sm3 sm4&#xff0c;包含了对称加密&#xff0c;非对称加密&#xff0c;单项散列&#xff0c;伪随机、签名&#xff0c;密码交换&#xff0c;证书等一些算法库。 为了深层次的学习…

基于SpringBoot+Vue的靓车汽车销售网站-无偿分享 (附源码+LW+调试)

目录 1. 项目技术 2. 功能菜单 3. 部分功能截图 4. 研究背景 5. 研究目的 6. 可行性分析 6.1 技术可行性 6.2 经济可行性 6.3 操作可行性 7. 系统设计 7.1 概述 7.2 系统流程和逻辑 7.3 系统结构 8. 数据库设计 8.1 数据库ER图 &#xff08;1&#xff09;材料分…