二叉树的实现(初阶数据结构)

1.二叉树的概念及结构

1.1 概念

一棵二叉树是结点的一个有限集合,该集合:

    1.或者为空

    2.由一个根结点加上两棵别称为左子树和右子树的二叉树组成

 从上图可以看出:

    1.二叉树不存在度大于2的结点

    2.二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树

1.2 特殊二叉树

    1.满二叉树:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树,也就是说没如果一个二叉树的层数为K,且结点总数是2^k-1,则它就是满二叉树。

    2.完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当每一个结点都与深度为K的满二叉树中编号从1至n的结点——对应时称之为完全二叉树,要注意的是满二叉树是一中特殊的完全二叉树。

 

1.3二叉树的性质

    1.若规定根结点的层数为1,则一棵非空二叉树的第i层上最多有2^(i-1)个结点。

    2.若规定根结点的层数为1,则深度为h的二叉树的最大结点数是2^h-1。

    3.对任何一棵二叉树,如果度为0其叶子结点个数为a,度为2的分支个数为b,则有a=b+1。

    4.若规定根结点的层数为1,具有n个结点的满二叉树的深度,h=log2(n+1).(ps:以2为底,n+1为对数)

    5.对于具有n个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有结点从0开始编号,则对于序号为i的结点有:

    1.若i>0,i的位置结点的双亲序号:(i-1)/2;i=0,i为根结点编号,无双亲结点

    2.2i+1<n,左孩子序号:2i+1,2i+1>=n否则无左孩子

    3.2i+2<n,右孩子序号:2i+2,2i+2>=n否则无右孩子

1.4二叉树的存储结构

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

1.顺序存储

顺序结构村塾就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费,而现实中使用只有堆才会使用数组来存储,二叉树顺序存储在物理上是一个数组,在逻辑上是一棵二叉树。

2.链式存储

二叉树的链式存储结构是指用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址。链式结构又分为二叉链和三叉链。

2.二叉树的实现

#pragma once#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>
typedef char BTDataType;typedef struct BinaryTreeNode
{BTDataType _data;struct BinaryTreeNode* _left;struct BinaryTreeNode* _right;
}BTNode;// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi);
// 二叉树销毁
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);
//二叉树的高度
int TreeHigh(BTNode* root);

2.1创建新的结点

调用函数BuyNode来创建新的结点

BTNode* BuyNode(BTDataType x)
{BTNode* node = (BTNode*)malloc(sizeof(BTNode));if (node == NULL){perror("malloc fail");return NULL;}node->_data = x;node->_left = NULL;node->_right = NULL;return node;
}

2.2通过前序遍历数组来构建二叉树

// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
//a为我们所要遍历的数组
//n是最大数组的长度
//pi是我们用来遍历数组的指针
//当遍历是遇到‘#’或者指针超出了数组的范围就返回NULL
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi)
{if (a[*pi] == '#' || *pi >= n){printf("NULL ");(*pi)++;return NULL;}//创建一个新的二叉树的节点BTNode* dst = BuyNode(a[*pi]); printf("%c ", dst->_data);(*pi)++;dst->_left = BinaryTreeCreate(a, n, pi);dst->_right = BinaryTreeCreate(a, n, pi);return dst;
}

构建出来的二叉树如下:

 2.3二叉树的销毁

实现二叉树的销毁时,我们要正确选择以哪种遍历的方式,这里使用后序遍历,从底层叶子层开始,先释放左子树和右子树的空间,再释放根结点的空间,如果先对根结点释放,就找不到它所对应的左子树和右子树了。

//二叉树的销毁
void BinaryTreeDestory(BTNode** root)
{if (*root == NULL){return;}BinaryTreeDestory(&((*root)->_left));BinaryTreeDestory(&((*root)->_right));free(*root);*root = NULL;return;}

2.4计算二叉树的结点个数

这里我罗列了两种方法:

一种是用一个静态变量通过size++的形式来计算结点的个数(局部的静态变量只能初始化一次)

另一种是递归遍历二叉树通过放回:  左子树+右子树+1

