数据结构 —— 二叉树

1.树的概念及结构

1.1树的概念

树是一种非线性的数据结构,它有着多分支,层次性的特点。

由于其形态类似于自然界中倒过来的数,所以我们将这种数据结构称为“树形结构”

注意: 树形结构中,子树之间不能有交集,否它就不是树形结构

 

1.2 树的相关概念

  • 结点的度:一个结点含有的子树的个数称为该结点的度; 如上图:A的为6
  • 叶结点或终端结点:度为0的结点称为叶结点; 如上图:BCHI...等结点为叶结点
  • 非终端结点或分支结点:度不为0的结点; 如上图:DEFG...等结点为分支结点
  • 双亲结点或父结点:若一个结点含有子结点,则这个结点称为其子结点的父结点; 如上图:AB的父结点
  • 孩子结点或子结点:一个结点含有的子树的根结点称为该结点的子结点; 如上图:BA的孩子结点
  • 兄弟结点:具有相同父结点的结点互称为兄弟结点; 如上图:BC是兄弟结点
  • 树的度:一棵树中,最大的结点的度称为树的度; 如上图:树的度为6
  • 结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推;
  • 树的高度或深度:树中结点的最大层次; 如上图:树的高度为4
  • 堂兄弟结点:双亲在同一层的结点互为堂兄弟;如上图:HI互为兄弟结点
  • 结点的祖先:从根到该结点所经分支上的所有结点;如上图:A是所有结点的祖先
  • 子孙:以某结点为根的子树中任一结点都称为该结点的子孙。如上图:所有结点都是A的子孙
  • 森林:由mm>0)棵互不相交的树的集合称为森林;

1.3树的表示 

树的表示我们使用:孩子兄弟表示法

设计一个数的节点,其中包含数据域(存储数据)、指针域(左孩子指针,右兄弟指针)

typedef int DataType;
struct Node
{struct Node* firstChild1; // 第一个孩子结点struct Node* pNextBrother; // 指向其下一个兄弟结点DataType data; // 结点中的数据域
};

这种数的设计方法,我们可以通过左孩子指针找到 A节点 的第一个孩子(B),在通过孩子的右兄弟指针把 A节点 的所有孩子都找到

1.4 树在实际中的运用

树在实际中的运用:电脑中的数目录

2.二叉树的概念及结构 

2.1二叉树的概念 

在实际运用中,二叉树要比树更加实用

二叉树其实就是特殊的一种树,它的每个节点最多有两个子节点,通常被称为左子节点和右子节点

  •  二叉树不存在度大于2的结点
  •  二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树

2.2现实中的二叉树

 2.3特殊的二叉树

 

  •  满二叉树:二叉树的每一层都是满的(特殊的完全二叉树)
  • 完全二叉树:二叉树的最后一层不一定是满的,但是它是连续的

像下面这个二叉树,最后一层并不连续,因此它并非是完全二叉树:

2.4二叉树的性质

2.5二叉树的存储结构

二叉树一般可以使用两种结构存储,一种顺序结构,一种链式结构
1. 顺序存储
顺序结构存储就是使用 数组来存储 ,一般使用数组 只适合表示完全二叉树 ,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储
二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树
2. 链式存储
二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。
通常的方法是:链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。链式结构又分为二叉链和三叉链,目前我们使用二叉链的新式学习
二叉链式实现的二叉树:

3.二叉树的顺序存储结构 

顺序存储结构只推荐完全叉树来进行存储,一般的二叉树容使用顺序结构进行存储,容易造成空间的大量浪费,现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段

堆在这篇文章中有所介绍 ———— 数据结构 - 堆

4.二叉树的链式结构的实现

在进行二叉树链式结构的实现时,我们首先回顾二叉树是:

1. 空树
2. 非空:根结点,根结点的左子树、根结点的右子树组成的

每一颗二叉树都可以看做是递归形成的因为:

每一颗二叉树都可以拆分成:根节点 左子树 右子树

它的左子树可以被拆分成 :根节点 左子树 右子树

它的右子树右也可以被拆分成 :根节点 左子树 右子树

依次类推直到变成一颗空树,不能被拆分,所以才会说二叉树可以看做是递归形成,二叉树可以被拆分成一个一个的小问题(即一个一个的子树 根节点),直到变成空树不能再被拆分,因此后序基本操作中基本都是按照递归概念实现的

4.1二叉树的前置声明

typedef int BTDataType;typedef struct BinaryTreeNode    //二叉树的单个节点
{BTDataType _data;struct BinaryTreeNode* _left;   //左孩子struct BinaryTreeNode* _right;  //右孩子
}BTNode;

