【数据结构】24王道考研笔记——树与二叉树

news2024/9/27 15:32:40

五、树与二叉树

目录

  • 五、树与二叉树
    • 树的基本概念
    • 二叉树的概念
      • 基础概念
      • 常考性质
      • 存储方式
    • 二叉树遍历及线索二叉树
      • 前中后以及层次遍历
      • 线索二叉树
    • 树、森林
      • 树的存储结构
      • 树、森林与二叉树的转换
      • 树、森林的遍历
    • 树与二叉树应用
      • 哈夫曼树
      • 并查集

树的基本概念

树是n个结点的有限集合,n=0时,称为空树。非空树满足:

image.png

除了根节点外,任何一个结点都有且仅有一个前驱

  • 结点的层次(深度):从上往下数
  • 结点的高度:从下往上数
  • 树的高度(深度):总共有多少层
  • 结点的度:有几个孩子(分支)
  • 树的度:各节点的度的最大值
  • 森林:m课互不相交的树的集合(m可为0,空森林)

树的性质:

  1. 结点数=总度数+1
  2. 度为m的树、m叉树的区别image.png
  3. 度为m的树第i层至多有mi-1个结点(i>=1);m叉树第i层至多有mi-1个结点(i>=1)image.png
  4. 高度为h的m叉树至多有mh-1/m-1个结点image.png
  5. 高度为h的m叉树至少有h个结点;高度为h、度为m的树至少有h+m-1个结点image.png
  6. 具有n个结点的m叉树的最小高度为向上取整 logm(n(m-1)+1)image.png

二叉树的概念

基础概念

二叉树时n个结点的有限集合(n可以为0)

由一个根节点和两个互不相交的被称为根的左子树和右子树组成,左子树和右子树又分别是一棵二叉树

  1. 每个结点至多只有两棵子树
  2. 左右子树不能颠倒(二叉树是有序树)

五种形态:

image.png

特殊二叉树:

满二叉树、完全二叉树:

image.png

二叉排序树:

image.png

平衡二叉树:

image.png

常考性质

二叉树常考性质:

  • 结点性质:n0=n2+1

    image.png

  • 第i层结点数

    image.png

  • 高度为h时最多结点数(满二叉树)

    image.png

完全二叉树常考性质:

  • 具有n个(n>0)结点的完全二叉树高度(两种推导)image.pngimage.png
  • 可以由结点数n退出度为0、1、2的结点个数n0、n1、n2image.png

总结:

image.png

存储方式

二叉树的顺序存储:

#define MaxSize 100

struct TreeNode {
    int value;//结点中的数据元素
    bool isEmpty;//判断结点是否为空
};

int main()
{
    TreeNode t[MaxSize];//定义一个长度为MaxSize的数组t,按照从上至下,从左至右的顺序依次存储二叉树中的各个结点

    for (int i = 0; i < MaxSize; i++)
    {
        t[i].isEmpty = true;//初始化时所有结点标记为空
    }
}

完全二叉树中,有着如下基本操作:

image.png

非完全二叉树使用顺序存储:

image.png

image.png

二叉树的链式存储:

//定义储存数据类型
struct ElemType {
    int value;
};

typedef struct BiTNode {
    ElemType data;//数据域
    struct BiTNode* lchild, * rchild;//左右孩子指针
} BiTNode, * BiTree;

//初始化
void InitTree(BiTree root) {
    root = (BiTree)malloc(sizeof(BiTNode));
    root->data = { 1 };
    root->lchild = NULL;
    root->rchild = NULL;
}

//插入新结点
bool InsertNode(BiTree T, ElemType val) {
    BiTNode* p = (BiTNode*)malloc(sizeof(BiTNode));
    p->data = val;
    p->lchild = NULL;
    p->rchild = NULL;
    T->lchild = p;//作为左孩子
}

n个结点的二叉链表共有n+1个空链域

image.png

二叉树遍历及线索二叉树

前中后以及层次遍历

递归法:

先序遍历

//先序遍历
void PreOder(BiTree T) {
    if (T != NULL) {
        visit(T);//访问根节点
        PreOder(T->lchild);//遍历左子树
        PreOder(T->rchild);//遍历右子树
    }
}