int BinaryTreeSize(BTNode* root)
{//方法一://用静态变量(在堆上,不在栈上)改变局部变量 -> 使得递归的size可以累加起来,但是局部的静态只能初始化一次/*static int size = 0;if (root == NULL){return 0;}else++size;BinaryTreeSize(root->_left);BinaryTreeSize(root->_right);*///方法二://如果我们当前的节点为空,也就是说我们已经到了叶子节点的左右节点,也就是没有节点//所以我们需要返回0if (root == NULL){return 0;}//如果我们当前的节点的左指针和右指针都是空的话,也就是说这是我们的叶子节点//就返回1,也就是只有一个节点if (root->_left == NULL && root->_right == NULL){return 1;}//使用递归遍历我们的二叉树,即分别统计我们左子树的节点个数再加上右子树中的节点个数再加上1//因为我们需要将我们当前所指的节点算上return BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right) + 1;}

2.5计算二叉树叶子结点的个数

int BinaryTreeLeafSize(BTNode* root)
{if (root == NULL){return 0;}//如果我们的节点的左右指针全部都为空,那就是我们的叶子节点if (root->_left == NULL && root->_right == NULL){return 1;}//返回我们左子树中的叶子节点和右子树中的叶子节点之和return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}

2.6二叉树第k层的结点个数

二叉树第一层结点个数为1,第k层结点是第一层结点往下找k-1层,第二层的结点往下找k-2层,当k为1的时候返回的结果就是找的k层的结点的个数的总和。

int BinaryTreeLevelKSize(BTNode* root, int k)
{if (root == NULL){return 0;}if (k == 1){return 1;}//分别遍历我们的左右子树,并且将我们的k的参数--,当我们的k为1时,就到达了我们所想要查找对应的层return BinaryTreeLevelKSize(root->_left, k - 1) + BinaryTreeLevelKSize(root->_right, k - 1);
}

2.7查找值为x的结点

查找第一个指定值为x的结点,同过前序遍历的方法来寻找第一个值为x的结点

BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL){return NULL;}if (root->_data == x){return root;}BTNode* ret1 = BinaryTreeFind(root->_left, x);if (ret1){return ret1;}/*BTNode* ret2 = BinaryTreeFind(root->_right, x);if (ret2){return ret2;}return NULL;*/return BinaryTreeFind(root->_right, x);
}

 2.8二叉树前序遍历

前序遍历的顺序是根 - 左子树 - 右子树

void BinaryTreePrevOrder(BTNode* root)
{if (root == NULL){return;}printf("%c ", root->_data);BinaryTreePrevOrder(root->_left);BinaryTreePrevOrder(root->_right);}

2.9二叉树中序遍历

中序遍历的顺序是左子树 - 根 - 右子树

void BinaryTreeInOrder(BTNode* root)
{if (root == NULL){return;}BinaryTreeInOrder(root->_left);printf("%c ", root->_data);BinaryTreeInOrder(root->_right);}

2.10二叉树后序遍历

后序遍历的顺序是左子树 - 右子树 - 根

void BinaryTreePostOrder(BTNode* root)
{if (root == NULL){return;}BinaryTreePostOrder(root->_left);BinaryTreePostOrder(root->_right);printf("%c ", root->_data);}

2.11二叉树层序遍历

需要使用一个队列实现层序遍历,先将指向根结点的指针入队,当根结点出队列的时候,将它的左右子树的结点的指针入队,就达到了层层遍历的效果

void BinaryTreeLevelOrder(BTNode* root)
{Queue q;QueueInit(&q);if (root){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);
}

2.12判断二叉树是否为完全二叉树

思路是通过层序遍历的方法,二叉树的叶子结点的下一层节点全部都是NULL,那么在根出队列,左右子树进队列的情况下:

当出队列出到空的时候,判断队列里面的结点是否有非空结点,如果有则证明不是完全二叉树,

反之队列里面都是空结点,则是完全二叉树。

// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root)
{Queue q;QueueInit(&q);if (root){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);QueuePop(&q);//如果有非空,就不是完全二叉树if (front){QueueDestroy(&q);printf("不是完全二叉树\n");return 0;}}QueueDestroy(&q);printf("是完全二叉树\n");return 1;
}

2.13求二叉树的高度

int TreeHigh(BTNode* root)
{if (root == NULL){return 0;}int lefthigh = TreeHigh(root->_left);int righthigh = TreeHigh(root->_right);return lefthigh > righthigh ? lefthigh + 1 : righthigh + 1;//return TreeHigh(root->_left) > TreeHigh(root->_right) ? TreeHigh(root->_left) + 1 : TreeHigh(root->_right) + 1;
}

3.二叉树总代码

3.1 Tree.h

#pragma once#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>
typedef char BTDataType;typedef struct BinaryTreeNode
{BTDataType _data;struct BinaryTreeNode* _left;struct BinaryTreeNode* _right;
}BTNode;// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi);
// 二叉树销毁
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);
//二叉树的高度
int TreeHigh(BTNode* root);

3.2 Tree.c

#define _CRT_SECURE_NO_WARNINGS 1#include"Tree.h"
#include"Queue.h"BTNode* BuyNode(BTDataType x)
{BTNode* node = (BTNode*)malloc(sizeof(BTNode));if (node == NULL){perror("malloc fail");return NULL;}node->_data = x;node->_left = NULL;node->_right = NULL;return node;
}// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi)
{//这里我们的a为我们的数组//n为我们数组的最大长度//pi为我们遍历数组的指针//这里我们使用'#'来表示NULL//当我们所指向的位置的元素为#或者我们的指针已经超过了数组的范围的时候,我们就需要返回NULL//并且将我们的指针后移if (a[*pi] == '#' || *pi >= n){printf("NULL ");(*pi)++;return NULL;}//创建一个新的二叉树的节点BTNode* dst = BuyNode(a[*pi]); printf("%c ", dst->_data);(*pi)++;//将我们之前开创的节点的左右指针指向数组中所对应的节点//如果我们的对应数组中的数据不为空的话,我们的左右指针都会指向新的对应的节点//如果我们的节点为空的话,我们会得到的返回值为NULLdst->_left = BinaryTreeCreate(a, n, pi);dst->_right = BinaryTreeCreate(a, n, pi);return dst;
}//二叉树的销毁
void BinaryTreeDestory(BTNode** root)
{if (*root == NULL){return;}BinaryTreeDestory(&((*root)->_left));BinaryTreeDestory(&((*root)->_right));free(*root);*root = NULL;return;}//计算二叉树的节点个数int BinaryTreeSize(BTNode* root)
{//用静态变量(在堆上,不在栈上)改变局部变量 -> 使得递归的size可以累加起来,但是局部的静态只能初始化一次/*static int size = 0;if (root == NULL){return 0;}else++size;BinaryTreeSize(root->_left);BinaryTreeSize(root->_right);*///如果我们当前的节点为空,也就是说我们已经到了叶子节点的左右节点,也就是没有节点//所以我们需要返回0if (root == NULL){return 0;}//如果我们当前的节点的左指针和右指针都是空的话,也就是说这是我们的叶子节点//就返回1,也就是只有一个节点if (root->_left == NULL && root->_right == NULL){return 1;}//使用递归遍历我们的二叉树,即分别统计我们左子树的节点个数再加上右子树中的节点个数再加上1//因为我们需要将我们当前所指的节点算上return BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right) + 1;}//统计二叉树叶子节点的个数
int BinaryTreeLeafSize(BTNode* root)
{if (root == NULL){return 0;}//如果我们的节点的左右指针全部都为空,那就是我们的叶子节点if (root->_left == NULL && root->_right == NULL){return 1;}//返回我们左子树中的叶子节点和右子树中的叶子节点之和return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}// 二叉树第k层节点个数int BinaryTreeLevelKSize(BTNode* root, int k)
{if (root == NULL){return 0;}if (k == 1){return 1;}//分别遍历我们的左右子树,并且将我们的k的参数--,当我们的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* ret1 = BinaryTreeFind(root->_left, x);if (ret1){return ret1;}/*BTNode* ret2 = BinaryTreeFind(root->_right, x);if (ret2){return ret2;}return NULL;*/return BinaryTreeFind(root->_right, x);
}// 二叉树前序遍历 
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;}BinaryTreeInOrder(root->_left);printf("%c ", root->_data);BinaryTreeInOrder(root->_right);}// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{if (root == NULL){return;}BinaryTreePostOrder(root->_left);BinaryTreePostOrder(root->_right);printf("%c ", root->_data);}// 层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{Queue q;QueueInit(&q);if (root){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);
}// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root)
{Queue q;QueueInit(&q);if (root){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);QueuePop(&q);//如果有非空,就不是完全二叉树if (front){QueueDestroy(&q);printf("不是完全二叉树\n");return 0;}}QueueDestroy(&q);printf("是完全二叉树\n");return 1;
}int TreeHigh(BTNode* root)
{if (root == NULL){return 0;}int lefthigh = TreeHigh(root->_left);int righthigh = TreeHigh(root->_right);return lefthigh > righthigh ? lefthigh + 1 : righthigh + 1;//return TreeHigh(root->_left) > TreeHigh(root->_right) ? TreeHigh(root->_left) + 1 : TreeHigh(root->_right) + 1;
}