4.2二叉树的遍历

4.2.1前序、中序以及后序遍历

二叉树的遍历是指按照某种规则访问树中的所有节点,并且每个节点只被访问一次。访问结点所做的操作依赖于具体的应用问题。遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。

按照规则,二叉树的遍历有:前序/中序/后序的递归结构遍历 

1. 前序遍历 (Preorder Traversal )—— 访问顺序:根节点 —>左子树 —>右子树
2. 中序遍历(Inorder Traversal)——访问顺序:左子树 —>根节点 —>右子树
3. 后序遍历(Postorder Traversal)——访问顺序:左子树 —>右子树—>根节
前序遍历递归图解

前序遍历结果: 1 2 3 4 5 6
中序遍历结果: 3 2 1 5 4 6
后序遍历结果: 3 2 5 6 4 1
前中后序遍历的方式大抵相同,这里不做过多赘述
代码实现:
// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root) {if (root == NULL)  //当访问的数为NULL树时停止访问{printf("N ");return;}printf("%d ",root->_data);//先便利根节点,整形的数据类型BinaryTreePrevOrder(root->_left);//左子树BinaryTreePrevOrder(root->_right);//右子树}
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root) {if (root == NULL){printf("N ");return;}BinaryTreeInOrder(root->_left);//左子树printf("%d ", root->_data);//根节点BinaryTreeInOrder(root->_right);//右子树
}// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root) {if (root == NULL){printf("N ");return;}BinaryTreePostOrder(root->_left);//左子树BinaryTreePostOrder(root->_right);//右子树printf("%d ", root->_data);//根节点
}

4.2.2层序遍历 

层序遍历 :除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根结点所在层数为1 ,层序遍历就是从所在二叉树的根结点出发,首先访问第一层的树根结点,然后从左到右访问第 2 层上的结点,接着是第三层的结点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。

 代码实现:

二叉树的层序遍历并不是通过递归来完成的,而是通过 —— 数据结构中的队列来实现的

遍历的原理是从根节点开始,首先访问根节点,然后将根节点的左右子节点依次入队。接下来,从队列中取出一个节点(队首节点),访问该节点,再将其未被访问的左右子节点入队。重复此过程,直到队列为空,即所有节点都被访问过。

动图理解:

// 层序遍历
void BinaryTreeLevelOrder(BTNode* root) {//创建队列Queue qu;QueueInit(&qu);QueuePush(&qu, root);//开始拖家带口,当队列为NULL时,说明已经遍历完成,循环结束while (!QueueEmpty(&qu)){//先访问队头的元素BTNode* bt = QueueFront(&qu);//获取队头元素printf("%d ", bt->_data);//将树的左右孩子都带入队列中,NULL孩子除外if (bt->_left)QueuePush(&qu, bt->_left);if (bt->_right)QueuePush(&qu, bt->_right);//队头数据处队列QueuePop(&qu);}//销毁队列QueueDestroy(&qu);}

5.二叉树总代码

队列的相关功能:

Queue.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>typedef struct BinaryTreeNode* QDataType;   //队列中的元素是树的节点
// 链式结构:表示队列 
typedef struct QListNode
{struct QListNode* _next;QDataType _data;
}QNode;// 队列的结构 
typedef struct Queue
{QNode* _front;QNode* _rear;int size;
}Queue;// 初始化队列 
void QueueInit(Queue* q);
// 队尾入队列 
void QueuePush(Queue* q, QDataType data);
// 队头出队列 
void QueuePop(Queue* q);
// 获取队列头部元素 
QDataType QueueFront(Queue* q);
// 获取队列队尾元素 
QDataType QueueBack(Queue* q);
// 获取队列中有效元素个数 
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q);
// 销毁队列 
void QueueDestroy(Queue* q);