中序遍历

//中序遍历
void InOrder(BiTree T) {
    if (T != NULL) {
        InOrder(T->lchild);//遍历左子树
        visit(T);//访问根节点
        InOrder(T->rchild);//遍历右子树
    }
}

后序遍历

//后序遍历
void PostOder(BiTree T) {
    if (T != NULL) {
        PostOder(T->lchild);
        PostOder(T->rchild);
        visit(T);
    }
}

非递归法:

先序遍历(需要用到辅助栈)

//先序遍历
void PreOrder2(BiTree T)
{
    SqStack S;
    InitStack(S); BiTree p = T;//初始化栈S;p是遍历指针
    while (p || !IsEmpty(S)) //栈不空或p不空时循环
    {
        if (p) //一路向左
        {
            visit(p); Push(S, p);//访问当前结点,并入栈
            p = p->lchild;//左孩子不空,一直向左走
        }
        else //出栈,并转向出栈结点的右子树
        {
            Pop(S, p);//栈顶元素出栈
            p = p->rchild;//向右子树走,p赋值为当前结点的右孩子
        } //返回while循环继续进入if-else语句
    }
}

中序遍历

//中序遍历
void InOrder2(BiTree T)
{
    SqStack S;
    InitStack(S);//初始化栈
    BiTree p = T;//p为遍历指针
    while (p || !IsEmpty(S))
    {
        if (p)
        {
            Push(S, p);//当前结点入栈
            p = p->lchild;//左孩子不空,一直向左走
        }
        else //出栈,并转向出栈结点的右子树
        {
            Pop(S, p); visit(p);//栈顶元素出栈,访问出栈结点
            p = p->rchild;//向右子树走,p赋值为当前结点的右孩子
        }//返回while循环继续进入if-else语句
    }
}

层次遍历(需要用到辅助队列)

//用于层序遍历的辅助队列
typedef struct LinkNode {
    BiTNode* data;//存的是指针而非结点
    struct LinkNode* next;
} LinkNode;

typedef struct {
    LinkNode* front, * rear;//队头队尾
} LinkQueue;

void InitQueue(LinkQueue& Q) {
    Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));
    //初始化时,front 、rear 都指向头节点
    Q.front->next = NULL;
}

bool EnQueue(LinkQueue& Q, BiTNode* x) {
    //判满?链式存储一般不需要判满,除非内存不足
    LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));
    if (s == NULL)return false;
    s->data = x;
    s->next = NULL;
    Q.rear->next = s;//新节点插入到rear之后
    Q.rear = s;//修改表尾指针
    return true;
}

bool DeQueue(LinkQueue& Q, BiTNode* x) {
    if (Q.front == Q.rear)return false;//队空
    LinkNode* p = Q.front->next;//用指针p记录队头元素
    x = p->data;//用x变量返回队头元素
    Q.front->next = p->next;//修改头节点的next指针
    if (Q.rear == p)//此次是最后一个节点出队
        Q.rear = Q.front;//修改rear指针,思考一下为什么?
    free(p); //释放节点空间
    return true;
}

bool isEmpty(LinkQueue Q) {
    return Q.front == Q.rear ? true : false;
}

//层序遍历
void levelOrder(BiTree T) {
    LinkQueue Q;//辅助队列
    InitQueue(Q);//
    BiTree p;
    EnQueue(Q, T);
    while (!isEmpty(Q)) {
        DeQueue(Q, p);//队头结点出队
        visit(p);
        if (p->lchild != NULL)
            EnQueue(Q, p->lchild);
        if (p->rchild != NULL)
            EnQueue(Q, p->rchild);
    }
}

应用:求树的深度

//求树的深度
int treeDepth(BiTree T)
{
    if (T == NULL)
    {
        return 0;
    }
    else
    {
        int l = treeDepth(T->lchild);
        int r = treeDepth(T->rchild);
        //树的深度=Max(左子树深度,右子树深度)+1
        return l > r ? l + 1 : r + 1;
    }
}