3.3 Queue.h

#pragma once#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>typedef struct BinaryTreeNode* QDataType;typedef struct QueueNode
{struct QueueNode* next;QDataType val;
}QNode;typedef struct Queue
{QNode* phead;QNode* ptail;int size;
}Queue;void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);
//队尾插入
void QueuePush(Queue* pq, QDataType x);//队头删除
void QueuePop(Queue* pq);//队头和队尾的数据
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);bool QueueEmpty(Queue* pq);
int QueueSize(Queue* pq);

3.4 Queue.c

#define _CRT_SECURE_NO_WARNINGS 1#include"Queue.h"void QueueInit(Queue* pq)
{assert(pq);pq->phead = NULL;pq->ptail = NULL;pq->size = 0;
}
void QueueDestroy(Queue* pq)
{assert(pq);QNode* cur = pq->phead;while (cur){QNode* next = cur->next;free(cur);cur = next;}pq->phead = pq->ptail = NULL;pq->size = 0;
}//队尾插入
void QueuePush(Queue* pq, QDataType x)
{assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc fail");return;}newnode->next = NULL;newnode->val = x;if (pq->ptail == NULL){pq->phead = pq->ptail = newnode;}else{pq->ptail->next = newnode;pq->ptail = newnode;}pq->size++;
}int QueueSize(Queue* pq)
{assert(pq);return pq->size;
}//队头删除
void QueuePop(Queue* pq)
{assert(pq);assert(QueueSize(pq) != 0);//一个节点if (pq->phead == pq->ptail){free(pq->phead);pq->phead = pq->ptail = NULL;}//多个节点else{QNode* next = pq->phead->next;free(pq->phead);pq->phead = next;}pq->size--;
}QDataType QueueFront(Queue* pq)
{assert(pq);assert(pq->phead);return pq->phead->val;
}QDataType QueueBack(Queue* pq)
{assert(pq);assert(pq->ptail);return pq->ptail->val;
}bool QueueEmpty(Queue* pq)
{assert(pq);return pq->size == 0;
}

3.5 Test.c

#define _CRT_SECURE_NO_WARNINGS 1#include "Tree.h"int main()
{char a[] = { 'A','B','D','#','#','E','#','H','#','#','C','F','#','#','G','#','#' };int b = 0;int* pi = &b;BTNode* Btree = BinaryTreeCreate(a, 16, pi);printf("\n");//前序遍历BinaryTreePrevOrder(Btree);printf("\n");//中序遍历BinaryTreeInOrder(Btree);printf("\n");//后序遍历BinaryTreePostOrder(Btree);printf("\n");//层次遍历BinaryTreeLevelOrder(Btree);printf("\n");int number = BinaryTreeSize(Btree);printf("%d", number);printf("\n");//查找为x的节点BTNode* find = BinaryTreeFind(Btree, 'A');printf("%c", find->_data);printf("\n");//查询第K层的节点个数int W = BinaryTreeLevelKSize(Btree, 3);printf("%d\n", W);//查询叶子节点的个数int count = BinaryTreeLeafSize(Btree);printf("%d\n", count);//判断当前是否为一颗完全二叉树int ret = BinaryTreeComplete(Btree);int x = TreeHigh(Btree);printf("%d\n", x);BinaryTreeDestory(&Btree);return 0;
}

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

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