Queue.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Queue.h"// 初始化队列 
void QueueInit(Queue* q) {assert(q);q->size = 0;q->_front = NULL;q->_rear = NULL;
}
// 队尾入队列 
void QueuePush(Queue* q, QDataType data) {assert(q);QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("QueuePush()::malloc()");return;}newnode->_data = data;newnode->_next = NULL;//队列为NULLif (q->_front == NULL){q->_front = q->_rear = newnode;}else{q->_rear->_next = newnode;q->_rear = q->_rear->_next;}q->size++;
}
// 队头出队列 
void QueuePop(Queue* q) {assert(q);assert(q->size != 0);//单个节点if (q->_front == q->_rear){free(q->_front);q->_front = q->_rear = NULL;}//多个节点else{QNode* next = q->_front->_next;free(q->_front);q->_front = next;}q->size--;
}
// 获取队列头部元素 
QDataType QueueFront(Queue* q) {assert(q);assert(q->_front);//队头不能为NULLreturn q->_front->_data;
}
// 获取队列队尾元素 
QDataType QueueBack(Queue* q) {assert(q);assert(q->_rear);//队尾不能为NULLreturn q->_rear->_data;
}
// 获取队列中有效元素个数 
int QueueSize(Queue* q) {return q->size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q) {assert(q);return q->size == 0;
}
// 销毁队列 
void QueueDestroy(Queue* q) {assert(q);QNode* cur = q->_front;while (cur){QNode* next = cur->_next;free(cur);cur = next;}q->_front = q->_rear = NULL;q->size = 0;//这个应该留给用户去释放/*free(q);q = NULL;*/
}

二叉树相关功能:

BinaryTree.h

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include"Queue.h"
typedef char BTDataType;typedef struct BinaryTreeNode
{BTDataType _data;struct BinaryTreeNode* _left;struct BinaryTreeNode* _right;
}BTNode;// 二叉树销毁
void BinaryTreeDestory(BTNode** root);// 二叉树节点个数
int BinaryTreeSize(BTNode* root);// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root);// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k);// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root);// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root);// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root);// 层序遍历
void BinaryTreeLevelOrder(BTNode* root);// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root);BTNode* CreatBinaryTree();

BinaryTree.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"BinaryTree.h"
BTNode* BuyNode(BTDataType x) {BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));if (newnode == NULL){perror("Buynode()::malloc()");return newnode;}newnode->_data = x;newnode->_left = NULL;newnode->_right = NULL;return newnode;
}// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root) {if (root == NULL)  //当访问的数为NULL树时停止访问{printf("N ");return;}printf("%d ",root->_data);//先便利根节点,整形的数据类型BinaryTreePrevOrder(root->_left);//左子树BinaryTreePrevOrder(root->_right);//右子树}
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root) {if (root == NULL){printf("N ");return;}BinaryTreeInOrder(root->_left);//左子树printf("%d ", root->_data);//根节点BinaryTreeInOrder(root->_right);//右子树
}// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root) {if (root == NULL){printf("N ");return;}BinaryTreePostOrder(root->_left);//左子树BinaryTreePostOrder(root->_right);//右子树printf("%d ", root->_data);//根节点
}//求二叉树的高度
int maxDepth(BTNode* root) {if (root == NULL)   //如果为空树则返回 0 {return 0;}int lefthigh = maxDepth(root->_left);    //记录树的左子树高度int righthigh = maxDepth(root->_right); //记录树的右子树高度//左子树高则返回左子树的高度    右子树高则返回右子树高度return lefthigh > righthigh ? lefthigh + 1 : righthigh + 1; }// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root) {if (root == NULL)  //如果为空树则返回 0 return 0;if (root->_left == NULL && root->_right == NULL)  //如果是叶子节点就返回 1 return 1;//返回左子树 与 右子树总共的叶子节点return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k) {//将找第k层问题转化成:层序遍历按照树的层次进行遍历,每次遍历一层,直到遍历到第k层或者遍历完整个树。   if (root == NULL)    //如果为空树则返回 0 return 0;if (root != NULL && k == 1) //当不为空且k为1时,到达所找层,返回1return 1;//一层一层的往下找if (root != NULL && k > 1)return BinaryTreeLevelKSize(root->_left,k - 1) + BinaryTreeLevelKSize(root->_right,k - 1);
}// 二叉树查找值为x的节点
//向这种找值的,一定要记录,把记录的递归返回
BTNode* BinaryTreeFind(BTNode* root, BTDataType x) {if (root == NULL)return NULL;if (root->_data == x)return root;BTNode* find1 = NULL;BTNode* find2 = NULL;find1 = BinaryTreeFind(root->_left, x);  //记录所找的节点if (find1)//如果左边找到了就不用去右边找了return find1;find2 = BinaryTreeFind(root->_right, x);return find2;
}// 二叉树销毁
void BinaryTreeDestory(BTNode** root) {if (*root == NULL)return;BinaryTreeDestory(&((*root)->_left));//先销毁左子树BinaryTreeDestory(&((*root)->_right));//在销毁右子树free(*root);*root = NULL;
}// 二叉树节点个数
int BinaryTreeSize(BTNode* root) {if (root == NULL)return 0;return BinaryTreeSize(root->_left)+ BinaryTreeSize(root->_right) + 1;
}// 层序遍历
void BinaryTreeLevelOrder(BTNode* root) {//创建队列Queue qu;QueueInit(&qu);QueuePush(&qu, root);//开始拖家带口,当队列为NULL时,说明已经遍历完成,循环结束while (!QueueEmpty(&qu)){//先访问队头的元素BTNode* bt = QueueFront(&qu);//获取队头元素printf("%d ", bt->_data);//将树的左右孩子都带入队列中if (bt->_left)QueuePush(&qu, bt->_left);if (bt->_right)QueuePush(&qu, bt->_right);QueuePop(&qu);}QueueDestroy(&qu);}// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root) {//创建队列Queue qu;QueueInit(&qu);QueuePush(&qu, root);//开始拖家带口,当队列为NULL时,说明已经遍历完成,循环结束while (!QueueEmpty(&qu)){//队列中存的数据是,树节点的指针,我们先访问队头的元素BTNode* bt = QueueFront(&qu);//获取队头元素if (bt == NULL){break;}//将树的左右孩子都带入队列中,NULL也不例外QueuePush(&qu, bt->_left);QueuePush(&qu, bt->_right);QueuePop(&qu);}while (!QueueEmpty(&qu)){BTNode* bt = QueueFront(&qu);//获取队头元素//如果在遇到非空的节点,说明它不是一个完全二叉树返回falseif (bt){return false;}QueuePop(&qu);}QueueDestroy(&qu);return true;
}

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

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