由二叉树的遍历序列可以构造出二叉树

前序+中序:

image.png

后序+中序:

image.png

层序+中序:

image.png

若没有中序遍历则不能够构造出二叉树

线索二叉树

线索二叉树的存在,方便我们能够找到某个结点的前驱以及后继

线索二叉树利用叶子结点中的空链域对前驱线索以及后继线索进行存储,并且使用ltag、rtag进行标注,tag==0表示指针指向的是孩子,tag==1表示指针指向的是“线索”

新的结构体:

struct ElemType {
    int value;
};

typedef struct ThreadNode {
    ElemType data;//数据域
    struct ThreadNode* lchild, * rchild;//左右孩子指针
    int ltag, rtag;//左右线索标志
} ThreadNode, * ThreadTree;

ThreadNode* pre = NULL;//全局变量用于暂存当前访问结点的前驱

image.png

利用visit函数来进行线索化的操作:

void visit(ThreadNode* q) {
    if (q->lchild == NULL) {//左子树为空,建立前驱线索
        q->lchild = pre;
        q->ltag = 1;
    }
    if (pre != NULL && pre->rchild == NULL) {//建立前驱结点的后继线索
        pre->rchild = q;
        pre->rtag = 1;
    }
    pre = q;
}

中序线索化:

//中序遍历二叉树,一边遍历一边线索化
void InThread(ThreadTree T) {
    if (T != NULL) {
        InThread(T->lchild);
        visit(T);
        InThread(T->rchild);
    }
}

//创建中序线索化二叉树T
void CreatInThread(ThreadTree T) {
    pre = NULL;
    if (T != NULL) {//非空二叉树才能线索化
        InThread(T);//中序线索二叉树
        if (pre->rchild == NULL) {
            pre->rtag = 1;//处理遍历的最后最后一个结点
        }
    }
}

//中序线索化(王道教材版)
void InThread_CSKaoYan(ThreadTree p, ThreadTree& pre) {
    if (p != NULL) {
        InThread_CSKaoYan(p->lchild, pre);//递归,线索化左子树
        if (p->lchild == NULL) {//左子树为空,建立前驱线索
            p->lchild = pre;
            p->ltag = 1;
        }
        if (pre != NULL && pre->rchild == NULL) {
            pre->rchild == p;//建立前驱结点的后及线索
            pre->rtag = 1;
        }
        pre = p;
        InThread_CSKaoYan(p->rchild, pre);
    }
}

//中序线索化二叉树(王道教材版本)
void CreatInThread_CSKaoYan(ThreadTree T) {
    ThreadTree pre = NULL;
    if (T != NULL) {
        InThread_CSKaoYan(T, pre);
        pre->rchild = NULL;//思考:为什么处理最后一个结点时没有判断rchild 是否为NULL?
        pre->rtag = 1;//答:因为最后一个结点的右孩子必为空。
    }
}

先序线索化:

//先序线索化,一边遍历一边线索化
void PreThread(ThreadTree T) {
    if (T != NULL) {
        visit(T);
        if (0 == T->ltag) {//lchild不是前驱线索
            PreThread(T->lchild);
        }
        PreThread(T->rchild);
    }
}

//创建先序线索化二叉树T
void CreatPreThread(ThreadTree T) {
    pre == NULL;
    if (T != NULL) {
        PreThread(T);
        if (pre->rchild == NULL) {
            pre->rtag = 1;//处理遍历的最后一个结点
        }
    }
}

//先序线索化(王道教程版本)
void PreThread_CSKaoYan(ThreadTree p, ThreadTree& pre) {
    if (p != NULL) {
        if (p->lchild == NULL) {
            p->lchild = pre;
            p->ltag = 1;
        }
        if (pre != NULL && pre->rchild == NULL) {
            pre->rchild == p;//建立前驱结点的后及线索
            pre->rtag = 1;
        }
        pre = p;
        if (0 == p->ltag) {
            PreThread_CSKaoYan(p->lchild, pre);
        }
        PreThread_CSKaoYan(p->rchild, pre);
    }
}

