C语言最终文章-二叉树

文章目录

  • 前言
  • 二叉树的性质
  • 二叉树的存储方式
    • 顺序存储
      • 堆及其应用
      • TopK问题
      • 堆排序
    • 链式存储
      • 二叉树的练习
        • 1.二叉树查找值为x的节点
        • 2.判断是否为完全二叉树
        • LC226.翻转二叉树
        • [LC572. 另一棵树的子树](https://leetcode.cn/problems/subtree-of-another-tree/description/)
        • 两道选择题
  • 结言

前言

  • 这篇文章大概就是我C语言学习的最后一篇文章了。

本篇文章主要内容:

  • 二叉树的几个性质,堆、堆排序和用堆实现TopK问题。
  • 向上建堆和向下建堆
  • 二叉树的练习

二叉树原图:

在这里插入图片描述

二叉树的性质

开始讲二叉树时,我们先来学一下二叉树的重要性质。

1.对于任意二叉树: n 0 = n 2 + 1 n0 = n2+1 n0=n2+1 (其中 n0代表度为0的个数,n2代表度为2的节点个数)
2. N − 1 = n 0 ∗ 0 + n 1 ∗ 1 + n 2 ∗ 2 + . . . . N-1 =n0*0+n1*1+n2*2+.... N1=n00+n11+n22+.... (N-1代表边的个数)
3. 对于满二叉树来说,二叉树节点个数 = 2 h − 1 2^h-1 2h1 (h为二叉树的高度)

先来看第一条 n 0 = = n 2 + 1 ? n0 ==n2+1? n0==n2+1

来让我们想一想二叉树是如何构建的呢?

首先我们要明白一件事: 首先我们要明白一件事: 首先我们要明白一件事: 度为1的是有度为0的节点增加一个分支得来的,度为2的是由度为1的节点增加一个分支得来的。

一开始我们只有一个根节点,那么我们的 n 0 = 1 n0=1 n0=1,当我们增加一个度为1的

节点时,那么此时我们的 n 0 还是 = 0 , n 1 = 1 n0还是 = 0,n1=1 n0还是=0n1=1,当我们增加一个度为2的时候
n 0 − > 2 , n 1 − > 0 , n 2 − > 1 n0->2,n1->0,n2->1 n0>2n1>0n2>1

过程如下图:
在这里插入图片描述
那我们不难发现,我们的 n 0 = n 2 + 1 n0=n2+1 n0=n2+1 这个条件始终成立,只要我们增加一个度为2的节点,那么n0肯定会增加一个。

再来看第二条,对与一棵树而言,子数肯定也是一棵树,两个兄弟节点之间也
不会有连线。那么 N 个节点就可以形成 N-1 条边。而 n0 有有0条边,n1有1条边…,那么总的边数 N-1 就可以得出来第二条的公式。

第三条

- 对于一个满二叉树来说
在这里插入图片描述

  • 第一层节点个数: 2 0 2^0 20
  • 第二层节点个数: 2 1 2^1 21
  • 第三层节点个数: 2 2 2^2 22
  • 第四层节点个数: 2 3 2^3 23

那么如果一个h层的满二叉树它的节点总数 T(N) = 2 0 + 2 1 + 2 2 + . . . + 2 h − 1 2^0+2^1+2^2+...+2^{h-1} 20+21+22+...+2h1

所以 T ( N ) = 2 h − 1 T(N) = 2^{h}-1 T(N)=2h1

二叉树的存储方式

顺序存储

顺序存储本质上就是用数组存。这里我们理解一下完全二叉树和满二叉树

  • 满二叉树:各层的节点都是满的状态-就如上面那个图一样如上图
  • 完全二叉树:前 h-1层都是满的,第h层从右向左连续去掉节点。这就相当于,在最后一层它的节点必须是连续的。
    在这里插入图片描述
    理解完这两个概念之后,如果我们把这些二叉树的节点都放入数组中会怎么样呢? 如图:
    在这里插入图片描述
    当我们把树的节点都放入数组中后,我们发现双亲节点和它的左孩子和右孩子之间存在这么一个关系。
  • l c h i l d i = 2 ∗ p a r e n t i + 1 , r c h i l d i = 2 ∗ p a r e n t i + 2 lchild_i = 2*parent_i+1,rchild_i = 2*parent_i+2 lchildi=2parenti+1rchildi=2parenti+2
  • p a r e n t i = ( ( l , r ) c h i l d i − 1 ) / 2 parent_{i} = ((l,r)child_i-1)/2 parenti=((l,r)childi1)/2

注意: 这个规则只对完全二叉树和满二叉树使用,当然其他的二叉树我们也可以这么存储,只不过途中我们要把位置空出来,这样比较浪费空间,所以我们会使用下面的链式存储。

堆及其应用

当我们对顺序存储有了以上的了解后,我们就可以来实现堆了。注意这里的堆跟操作系统的堆可不一样,我们这里只是一个数据结构。

堆的操作:

  • 入堆
  • 出堆顶元素
  • 取堆顶元素
  • 判空

堆可以用来做什么呢?
比如:排出中国最有钱的前10个人,堆排序等等。

这里先介绍两个概念:

  • 大堆:堆顶元素比其他元素大
  • 小堆:堆顶元素比其他元素小

为什么要有这两个堆呢?

同时注意:大堆和小堆并不意味着有序。

如下图:大堆和小堆,只能说明堆顶元素,一定比其他元素大,由于二叉树左子树和右子树是两个子树。子树和树具有相同的性质

  • 对于大堆而言: 左子树也是大堆,右子树也是大堆,那么左子树的左子树也是大堆…
    在这里插入图片描述
    如果你要排升序的话,利用堆排大堆还是小堆呢呢?

如果排小堆,那么每次堆顶就是我们的最小元素,但是然后怎么排呢?这样剩
下的元素就不一定是小堆了。所以当我们排升序的时候我们排大堆,直接把堆顶元素与最后一个位置的元素交换,注意这时我们下面的子树并没有受影响,所以我们直接再排一次大堆就可以了。然后不断的排,数组就有序了。

下面我们都以建大堆为例:

先来说入堆

入堆的话,我们需要用到向上调整算法

算法演示如下:
在这里插入图片描述
当我们插入一个新元素后,不断地去找双亲节点判断大小,如果比双亲的值大

那么就交换,否则就不交换。

代码:

void ADjustUp(HpDataType* a, int n)
{int child = n - 1;int parent = (n - 1 - 1) / 2;while (parent >= 0){if (a[child] > a[parent]) //大的往上调{swap(&a[parent], &a[child]);child = parent;parent = (child - 1) / 2;}elsebreak;}
}
void HpPush(Hp* hp, HpDataType x)
{assert(hp);check_capacity(hp); //检查容量hp->a[hp->size] = x;hp->size++;ADjustUp(hp->a,hp->size); // 开区间
}

出堆顶元素

这里我们就要用到 向下调整算法:,由于我们必须保证树是一个大堆,所以每次把堆顶元素Pop调后,要保证树还是一个大堆。

这里我们直接把堆顶 a[0] 与 最后一个元素交换。我们本质上还是数组。
然后再用一次向下调整算法即可。

向下调整算法过程如图:
在这里插入图片描述
代码:

void AdjustDown(HpDataType* a, int begin, int end)
{int parent = begin;int child = 2 * parent + 1;while (child < end){if (child + 1 < end && a[child] > a[child + 1]){child += 1;}if (a[parent] > a[child]){swap(&a[parent], &a[child]);parent = child;child = 2 * parent + 1;}elsebreak;}
}
//出堆
void HpPop(Hp* hp)
{assert(hp && hp->size > 0);swap(&hp->a[0],&hp->a[hp->size-1]);//此时这个位置就不能才排了hp->size--;AdjustDown(hp->a,0,hp->size); }

堆的总代码:

typedef int HpDataType;
typedef struct Heap
{HpDataType* a;int size;int capacity;
}Hp;//初始化堆
void HpInit(Hp* hp);
//销毁堆
void HpDestory(Hp* hp);
//入堆
void HpPush(Hp* hp, HpDataType x);
//出堆
void HpPop(Hp* hp);
//判空
bool HpEmpty(Hp* hp);
//堆顶元素
HpDataType HpTop(Hp* hp);
//向下
void AdjustDown(HpDataType* a, int begin, int end);void swap(HpDataType* e1, HpDataType* e2);void swap(HpDataType* e1, HpDataType* e2)
{HpDataType tmp = *e1;*e1 = *e2;*e2 = tmp;
}//初始化堆
void HpInit(Hp* hp)
{hp->size = 0;hp->capacity = 4;hp->a = (HpDataType*)malloc(sizeof(HpDataType) * (hp->capacity));if (hp->a == NULL){perror("malloc fail!\n");exit(-1);}
}
//销毁堆
void HpDestory(Hp* hp)
{hp->size = hp->capacity = 0;free(hp->a);
}
void check_capacity(Hp* hp)
{if (hp->capacity == hp->size){HpDataType* ptr = (HpDataType*)realloc(hp->a, sizeof(HpDataType) * (hp->capacity * 2));if (ptr == NULL){printf("realloc fail!\n");exit(-1);}hp->capacity *= 2;hp->a = ptr;}
}//排倒序 - 建大堆
void ADjustUp(HpDataType* a, int n)
{int child = n - 1;int parent = (n - 1 - 1) / 2;while (parent >= 0){if (a[child] > a[parent]) //大的往上调{swap(&a[parent], &a[child]);child = parent;parent = (child - 1) / 2;}elsebreak;}
}
//入堆
void HpPush(Hp* hp, HpDataType x)
{assert(hp);check_capacity(hp);hp->a[hp->size] = x;hp->size++;ADjustUp(hp->a,hp->size); // 开区间
}
//堆顶元素
HpDataType HpTop(Hp* hp)
{assert(hp && hp->size > 0);return hp->a[0];
}
//建大堆
void AdjustDown(HpDataType* a, int begin, int end)
{int parent = begin;int child = 2 * parent + 1;while (child < end){if (child + 1 < end && a[child] > a[child + 1]){child += 1;}if (a[parent] > a[child]){swap(&a[parent], &a[child]);parent = child;child = 2 * parent + 1;}elsebreak;}
}
//出堆
void HpPop(Hp* hp)
{assert(hp && hp->size > 0);swap(&hp->a[0],&hp->a[hp->size-1]);//此时这个位置就不能才排了hp->size--;AdjustDown(hp->a,0,hp->size); }
//判空
bool HpEmpty(Hp* hp)
{return hp->size == 0;
}

TopK问题

现在有一个问题

  • 你只有1KB的空间,如何把在4G的文件(假设都是整数)中找出前K(K > 0)大的数字
    既然我们学的是堆,肯定使用堆来解决,如果没有空间限制的话,我们可以把数据都读到内存中,然后排K次大堆即可。可关键我们只有1KB(1024byte)的空间,那如何做呢?

在这里插入图片描述
排成小堆后,堆顶元素就是最小值,每次读入一个比堆顶大的数据,读到最后就是前K个最大的数据了。

代码实现:

#define N 100000 //这里以 10万个数据为例子。
//创建数据
void CreatData()
{FILE* fin = fopen("data.txt", "w");if (fin == NULL){perror("fopen fail!\n");exit(-1);}int i = 0;srand(time(0));for (i = 0; i < N; i++){int x = (rand() + i) % 10000;fprintf(fin,"%d\n", x);}fclose(fin);
}//要求:只给你1KB空间,排出4G个整数的前K个最大值
void TopK()
{FILE* fout = fopen("data.txt","r");if (fout == NULL){perror("fopen fail!\n");exit(-1);}int k;printf("请输入k>: ");scanf("%d", &k);int i = 0;int* KminArr = (int*)malloc(sizeof(int) * k);//读取K个数建最小堆for (i = 0; i < k; i++){fscanf(fout,"%d",&KminArr[i]);}int x = 0;while (fscanf(fout, "%d", &x) > 0){if (x > KminArr[0]){KminArr[0] = x;AdjustDown(KminArr,0,k);}}HeapSort(KminArr,k);//前k个最大值printf("前%d个最大值为:", k);for (i = 0; i < k; i++){printf("%d ", KminArr[i]);}printf("\n");
}

堆排序

当我们了解了向上和向下两种算法的时候,我们就可以来实现啊堆排序了。

如果给你这样一个数组,如何排序呢?
在这里插入图片描述
思路:

建大堆,不断交换堆顶和数组最后一个位置的元素,然后再对剩下的数字进行向下调整算法。直到数组有序为止。

关键就是,我们如何去建大堆呢,前面我们讲堆的时候,那数组经过向上调整算法之后,本来就是一个大堆(ps:建大堆的前提就是源数据也是大堆)。那我们拿到一个随机的数组之后如何建大堆呢?

  • 以最后一个非叶子节点为开始,不断向下调整,直到达到堆顶,此时即为大堆。

在这里插入图片描述
建完大堆之后,不断交换堆顶和数组最后一个位置的元素,然后再对剩下的数字进行向下调整算法。

总代码:

void HeapSort(int* a, int n)
{int i = 0;for (i = (n - 1 - 1) / 2; i >= 0; i--){AdjustDown(a,i,n);}int end = n - 1;while (end > 0){swap(&a[end],&a[0]);AdjustDown(a,0,end);end--;}
}void PrintArray(int* a, int n)
{for (int i = 0; i < n; i++){printf("%d ", a[i]);}printf("\n");
}
void TestHeapSort()
{int a[] = { 6,1,3,8,9,3,2,5,10,7 };int sz = sizeof(a) / sizeof(a[0]);HeapSort(a,sz);PrintArray(a,sz);
}

那么堆排序的时间复杂度是多少呢?

我们先来看一下建堆的复杂度:
在这里插入图片描述
建堆是 O(N),下面交换以及排大堆是 N*LOGN,按照大O渐进表示法,我们堆排序的时间复杂度为: O ( N ∗ L O G N ) O(N*LOGN) O(NLOGN)

再来看一下向上调整算法,建堆的复杂度:

在这里插入图片描述
这也是为什么我们不用向上调整算法的原因。

链式存储

先来看一下链式二叉树如何定义。
在这里插入图片描述
每一个节点我们都有数据和左孩子和右孩子。直接看遍历方式

链式二叉树有那么四种遍历方式,他们的访问方式为:

  • 前序遍历: 根 − > 左子树 − > 右子树 根->左子树->右子树 >左子树>右子树
  • 中序遍历: 左子树 − > 根 − > 右子树 左子树->根->右子树 左子树>>右子树
  • 后序遍历: 左子树 − > 右子树 − > 根 左子树->右子树->根 左子树>右子树>

很明显,这三种遍历方式很适合用递归来解决。
再来看一下层序遍历 (以上面大堆结果为例):

在这里插入图片描述
然后再挨个把队列的元素,Pop完就可以了,由于我们现在队列的元素是树的节点,所以最后队列里面全是 N U L L NULL NULL

  • 层序遍历的结果:就是按照层次把树中的元素打印出来。这里我们打印的就为 10 − > 9 − > 3 − > 8 − > 7 − > 3 − > 2 − > 5 − > 1 − > 6 10->9->3->8->7->3->2->5->1->6 10>9>3>8>7>3>2>5>1>6

代码实现:

// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root)
{if (root == NULL)return;printf("%c ", root->_data);BinaryTreePrevOrder(root->_left);BinaryTreePrevOrder(root->_right);
}
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{if (root == NULL)return;BinaryTreePrevOrder(root->_left);printf("%c ", root->_data);BinaryTreePrevOrder(root->_right);
}
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{if (root == NULL)return;BinaryTreePrevOrder(root->_left);BinaryTreePrevOrder(root->_right);printf("%c ", root->_data);
}
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{Queue q;QueueInit(&q);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.二叉树查找值为x的节点

思路:

  • 如果此时我们这个节点的值 == 我们要找的值,直接返回即可。
  • 如果不等于取左右子树去找
  • 返回其中一个答案。

代码:

// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL)return NULL;if (root->_data == x)return root;BTNode* left = BinaryTreeFind(root->_left,x);BTNode* right = BinaryTreeFind(root->_right,x);return left == NULL ? right : left;
}
2.判断是否为完全二叉树

思路:

非完全二叉树我们测序遍历的时候跟完全二叉树有什么区别呢?

在这里插入图片描述
那就是我们会入空值进去,所以当我们取队头元素去到空值的时候,我们要判断如果队列中出现了非空的值,那就说明这时一个非完全二叉树。

代码:

// 判断二叉树是否是完全二叉树
bool BinaryTreeComplete(BTNode* root)
{Queue q;QueueInit(&q);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);if (front != NULL)return false;QueuePop(&q);}QueueDestroy(&q);return true;
}
LC226.翻转二叉树

在这里插入图片描述
思路:

  • 翻转二叉树是把左子树和右子树互换,那么我们每一个子树都要互换。所以我们要不断往子树递归把子树的左子树和右子树交换。这就跟我们的层序遍历一样。

所以我们要递归左右子树,最后再把左右子树交换,然后再返回root。

代码:

struct TreeNode* invertTree(struct TreeNode* root) {if (root == NULL)return NULL;struct TreeNode* left = invertTree(root->left);struct TreeNode* right = invertTree(root->right);root->right = left;root->left = right;return root;
}

在这里插入图片描述

LC572. 另一棵树的子树
  • 建议先做一下这道题100. 相同的树

这题其实就是去找和 subRoot 相同的子树。

注意这个例子:我们要保证我们找的 root和 subRoot 左右子树都相同。
所以这时我们要遍历的root的左子树才能判断与subRoot相同。
在这里插入图片描述
思路:

  • 如果 r o o t 和 s u b R o o t 都为 N U L L ,直接返回 t r u e root和subRoot都为NULL,直接返回true rootsubRoot都为NULL,直接返回true,如果只有一个为空,返回false,如果此时两个树的val相同,判断此时这个位置是否相同,如果相同直接返回true,不想同去root的左右子树,继续去找。只要找到一个就返回true。

代码:

bool isSameTree(struct TreeNode* p, struct TreeNode* q) {if (p == NULL && q == NULL)return true;    if (p == NULL || q == NULL)return false;if (p->val != q->val)return false;return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
}bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){if (root == NULL && subRoot == NULL)return true;if (root == NULL || subRoot == NULL)return false;if (root->val == subRoot->val){if (isSameTree(root,subRoot))return true;}return isSubtree(root->left,subRoot) || isSubtree(root->right,subRoot);
}
两道选择题

在这里插入图片描述
在这里插入图片描述

结言

到这里本篇文章就结束了。

本篇文章的基本思路如下:
在这里插入图片描述
OK,二叉树部分就到这吧,学C++去了。
在这里插入图片描述

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

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

相关文章

单片机建立自己的库文件(4)

文章目录 前言一、新建自己的外设文件夹1.新建外设文件夹&#xff0c;做项目好项目文件管理2.将之前写的.c .h 文件添加到文件夹中 二、在软件中添加项目 .c文件2.1 编译工程保证没问题2. 修改项目列表下的名称 三、在软件项目中添加 .h文件路径四、实际使用测试总结 前言 提示…

Stable Diffusion文生图模型训练入门实战(完整代码)

Stable Diffusion 1.5&#xff08;SD1.5&#xff09;是由Stability AI在2022年8月22日开源的文生图模型&#xff0c;是SD最经典也是社区最活跃的模型之一。 以SD1.5作为预训练模型&#xff0c;在火影忍者数据集上微调一个火影风格的文生图模型&#xff08;非Lora方式&#xff…

创新实训2024.06.17日志:大模型微调总结

前段时间其实我们已经部署了大模型&#xff0c;并开放了对外的web接口。不过由于之前某几轮微调实验的大模型在对话时会有异常表现&#xff08;例如响应难以被理解&#xff09;&#xff0c;因此我在项目上线后&#xff0c;监控了数据库里存储的对话记录。确定了最近一段时间部署…

多叉树的DFS深度优先遍历,回溯法的基础算法之一

一、前言 多叉树一般用于解决回溯问题。 想必大家都学过二叉树&#xff0c;以及二叉树的深度优先遍历和广度优先遍历&#xff0c;我们思考&#xff1a;能不能将二叉树的DFS转化为多叉树的DFS&#xff1f; 二、多叉树的结构 多叉树的本质&#xff0c;就是一棵普通的树&#x…

【秋招突围】2024届秋招笔试-小红书笔试题-第三套-三语言题解(Java/Cpp/Python)

&#x1f36d; 大家好这里是清隆学长 &#xff0c;一枚热爱算法的程序员 ✨ 本系计划跟新各公司春秋招的笔试题 &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f497; &#x1f4e7; 清隆这边…

Redis作者长文总结LLMs, 能够取代99%的程序员

引言 这篇文章并不是对大型语言模型&#xff08;LLMs&#xff09;的全面回顾。很明显&#xff0c;2023年对人工智能而言是特别的一年&#xff0c;但再次强调这一点似乎毫无意义。相反&#xff0c;这篇文章旨在作为一个程序员个人的见证。自从ChatGPT问世&#xff0c;以及后来使…

如何用多线程执行 unittest 测试用例实现方案

前言 使用python做过自动化测试的小伙伴&#xff0c;想必都知道unittest和pytest这两个单元测试框架&#xff0c;其中unittest是python的官方库&#xff0c;功能相对于pytest来要逊色不少&#xff0c;但是uniitest使用上手简单&#xff0c;也受到的很多的小伙伴喜爱。一直以来都…

自然语言处理学习路线(1)——NLP的基本流程

NLP基本流程 【NLP基本流程】 0. 获取语料 1. 语料预处理 2. 特征工程&选择 3. 模型训练 4. 模型输出&上线 【NLP基本流程图】 Reference 1. 自然语言处理(NLP)的一般处理流程&#xff01;-腾讯云开发者社区-腾讯云 2. https://zhuanlan.zhihu.com/p/55…

leetcode 1355 活动参与者(postgresql)

需求 表: Friends ---------------------- | Column Name | Type | ---------------------- | id | int | | name | varchar | | activity | varchar | ---------------------- id 是朋友的 id 和该表的主键 name 是朋友的名字 activity 是朋友参加的活动的名字 表: Activit…

【每日刷题】Day67

【每日刷题】Day67 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 23. 合并 K 个升序链表 - 力扣&#xff08;LeetCode&#xff09; 2. 1189. “气球” 的最大数量 - …

动力学笔记01——共振频率和共振带的数学定义

文章目录 0、背景描述1、正文2. 位移、速度、加速度的共振频率并不相同 0、背景描述 过去一年&#xff0c;我基本都在考虑塔架&#xff08;尤其是混塔&#xff09;频率仿真/模态分析的问题。关于这个问题&#xff0c;不仅有地基刚度&#xff0c;还有塔筒本身以及其他影响频率的…

MAC认证

简介 MAC认证是一种基于接口和MAC地址对用户的网络访问权限进行控制的认证方法&#xff0c;它不需要用户安装任何客户端软件。设备在启动了MAC认证的接口上首次检测到用户的MAC地址以后&#xff0c;即启动对该用户的认证操作。认证过程中&#xff0c;不需要用户手动输入用户名…

Linux ubuntu安装pl2303USB转串口驱动

文章目录 1.绿联PL2303串口驱动下载2.驱动安装3.验证方法 1.绿联PL2303串口驱动下载 下载地址&#xff1a;https://www.lulian.cn/download/16-cn.html 也可以直接通过CSDN下载&#xff1a;https://download.csdn.net/download/Axugo/89447539 2.驱动安装 下载后解压找到Lin…

R语言dplyr统计指定列里面种类个数和比例

输入数据框&#xff1a;dfuorf&#xff0c;Type列有uORF和overlpaORF两种类型 dfuorf1 <- dfuorf %>%group_by(Type) %>% summarise(Countn()) %>% mutate(percentCount/sum(Count)) %>% mutate(percent1 (paste0(round((Count/sum(Count)), 2)*100,"%&…

编码在网络安全中的应用和原理

前言:现在的网站架构复杂&#xff0c;大多都有多个应用互相配合&#xff0c;不同应用之间往往需要数据交互&#xff0c;应用之间的编码不统一&#xff0c;编码自身的特性等都很有可能会被利用来绕过或配合一些策略&#xff0c;造成一些重大的漏洞。 什么是编码&#xff0c;为什…

货代小白快来收藏‼️普货与非普货的区别

普货是指不属于以下类别的普通货物 危险品 冷冻/冷藏品 违禁品 仿牌货 敏感货 危险品 危险品具体分为九类&#xff1a; 爆炸品 压缩气体 易燃液体 易燃固体、易燃物品和遇湿易燃物品 氧化剂和有机氧化物 有毒和感染性物品 放射性 腐蚀性 杂类 冷冻/冷藏品 主要是指以食品为主的…

海康视觉算法平台VisionMaster 4.3.0 C# 二次开发01 加载方案并获取结果

前言 第一次使用海康视觉算法平台VisionMaster 4.3.0&#xff0c;项目中要使用这个平台进行视觉处理并获取结果。 运行效果 开发环境 C#&#xff0c; WPF&#xff0c; vs2022, 海康视觉算法平台VisionMaster 4.3.0 基本概念 上图这些.sol为后缀的是vm的方案文件。 打开方案文…

海南云亿商务咨询有限公司助力商家腾飞新高度

在数字化浪潮席卷全球的今天&#xff0c;电商行业正迎来前所未有的发展机遇。海南云亿商务咨询有限公司&#xff0c;作为抖音电商服务的佼佼者&#xff0c;凭借其专业的团队和丰富的经验&#xff0c;正成为越来越多企业实现电商转型与升级的得力助手。 海南云亿商务咨询有限公…

AI写代码,CS还有前途吗?加州大学伯克利分校:CDSS申请人数激增48%!

目录 01 CS入学人数暴涨 02 人类Coder可堪大任 03 AI还没有学会创新 04 编程与农耕不同 AI写了这么多代码&#xff0c;你还应该学习计算机科学吗&#xff1f; 新的数据显示&#xff0c;学生们仍然热衷于选修计算机科学&#xff1a;加州大学伯克利分校&#xff08;UCB&#…

Python基础用法 之 转义字符

将两个字符进⾏转义 表示⼀个特殊的字符 \n ---> 换⾏&#xff0c;回⻋ \t ---> 制表符, tab键 注意&#xff1a; print( end\n)&#xff1a; print() 函数中默认有⼀个 end\n, 所以,每个 print 结束之后, 都会输出⼀ 个换行。 未完待续。