相关文章

降重工具大揭秘:AI如何帮你轻松搞定论文重写?

已经天临五年了&#xff0c;大学生们还在为论文降重烦恼……手动降重确实是个难题&#xff0c;必须要先付点小经费去靠谱的网站查重&#xff0c;再对着红字标注去改&#xff0c;后面每一次的论文呢查重结果都像赌//博&#xff0c;谁也不知道明明是同一篇文章&#xff0c;第二次…

2024鲲鹏昇腾创新大赛集训营Ascend C算子学习笔记

异构计算架构&#xff08;CANN&#xff09; 对标英伟达的CUDA CuDNN的核心软件层&#xff0c;向上支持多种AI框架&#xff0c;向下服务AI处理器&#xff0c;发挥承上启下的关键作用&#xff0c;是提升昇腾AI处理器计算效率的关键平台。主要包括有各种引擎、编译器、执行器、算…

(番外篇)指针的一些相关习题讲解(速进,干货满满)(2)

前言&#xff1a; 小编感觉最近有点太堕落&#xff0c;于是我开始从事这篇文章的撰写&#xff0c;现在也是进入七月份了&#xff0c;我现在文章开头定一个小目标&#xff0c;我决定在七月份发布至少十篇文章&#xff0c;希望我可以说到做到&#xff08;我前面就口头欠了不少文章…

OpenSSL的一些使用案例

目录 一、介绍 二、基本使用 1、Shell &#xff08;1&#xff09;文件加解密 &#xff08;2&#xff09;生成密钥文件 2、API &#xff08;1&#xff09;md5sum &#xff08;2&#xff09;AES256加解密 一、介绍 本篇博客重点不是详细描述 OpenSSL 的用法&#xff0c;只…

什么是校园气象站

在科技日新月异的今天&#xff0c;气象观测不仅局限于专业的气象机构&#xff0c;它已经走进了我们的校园&#xff0c;成为了学生们探索自然、学习科学知识的重要平台。 校园气象站是设置在学校内部&#xff0c;用于进行气象观测、数据记录和科学实验的设施。它通常由气象传感器…

常见锁策略之可重入锁VS不可重入锁

可重入锁VS不可重入锁 有一个线程,针对同一把锁,连续加锁两次,如果产生了死锁,那就是不可重入锁,如果没有产生死锁,那就是可重入锁. 死锁 我们之前引入多线程的时候不是讲了一个加数字的案例么,我们今天以它来举例 当我们这样写的时候会出现什么问题? 分析:第一个synchron…

前端基础--Vue3

Vue3基础 VUE3和VUE2的区别 2020年9月18日&#xff0c;Vue.js发布版3.0版本&#xff0c;代号&#xff1a;One Piece 于 2022 年 2 月 7 日星期一成为新的默认版本! Vue3性能更高,初次渲染快55%, 更新渲染快133% 。体积更小 Vue3.0 打包大小减少41%。 同时Vue3可以更好的支持T…

基于微服务智能推荐健康生活交流平台的设计与实现(SpringCloud SpringBoot)+文档

&#x1f497;博主介绍&#x1f497;&#xff1a;✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示&#xff1a;文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…