//先序线索化二叉树(王道教材版本)
void CreatPreThread_CSKaoYan(ThreadTree T) {
    ThreadTree pre = NULL;
    if (T != NULL) {
        PreThread_CSKaoYan(T, pre);
        if (pre->rchild = NULL)//处理遍历的最后一个结点
            pre->rtag = 1;
    }
}

后序线索化:

//后序线索二叉树
void PostThread(ThreadTree T) {
    if (T != NULL) {
        PostThread(T->lchild);
        PostThread(T->rchild);
        visit(T);
    }
}

//创建后序线索二叉树T
void CreatPostThread(ThreadTree T) {
    pre == NULL;
    if (T != NULL) {
        PostThread(T);
        if (pre->rchild == NULL) {
            pre->rtag = 1;//处理遍历的最后一个结点
        }
    }
}

//后序线索化(王道教程版本)
void PostThread_CSKaoYan(ThreadTree p, ThreadTree& pre) {
    if (p != NULL) {
        PostThread_CSKaoYan(p->lchild, pre);
        PostThread_CSKaoYan(p->rchild, pre);
        if (p->lchild == NULL) {
            p->lchild = pre;
            p->ltag = 1;
        }
        if (pre != NULL && pre->rchild == NULL) {
            pre->rchild == p;//建立前驱结点的后及线索
            pre->rtag = 1;
        }
        pre = p;
    }
}
//后序线索化二叉树(王道教材版本)
void CreatPostThread_CSKaoYan(ThreadTree T) {
    ThreadTree pre = NULL;
    if (T != NULL) {
        PostThread_CSKaoYan(T, pre);
        if (pre->rchild = NULL)//处理遍历的最后一个结点
            pre->rtag = 1;
    }
}

而通过线索二叉树找到前驱后继又是另一大问题

中序线索二叉树找后继:

//中序线索二叉树找中序后继
//找到以P为根的子树中,第一个被中序遍历的结点
ThreadNode* FirstNode(ThreadNode* p) {
    //循环找到最左下结点(不一定是叶结点)
    while (0 == p->ltag) {
        p = p->lchild;
    }
    return p;
}

//在中序线索二叉树中找到结点p的后继结点
ThreadNode* NextNode(ThreadNode* p) {
    //在右子树中最左下结点
    if (0 == p->rtag)return FirstNode(p->rchild);
    else return p->rchild;
}

//对中序线索二叉树进行中序遍历(利用线索实现的非递归算法),空间复杂度为O(1);
void InOrder(ThreadNode* T) {
    for (ThreadNode* p = FirstNode(T); p != NULL; p = NextNode(p)) {
        visit(p);
    }
}

中序线索二叉树找前驱:

//中序线索二叉树找中序前驱
//找到以p为根的子树中,最后一个被中序遍历的结点
ThreadNode* LastNode(ThreadNode* p) {
    //循环找到最右下结点(不一定是叶结点)
    while (0 == p->rtag)p = p->rchild;
    return p;
}

//在中序线索二叉树中找到结点p的前驱结点
ThreadNode* PreNode(ThreadNode* p) {
    //左下子树中最右结点
    if (0 == p->ltag)return LastNode(p->lchild);
    else return p->lchild;
}

//对中序线索二叉树进行逆向中序遍历
void RevInOrder(ThreadNode* T) {
    for (ThreadNode* p = LastNode(T); p != NULL; p = PreNode(p)) {
        visit(p);
    }
}

先序以及后序找前驱后继的思路:

image.png

image.png

对于先序线索二叉树找前驱以及后序线索二叉树找后继都较为复杂,需要对不同情况进行分类讨论。

树、森林

树的存储结构

双亲表示法

//树——双亲表示法(顺序存储法)
#define MAX_TREE_SIZE 100

typedef struct {
    int data; //数据元素
    int parent;//双亲位置域
}PTNode;
typedef struct {
    PTNode nodes[MAX_TREE_SIZE];//双亲表示
    int n;//结点数
}PTree;

image.png

image.png

优点:找双亲(父节点)很方便

缺点:找孩子不方便,只能从头到尾遍历整个数组