相关文章

DevOps入门

DevOps: 让技术团队、运维、测试等团队实现一体式流程自动化 CICD: CI:持续集成 CD:持续交付持续集成:从编码、编译、测试、发布项目到仓库的自动化流程持续交付:包含持续集成&#xff0c;并且增加将项目部署到对应的环境的自动化流程 传统项目闭环流程: DevOps闭环流程…

软考架构-计算机网络考点

会超纲&#xff0c;3-5分 网络分类 按分布范围划分 局域网 LAN 10m-1000m左右 房间、楼宇、校园 传输速率高 城域网 MAN 10km 城市 广域网 WAN 100km以上 国家或全球&#xff08;英特网&#xff09; 按拓扑结构划分 总线型&#xff1a;利用率低、干…

问题:设备管理指标为完好率不低于( ),待修率不高于5%,事故率不高于1%。 #知识分享#经验分享#经验分享

问题&#xff1a;设备管理指标为完好率不低于( )&#xff0c;待修率不高于5%&#xff0c;事故率不高于1%。 A、100% B、95% C、90% D、80% 参考答案如图所示

思维,CF1575K - Knitting Batik

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 1575K - Knitting Batik 二、解题报告 1、思路分析 诈骗题&#xff0c;上面…

Android开机动画关闭流程

一步一图项目上要加一个开机动画结束的回调&#xff0c;我这边看下如何加 好&#xff0c;老规矩&#xff0c;如何启动动画&#xff1f;动画是谁启动的&#xff1f;怎么关闭的&#xff1f;谁通知关闭的 带着问题看源码 动画的启动流程 开机动画的主入口在哪&#xff1f; 这个…

数据结构--线性表和串

个人介绍 hello hello~ &#xff0c;这里是 code袁~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的…

2024-06-08 Unity 编辑器开发之编辑器拓展9 —— EditorUtility

文章目录 1 准备工作2 提示窗口2.1 双键窗口2.2 三键窗口2.3 进度条窗口 3 文件面板3.1 存储文件3.2 选择文件夹3.3 打开文件3.4 打开文件夹 4 其他内容4.1 压缩纹理4.2 查找对象依赖项 1 准备工作 ​ 创建脚本 “Lesson38Window.cs” 脚本&#xff0c;并将其放在 Editor 文件…

Vue3【十二】09Computed计算属性

Vue3【十二】09Computed计算属性 计算属性 获取全名 这种方式是只读的不能修改 这样定义fullName是一个计算属性&#xff0c;可读可写 案例截图 目录结构 代码 Person.vue <template><div class"person"><h1>我是 Person 组件</h1>姓&…

基于OpenVINO实现无监督异常检测

异常检测(AD) 在欺诈检测、网络安全和医疗诊断等关键任务应用中至关重要。由于数据的高维性和底层模式的复杂性&#xff0c;图像、视频和卫星图像等视觉数据中的异常检测尤其具有挑战性。然而&#xff0c;视觉异常检测对于检测制造中的缺陷、识别监控录像中的可疑活动以及检测医…

三维重建 虚拟内窥镜(VE)是什么?怎么实现 使用场景

1.虚拟内窥镜&#xff1a; 就是利用计算机图形学、虚拟现实、图像处理和科学可视化等信息处理技术仿真光学内窥镜对病人进行诊断的一种技术。 VE(Virtual Endoscopy)&#xff0c;虚拟内镜技术。这种CT重建图像可以模拟各种内镜检查的效果&#xff0c;它是假设视线位于所要观察…