解决使用monaco-editor编译器,编译器展示内容没有超过编译器高度,但是出现滚动条问题

前言&#xff1a; 最近在完成项目时&#xff0c;有使用编译器进行在线编辑的功能&#xff0c;就选用了monaco-editor编译器&#xff0c;但是实现功能之后&#xff0c;发现即使在编译器展示的内容没有超过编译器高度的情况下&#xff0c;编译器依旧存在滚动条&#xff0c;会展示…

计算机网络--网络层

一、网络层的服务和功能 网络层主要为应用层提供端对端的数据传输服务 网络层接受运输层的报文段&#xff0c;添加自己的首部&#xff0c;形成网络层分组。分组是网络层的传输单元。网络层分组在各个站点的网络层之间传输&#xff0c;最终到达接收方的网络层。接收方网络层将运…

如何在 Java 应用中使用 Jedis 客户端库来实现 Redis 缓存的基本操作

本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯 山峯 转载说明:务必注明来源(注明:作者:王文峰…

堆与栈的概念(RTOS)

目录 #堆在RTOS的概念 #相关代码表示 #堆相关特点 #栈在RTOS中的概念 #栈的代码表示 #栈的相关特点 #为什么每个RTOS任务都要有自己的栈 前言&#xff1a;本篇参考韦东山老师的RTOS&#xff0c;连接放在最后 #堆在RTOS的概念 本文所指的堆与栈并不是数据结构中&#xff…

【unity实战】在Unity中使用有限状态机制作一个敌人AI

最终效果 文章目录 最终效果前言有限状态机的主要作用和意义素材下载逻辑图敌人动画配置优雅的代码文件目录状态机代码定义敌人不同状态切换创建敌人效果更多的敌人参考源码完结 前言 有限状态机以前的我嗤之以鼻&#xff0c;现在的我逐帧分析。其实之前我就了解过有限状态机&…

2.(vue3.x+vite)调用iframe的方法(vue编码)

1、效果预览 2.编写代码 (1)主页面 <template><div><button @click="sendMessage">调用iframe,并发送信息

【udp报文】udp报文未自动分片,报文过长被拦截问题定位

问题现象 某局点出现一个奇怪的现象&#xff0c;客户端给服务端发送消息&#xff0c;服务端仅能收到小部分消息&#xff0c;大部分消息从客户端发出后&#xff0c;服务端都未收到。 问题定位 初步分析 根据现象初步分析&#xff0c;有可能是网络原因导致消息到服务端不可达&a…

【C语言】文件的顺序读写

©作者:末央&#xff06; ©系列:C语言初阶(适合小白入门) ©说明:以凡人之笔墨&#xff0c;书写未来之大梦 目录 前言字符输入输出函数 - fgetc和fputc文本行输入输出函数 - fgets和fputs格式化输入输出函数 - fscanf和fprintf 前言 对文件数据的读写可以分为顺序…

Seal^_^【送书活动第8期】——《ChatGLM3大模型本地化部署、应用开发与微调》

Seal^_^【送书活动第8期】——《ChatGLM3大模型本地化部署、应用开发与微调》 一、参与方式二、本期推荐图书2.1 作者建语2.2 编辑推建2.3 图书简介2.4 前 言2.5 目 录 三、正版购买 大模型领域 既是繁星点点的未知宇宙&#xff0c;也是蕴含无数可能的广阔天地&#xff0c; 正…

idea创建自定义的maven spark scala archetype脚手架

一&#xff1a;先创建一个Maven项目net.alchim31.maven&#xff08;选该模板&#xff0c;得要等一会儿才能加载出来&#xff09; 之后将自己的目录结构建立好&#xff0c;最好不要有空目录&#xff0c;可能会因为没有文件在install的时候编译不进去 pom中内容也按照自己的需要改…

Stable Diffusion web UI 插件

2024.7.3更新&#xff0c;持续更新中 如果需要在linux上自己安装sd&#xff0c;参考&#xff1a;stable diffusion linux安装 插件复制到 /stable-diffusion-webui/extensions 目录下&#xff0c;然后重新启动sd即可 一、插件安装方法 每种插件的安装方法可能略有不同&#xf…

苹果p12证书最简单最新申请流程

使用uniapp打包&#xff0c;在ios上打正式包需要苹果的p12证书和证书profile文件&#xff0c;点进去uniapp的ios证书申请教程&#xff0c;通篇就是使用mac电脑申请的教程&#xff0c;假如没有mac电脑就无法继续了。 因此&#xff0c;假如没有mac电脑的同志们&#xff0c;可以参…