适用于“找父亲”多“找孩子”少的应用场景,如:并查集

孩子表示法(顺序存储+链式存储结合)

//树——孩子表示法(顺序+链式存储)
struct CTNode {
    int child;//孩子节点在数组中的位置
    struct CTNode* next;//下一个孩子
};
typedef struct {
    int data; //数据元素,数据元素类型不定
    struct CTNode* firstChild;//第一个孩子
}CTBox;
typedef struct {
    CTBox nodes[MAX_TREE_SIZE];//双亲表示
    int n, r;//结点数和根的位置
}CTree;

image.png

优点:找孩子很方便

缺点:找双亲(父节点)不方便,只能遍历每个链表

适用于“找孩子”多,“找父亲”少的应用场景,如:服务流程树

孩子兄弟表示法

//树——孩子兄弟表示法(链式存储)
typedef struct CSNode {
    int data; //数据域,数据类型不定
    struct CSNode* firstChild, * nextsibiling;//第一个孩子和右兄弟指针
}CSNode, * CSTree;

与二叉树类似,采用二叉链表实现,每个结点内保存数据元素和两个指针,但两个指针的含义与二叉树结点不同。

用这种表示法存储树或森林时,从存储视角来看形态上与二叉树类似

image.png

树、森林与二叉树的转换

树转二叉树

image.png

森林转二叉树

image.png

二叉树转树

image.png

二叉树转森林

image.png

树、森林的遍历

树的先根遍历

image.png

与相应二叉树的先序序列相同

树的后根遍历

image.png

与相应二叉树的中序序列相同

层次遍历(广度优先)用队列实现

image.png

森林的先序遍历

image.png

效果等同于依次对各个树进行先根遍历,也等同于对相应二叉树先序遍历

森林中序遍历

image.png

效果等同于依次对各个树进行后根遍历,也等同于对相应二叉树中序遍历

image.png

树与二叉树应用

哈夫曼树

带权路径长度:

image.png

哈夫曼树定义:

image.png

哈夫曼树构造:

image.png

哈夫曼编码:

image.png

并查集

利用双亲表示法的存储方式,每个子集合以一棵树表示,所有表示子集合的树,构成表示全集合的森林,根节点的双亲结点为负数

image.png

初始化:

image.png

#define SIZE 10
int UFSets[SIZE];//集合元素数组

//初始化
void Initial(int S[])
{
	for (int i = 0; i < SIZE; i++)
		S[i] = -1;
}

查:

//查,找到x所属集合(返回x所属根节点)
int Find(int S[], int x)
{
	while (S[x] >= 0)
		x = S[x];
	return x;//根节点S[]小于0
}

优化查:

image.png

//查优化,压缩路径
int Find2(int S[], int x)
{
	int root = x;
	while (S[root] >= 0) root = S[root];//循环找到根
	while (x != root) //压缩路径
	{
		int t = S[x];//t指向x的父节点
		S[x] = root;//x直接挂到根节点下
		x = t;
	}
	return root;
}

并:(并之前要先找到两个元素根节点)

//并,将两个集合根节点传入,合并为一个
void Union(int S[], int Root1, int Root2)
{
	//判断为不同集合
	if (Root1 == Root2) return;
	//将根Root2连接到另一根Root1下面
	S[Root2] = Root1;
}

优化并:

image.png

//并优化,让小树合并到大树,用根节点的绝对值表示树的结点总数
void Union2(int S[], int Root1, int Root2)
{
	if (Root1 == Root2) return;
	if (S[Root2] > S[Root2]) //Root2更大,绝对值更小,结点数更小
	{
		S[Root1] += S[Root2];//累加结点总数
		S[Root2] = Root1;//小树合并到大树
	}
	else
	{
		S[Root2] += S[Root1];
		S[Root1] = Root2;
	}
}

优化前后对比:

image.png

主要参考:王道考研课程
后续会持续更新考研408部分的学习笔记,欢迎关注。
github仓库(含所有相关源码):408数据结构笔记

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

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

相关文章

Oracle体系结构