高能来袭|联想拯救者携手《黑神话:悟空》玩转东方神话世界

从2020年首次发布实机演示视频以来&#xff0c;《黑神话&#xff1a;悟空》便在全球范围内获得了广泛关注&#xff0c;成为国产3A游戏的现象级爆款。6月&#xff0c;联想拯救者正式宣布成为《黑神话&#xff1a;悟空》全球官方合作伙伴&#xff0c;致力于共同革新国产游戏体验&…

第十二届蓝桥杯C++青少年组中/高级组选拔赛2020年11月22日真题解析

一、编程题 第1题&#xff1a;求和 【题目描述】 输入一个正整数 N(N < 100)&#xff0c;输出 1 到 N(包含 1 和 N)之间所有奇数的和。 【输入描述】 输入一个正整数 N(N < 100) 【输出描述】 输出 1 到 N 之间的所有奇数的和 【输入样例】 3【输出样例】 4答案&…

LIP模型动力学方程例子

线性倒立摆(Linear Inverted Pendulum, LIP)模型是用于描述和控制人形机器人步态的重要工具。LIP模型假设质心沿着一条固定的直线运动,并且所有质量集中在质心上。这简化了计算,使得模型更容易用于控制和稳定分析。 LIP模型动力学方程 LIP模型的基本假设是: 机器人的质心…

【病理数据】svs格式数据解读

Openslide 病理图像通常以.svs格式存储在数据库中。要想使用python处理svs格式的图像&#xff0c;我们通常使用Openslide模块。 关于Openslide模块的安装详见这个博客&#xff1a; 【解决Error】ModuleNotFoundError: No module named ‘openslide‘ 病理图像数据结构 病理图…

Latex中表格(3)

Latex中的表格 一、多行或多列单元格 这篇主要说Latex中表格出现多行或者多列单元格的形式. 一、多行或多列单元格 可能用到的宏包 \usepackage{booktabs}\usepackage{multirow} 代码&#xff1a; \begin{table}[h!] \centering \caption{Your caption here} \begin{tabul…

【iOS】UI——关于UIAlertController类(警告对话框)

目录 前言关于UIAlertController具体操作及代码实现总结 前言 在UI的警告对话框的学习中&#xff0c;我们发现UIAlertView在iOS 9中已经被废弃&#xff0c;我们找到UIAlertController来代替UIAlertView实现弹出框的功能&#xff0c;从而有了这篇关于UIAlertController的学习笔记…

Nextjs学习教程

一.手动创建项目 建议看这个中文网站文档,这个里面的案例配置都是手动的,也可以往下看我这个博客一步步操作 1.在目录下执行下面命令,初始化package.json文件 npm init -y2.安装react相关包以及next包 yarn add next react react-dom // 或者 npm install --save next react…

k8s常见故障--yaml文件检查没有问题 pod起不来(一直处于创建中)

故障信息 pod一直处于创建中 查看pod详细信息显示 kubectl describe pod 容器id文字 Events: Type Reason Age From Message Normal Scheduled 5m30s default-scheduler Successfully assigned default/nginx-server2-f97c6b9d5-d6dsp to worker02 Warning FailedCreatePod…

C语言之字符函数总结(全部!),一篇记住所有的字符函数

前言 还在担心关于字符的库函数记不住吗&#xff1f;不用担心&#xff0c;这篇文章将为你全面整理所有的字符函数的用法。不用记忆&#xff0c;一次看完&#xff0c;随查随用。用多了自然就记住了 字符分类函数和字符转换函数 C语言中有一系列的函数是专门做字符分类和字符转换…

XML解析库tinyxml2库使用详解

XML语法规则介绍及总结-CSDN博客 TinyXML-2 是一个简单轻量级的 C XML 解析库,它提供了一种快速、高效地解析 XML 文档的方式。 1. 下载地址 Gitee 极速下载/tinyxml2 2. 基本用法 下面将详细介绍 TinyXML-2 的主要使用方法: 2.1. 引入头文件和命名空间 #i…