Oracle体系结构 前言 1、数据库 2、 实例 3、用户 4、表空间 5、数据文件&#xff08;dbf、ora&#xff09; 6、逻辑图 1、数据库 Oracle 数据库是数据的物理存储。这就包括&#xff08;数据文件 ORA 或者 DBF、控制文件、联机日志、参数文件&#xff09;。 其实 Oracle 数据库…

【javaEE面试题(一)用鸡和鸡蛋和房间的样例 讲给面试官听】【3.8千字解析进程和线程-配非常重要的面试题】进程和线程的区别

欢迎观看我的博客&#xff0c;如有问题交流&#xff0c;欢迎评论区留言&#xff0c;一定尽快回复&#xff01;&#xff08;大家可以去看我的专栏&#xff0c;是所有文章的目录&#xff09;   文章字体风格&#xff1a; 红色文字表示&#xff1a;重难点★✔ 蓝色文字表示&#…

Nodejs基于Windows安装教程

一、安装环境 在进行 Node.js 环境的安装之前&#xff0c;您需要先安装并配置好以下环境&#xff1a; 操作系统&#xff1a;Windows 命令行工具&#xff1a;Node.js 是通过命令行工具进行使用和管理的&#xff0c;因此您需要选择一个适合您的命令行工具。在 Windows 上&…

go-zero微服务实战——基本环境搭建

简介 项目架构来源于go-zero实战&#xff1a;让微服务Go起来。此对该项目有所删减&#xff0c;相对简单适合初学者。 省去了项目中每个服务占用独立docker的过程&#xff0c;省略了docker-compose的构建过程。每个服务是一个独立的程序不依赖与容器。 环境搭建 安装goctl …

c++ -- STL

【C/C】STL详解_cstl_沉晓的博客-CSDN博客 Learning Record have done assignment class template An excellent programmer only needs to know how to use containers to improve program encapsulation and reduce coupling, without understanding the underlying pri…

面向对象之创建对象模式和继承模式

目录 工厂函数模式 优点&#xff1a; 缺点&#xff1a; 构造函数模式 优点: 缺点: 原型对象模式 优点: 缺点: 组合模式 instanceof 继承 继承分为三类&#xff0c;分别是:原型链继承、借用构造函数继承、组合继承(原型链继承借用构造函数继承) 组合继承 从…

开发工具VSCODE的使用记录

vscode简介 Visual Studio Code&#xff08;简称“VS Code” [1] &#xff09;是Microsoft在2015年4月30日Build开发者大会上正式宣布一个运行于 Mac OS X、Windows和 Linux 之上的&#xff0c;针对于编写现代Web和云应用的跨平台源代码编辑器&#xff0c; [2] 可在桌面上运行…

ADB 命令结合 monkey 的简单使用,超详细

一&#xff1a;ADB简介 1&#xff0c;什么是adb&#xff1a; ADB 全称为 Android Debug Bridge&#xff0c;起到调试桥的作用&#xff0c;是一个客户端-服务器端程序。其中客户端是用来操作的电脑&#xff0c;服务端是 Android 设备。ADB 也是 Android SDK 中的一个工具&#…

openssl CVE-2016-2107 漏洞检测---OpenSSL Padding Oracle 攻击

openssl CVE-2016-2107 漏洞检测—OpenSSL Padding Oracle 攻击 文章目录 CVE-2016-2107.exe执行1执行2 OpenSSL Padding Oracle 攻击漏洞描述检测方法修复 CVE-2016-2107.exe 执行1 下载CVE-2016-2107.exe https://github.com/FiloSottile/CVE-2016-2107 https://github.com…

2023 7.3~7.9 周报 (论文初读)

上周回顾: (上周还没开始) 本周计划: 本周阅读论文《Deep-Learning Full-Waveform Inversion Using Seismic Migration Images》. 这篇论文是发表于2022的一篇较新的关于DL-FWI的论文, 作者在论文中提出了一些比较新颖的观点和质疑. 这篇论文主基调很符合近几年DL-FWI的味道…

对 MinIO API 进行封装并上传到第三方库 Pyzjr

目录 本文介绍 上一节补充 使用官方的游乐场进行测试和开发 熟悉MinIO的API 创建客户端 操作桶 1、检查桶是否存在&#xff0c;如果不存在就创建一个桶 2、列出所有的存储桶名 3、删除储存桶 4、用于查看存储桶的对象 操作对象 1、删除对象 2、删除zip文件 3、下…

C#基础学习_构造方法

C#基础学习_构造方法 在构造方法中添加初始化内容; 通过使用构造方法,可以简化对象初始化代码。 无参数的构造方法: public Student(){StudentID = 12345;StudentName = "djichsdi";}带参数的构造方法(构造方法同样可以重载&

Python——基础语法

输出语句 #字符串拼接 print("hello word""北岭山脚鼠鼠") #字符转义 print("He said \"Let\s go!\"") #换行 print("hello!\nHi!") #三引号 print(""""北岭山脚鼠鼠 北岭山脚鼠鼠 北岭山脚鼠鼠 北岭山…

ESP32(掌控板) 陀螺仪显示与RGB灯

ESP32&#xff08;掌控板&#xff09; 陀螺仪显示与RGB灯 本程序图形化显示陀螺仪位置&#xff08;注意要换算&#xff09;&#xff0c;根据陀螺仪位置控制RGB灯颜色并有3种颜色组合和关灯可选&#xff0c;通过触摸按键调节亮度。 图形化程序如下 Arduino代码如下 /*!* MindP…

字符集,编码方式和Java程序乱码问题

目录 1&#xff0c;字符编码 2&#xff0c;三大字符集及编码方式 2.1&#xff0c;ASCII字符集及编码方式 2.2&#xff0c;GBK字符集及编码方式 2.3&#xff0c;Unicode字符集及编码方式 3.程序乱码问题 1&#xff0c;字符编码 数字计算机中的存储器唯一可以存储的是比特&a…

绿虫生产效率提升工具怎么安装配置?

一、添加员工 打开绿虫生产效率提升工具后台&#xff0c;输入账号密码登录&#xff0c;登录成功之后&#xff0c;需要先进行员工添加&#xff0c;点击员工管理&#xff0c;导入员工信息&#xff0c;也可使用企微同步。 二、绑定员工 点击终端部署&#xff0c;复制网址或下载安…

多模态系列论文----最详细的多模态论文总结(BLIP、BEIT、CoCa等)

1 多模态概述 多模态指的是多种模态的信息数据&#xff0c;包括&#xff1a;文本、图像、视频、音频等。多模态任务是指需要同时处理两种或多种不同类型的数据的任务。近年来&#xff0c;随着深度学习技术的发展&#xff0c;多模态任务取得了显著的进步。特别是VIT&#xff08…

【WebSocket】SpringBoot整合WebSocket实现聊天室(一)

目录 一、准备 1、引入依赖 2、创建配置类 二、相关注解 一、准备 1、引入依赖 首先我们需要在项目中引入依赖&#xff0c;有两种方式。第一种我们可以在创建Spring Boot项目时搜索WebSocket然后勾选依赖 第二种是我们可以直接在项目的pom.xml文件中插入以下依赖 <dep…

基于TF-IDF+Tensorflow+PyQt+孪生神经网络的智能聊天机器人(深度学习)含全部Python工程源码及模型+训练数据集

目录 前言总体设计系统整体结构图系统流程图孪生神经网络结构图 运行环境Python 环境TensorFlow 环境 模块实现1. 数据预处理2. 创建模型并编译3. 模型训练及保存4. 模型应用 系统测试1. 训练准确率2. 测试效果3. 模型生成 工程源代码下载其它资料下载 前言 本项目利用TF-IDF&…

[VUE学习】从头搭建权限管理系统前端-初始化

1.安装Node 2.安装Vue Cli vue的一个脚手架 npm install -g vue/cli 3.vue ui搭建vue项目 cmd 运行 vue ui 然后创建新项目 选择npm 选择配置 Babel 是编译的 Router 是路由 vuex 是状态保存的 Linter/fomatter 代码检测和格式化 创建完成 这个时候 代码在我们本地…