数据结构-二叉树-更新完整版

2023-11-13

目录

二叉树初识

实现二叉树的功能

功能前操作

遍历功能

操作、计算、查询功能

源码


因为上次二叉树的文章的功能不全,所以这次更新一个完整版的二叉树文章

这篇文章有些功能是需要用到队列知识的,所以对队列不了解的可以先去看看这篇队列--详解

因为这次需要调用到栈的代码 所以本篇代码会较多 但我会在每个源码标上各个所属文件名称。


二叉树初识

我们先认识下二叉树

二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个节点最多只能有两棵子树,且有左右之分

树相关词汇与解释

节点的度:一个节点有多少个孩子,就叫节点的度

叶子节点:节点度为0的节点,就叫叶子节点(相当于该节点没有左、右孩子节点)

分支节点:节点度不为0的节点,叫分支节点

父节点:节点的父亲

子节点:节点的孩子

兄弟节点:具有相同父亲节点的叫兄弟节点

树的度:最大节点的度

节点层次:从根开始定义根为第一层,根的节点为第二层

堂兄弟节点:双亲在同一层

节点的祖先:根节点是所有节点的祖先

满足二叉树的条件:

  1. 本身是有序树
  2. 树中包含的各个节点的度不能超过 2,即只能是 0、1 或者 2

 


实现二叉树的功能


功能前操作

需要用到的头文件

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

二叉树的节点为左、右节点,那么就创建两个指针,分别指向左、右节点,最后再添加一个存储该节点的数据的变量。再对类型名重命名,以方便以后更该类型

typedef char STDataType;

typedef struct Linode
{
	struct Linode* left;
	struct Linode* right;
	STDataType data;
}TR;

1.1创建节点功能

先申请一个内存空间(即申请一个结点),并且对此空间进行检查

让此结点存放数据 并且先让它的left,right指针指向空

最后再返回该结点

TR* BuyTree(STDataType x)
{
	TR* newnode = (TR*)malloc(sizeof(TR));
	assert(newnode);
	newnode->data = x;
	newnode->left = NULL;
	newnode->right = NULL;

	return newnode;
}

1.2节点连接功能

创建一些节点后,对他们进行连接,再返回头节点。

TR* CreeTree()
{
	TR*A1 = BuyTree('A');
	TR*B1 = BuyTree('B');
	TR*C1 = BuyTree('C');
	TR*D1 = BuyTree('D');
	TR*E1 = BuyTree('E');

	A1->left = B1;
	A1->right = C1;
	B1->left = D1;
	B1->right = E1;

	return A1;
}

代码中连接的,可以理解为:

 

Lonely丶墨轩

 实现好功能前操作,可以开始实现遍历功能了~


遍历功能

2.1前序遍历

前序遍历的走读思路:根---左节点---右节点

那么通过递归的方式即为:先打印根节点,再递归左节点,最后递归右节点

通过上图(构建的二叉树)  那么它的流程为:

(为了体现二叉树的结构,当递归遇到空节点时,先打印NULL再return)

1.A(即根节点)先打印A

2.递归左节点  再打印B 

3.再递归左节点 打印的D 

4.D递归左节点时为空,那么返回到B

5.B去递归右节点 打印E 

6.E去递归左节点,左节点为空,返回到B

7.B左右节点递归完,返回到A 

8.A再去递归右节点,打印C

则 前序遍历为  A---B---D---NULL---NULL---E---NULL---NULL---C---NULL---NULL

那么我们运行下,看打印结果

void PrevOrder(TR* root)
{
	if (root == NULL)
	{
		printf("NULL->");
		return;
	}

	printf("%c->", root->data);
	PrevOrder(root->left);
	PrevOrder(root->right);
}

2.2中序遍历

中序遍历的走读思路:左节点---根---右节点

那么通过递归的方式即为:先递归左节点---打印根---再递归右节点

通过上图(构建的二叉树)  那么它的流程为:

1.先递归左节点  A递归到B 打印B

2.B再递归左节点  D 

3.D再递归到左、右节点,均为空,返回B 

4.B再递归右节点  E   打印E

5.E再递归到左、右节点、均为空 返回B 

6.B左右节点均递归完后,返回A 

7.A的左节点递归完后 打印A 

8.A再递归右节点 C  再打印C 

9.C再递归左、右节点,均为空

10.返回A 

结束

则 中序遍历为  B---D---NULL---NULL---E---NULL---NULL---A---C---NULL---NULL

那么我们运行下 看打印结果

void InOrder(TR* root)
{
	if (root == NULL)
	{
		printf("NULL->");
		return;
	}

	PrevOrder(root->left);
	printf("%c->", root->data);
	PrevOrder(root->right);
}

2.3后续遍历

后序遍历的走读思路:左节点---右节点---根

那么通过递归的方式即为:先递归左节点---再递归右节点---打印根

通过上图(构建的二叉树)  那么它的流程为:

先递归左节点B  打印B 

B再递归D  打印D 

D再递归左、右节点,均为空,返回到B 

B再递归到右节点E 

E递归到左、右节点,均为空,返回到B 

B的左右节点递归完后,返回A 

A再递归到C  打印C

C再递归左、右节点均为空,再返回到A 

再打印A 

结束

则 后续遍历为  B---D---NULL---NULL---E---NULL---NULL---C---NULL---NULL---A

那么我们运行下 看打印结果

void CurOrder(TR* root)
{
	if (root == NULL)
	{
		printf("NULL->");
		return;
	}

	PrevOrder(root->left);
	PrevOrder(root->right);
	printf("%c->", root->data);
}

2.4层序遍历

层序遍历相交与另外三个遍历,是最好理解的,但是代码却比其他三个遍历难很多。

那么层序遍历是如果走读的呢?顾名思义就是一层层遍历。如图:

Lonely丶墨轩

先打印第一层 A  再打印第二层  B    C   再打印第三层  D    E   

则  层序遍历为  A---B---C---D---E  因为层序遍历比较好体现结果,所以不用打印空

因为这里是需要用到队列的,而C语言没有队列的库 所以我们需要自己手动写一个(这也是C的缺点之一,栈、队列 C语言均没有(有需要队列的我待会在最下方会给出源码

层序代码思路

首先初始化一个栈,

1.判断根节点是否为空,不为空时 把根节点放入队列  然后进循环(循环条件为队列为空时结束) 

2.利用结构体指针 接收头结点(即存储这个头数据)

3.我们让刚才进队列的头数据,出队列

4.利用这个指针存储的数据 打印这个结点的数据   

5.我们再判断它的左、右结点是否为空,不为空,就把不为空的结点放入队列 

需要注意  因为队列原来的STDataType原来是int  而我们需要返回一个结构体指针类型,所以重定义类型名的优势就体现出来了  我们只需要在栈的重定义类型名修改为结构体指针类型即可

typedef struct Linode* STDaType;

6.循环 至循环结束

这个是简化动图,添加文字的动图做的很乱,以后学好了,可以添加更详细的动图! 


操作、计算、查询功能

3.1计算结点个数

计算二叉树结点个数思路就是 递归到不为空的结点时+1 最后返回共加了几次1即为结点个数

首先判断结点是否为空,若为空返回0  若不为空则返回1。

这里有两种写法(思路一样)

一种是传一个值进去  没递归一次 判断不为空时,就自增++,但递归会有栈帧问题,所以需要换地址,会稍微麻烦点。

void TreeSize(TR* root,int* p)
{
	/*return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;*/
	if (root == NULL)
		return 0;

	++(*p);
	TreeSize(root->left,p);
	TreeSize(root->right,p);
}

另一种是用三目操作服,每次递归都+1,如果为空时返回0,此方法相较于上面的方法更简洁,但不利于理解。

int TreeSize(TR* root)
{
	return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}


 

3.2计算叶子结点个数

首先要了解叶子结点   叶子结点即为 当它没有左结点、右结点时,就把它称为叶子结点

那么代码则可以判断 当这个结点左、右子树为空时就返回1

代码就迎刃而解

首先判断结点是否为空 若为空返回0

若它左、右结点均为空,返回1

依次递归他的左与右最后将他们相加(则为左子树共有几个叶子)+(右子树共右几个叶子)


int BTreeLeafSize(TR* root)
{
	if (root == NULL)
		return 0;

	if (root->left == NULL && root->right == NULL)
		return 1;

	return BTreeLeafSize(root->left) + BTreeLeafSize(root->right);
}


3.3计算第K层结点个数

已根结点为1时 当走到第K层时 计算第K层的结点个数

本题思路需要多用到一个遍历,这个遍历记录着要计算的第K层  每递归一次 让K--,当K==1时,说明K已经走到了需要计算的那层,这时再++,最后把(左子树返回的总树)+(右子树返回的总数)就可以求出第K层的结点个数

先判断结点是否为空若为空返回0即可

这里只需判断一个条件 即 K==1时 就返回你

最后到递归左和递归右相加 即可求出

int BreeKlevelSize(TR* root, int k)
{
	if (root == NULL)
	return 0;

	if (k == 1)
		return 1;

	return BreeKlevelSize(root->left, k - 1) + BreeKlevelSize(root->right, k - 1);
}


3.4计算计算左子和又子大的节点个数 

这里只要计算左子树的结点总数与右子树的结点总数相比 大的那方再+1即为左子\右子大的结点总数

这里判断root是否为空 为空时就返回0

用left存放左子树

用right存放右子树

利用三目操作符相比  无论谁大 都+1(计算结点个数)

int BTreeDePth(TR* root)
{
	if (root == NULL)
		return 0;

	int left = BTreeDePth(root->left);
	int right = BTreeDePth(root->right);

	return left > right ? left + 1 : right + 1;
}

 

 


3.5二叉树查找

查找 顾名思义就是查找某个值  

思路为 依次递归,若查找到则返回,若查找不到,赋值空,若一直查找不到,最后则会返回空

​
TR* BTreeFind(TR* root, STDataType x)
{
	if (root == NULL)
		return 0;

	if (root->data == x)
		return root;

	TR* rel1 = BTreeFind(root->left, x);
	if (rel1)
		return rel1;

	TR* rel2 = BTreeFind(root->right, x);
	if (rel2)
		return rel2;

	return NULL;//若到最后都查找不到 返回NULL
}

​

 


3.6判断二叉树是否是完全二叉树

先来看完全二叉树的定义

完全二叉树的特点:叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部。

一棵深度为k且有个结点的二叉树称为满二叉树

根据二叉树的性质  满二叉树每一层的结点个数都达到了最大值, 即满二叉树的第i层上有(2的i次方-1)个结点 (i≥1) 

这里是需要用到队列的,它的代码思路根层序有点相像,并且思路较好理解

我们先来看非完全二叉树和完全二叉树在队列中结构

 不难看出他们区别  非完全二叉树中间会有掺杂NULL 而 完全二叉树中间不会掺杂NULL

所以我们可以利用此特点  

思路  当在队列中遇到NULL  就去判断NULL后面是否有值 如果有 就不是完全二叉树

若没有 就是完全二叉树

代码思路

1.创建队列。并初始化

2.当根结点不为空时,让他入队列。

3.用front接收结点,并让他出队列,判断这个front是否为空,当他为空,结束循环,让他进入下一个循环

4.当front不为空时,让他入结点的左,右结点

5.当循环结束

6.让他用front取结点  再出队列,当front不为空时,

(说明后面还有值  不是完全二叉树,返回false(假)) 

7.当front为空时,就继续循环,

8.直到循环结束时,还是为空时,说明他后面没有值,是完全二叉树 返回true

需要注意  因为队列原来的STDataType原来是int  而我们需要返回一个结构体指针类型,所以重定义类型名的优势就体现出来了  我们只需要在栈的重定义类型名修改为结构体指针类型即可

typedef struct Linode* STDaType;

 

 这两个动图分别对应了完全二叉树和非完全二叉树的情况

bool BTcomDlete(TR* root)
{
	Qnene p;
	QueueInit(&p);
	if (root)
	{
		QueuePush(&p, root);
	}
	while (!QueueEmpty(&p))
	{
		TR* front = QueueHeadTop(&p);
		QueuePop(&p);
		if (front == NULL)
		{
			break;
		}
		QueuePush(&p, front->left);
		QueuePush(&p, front->right);
	}
	while (!QueueEmpty(&p))
	{
		TR* front = QueueHeadTop(&p);
		QueuePop(&p);
		if (front)
		{
			return false;
			QueueDestory(&p);
		}
	}
	return true;
	QueueDestory(&p);
}

3.7销毁二叉树

销毁二叉树就是要销毁二叉树的每个结点

那么可以利用前面的后续遍历的原理  先走到最后的结点,先释放最后的结点,再返回,再释放,最后就可以全部释放

void BinaryTreeDestory(TR* root)
{
	if (root == NULL)
	{
		return;
	}
	BinaryTreeDestory(root->left);
	BinaryTreeDestory(root->right);
	free(root);
}

 


源码

这个源码为队列是声明

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef struct Linode* STDaType;

typedef struct QListNode
{
	struct QListNode* next;
	STDaType data;
}Queue;

typedef struct Qnene
{
	Queue* head;
	Queue* tail;
}Qnene;

//初始化队列
void QueueInit(Qnene* Q);

//队尾入
void QueuePush(Qnene* Q, STDaType x);

//队头出
void QueuePop(Qnene* Q);

//取对头元素
STDaType QueueHeadTop(Qnene* Q);

//取队尾元素
STDaType QueueTailTop(Qnene* Q);

//判空
bool QueueEmpty(Qnene* Q);

//获取队列的元素个数
int QueueSize(Qnene* Q);

//释放
void QueueDestory(Qnene* Q);

这个源码为队列的实现

#include"队列.h"

//初始化队列
void QueueInit(Qnene* Q)
{
	assert(Q);

	Q->head = Q->tail = NULL;
}

//队尾入队列
void QueuePush(Qnene* Q, STDaType x)
{
	assert(Q);
	Queue* newnode = (Queue*)malloc(sizeof(Queue));
	if (newnode == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	if (Q->tail == NULL)
	{
		Q->head = Q->tail = newnode;
	}
	else
	{
		Q->tail->next = newnode;
		Q->tail = newnode;
	}
}

//对头出
void QueuePop(Qnene* Q)
{
	assert(Q);

	if (Q->head->next == NULL)
	{
		free(Q->head);
		Q->head = Q->tail = NULL;
	}
	else
	{
		Queue* tail = Q->head->next;
		free(Q->head);
		Q->head = tail;
	}
}

//取队头元素
STDaType QueueHeadTop(Qnene* Q)
{
	assert(Q);

	return Q->head->data;
}

//取队尾元素
STDaType QueueTailTop(Qnene* Q)
{
	assert(Q);

	return Q->tail->data;
}

//判空
bool QueueEmpty(Qnene* Q)
{
	assert(Q);

	return Q->head == NULL;
}

//获取队列的元素个数
int QueueSize(Qnene* Q)
{
	int size = 0;
	Queue* cur = Q->head;
	while (cur)
	{
		++size;
		cur = cur->next;
	}
	return size;
}

//释放
void QueueDestory(Qnene* Q)
{
	Queue* tail = Q->head;
	while (tail)
	{
		Queue* next = tail->next;
		free(tail);
		tail = next;
	}
	Q->head = Q->tail = NULL;
}

这个源码为二叉树的声明

​
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef char STDataType;

typedef struct Linode
{
	struct Linode* left;
	struct Linode* right;
	STDataType data;
}TR;

//层序遍历
void LeveOreder(TR* root);

TR* CreeTree();

//前序遍历
void PrevOrder(TR* root);

//中序遍历
void InOrder(TR* root);

//后续遍历
void CurOrder(TR* root);

//计算二叉树节点个数
int TreeSize(TR* root);

//二叉树叶子节点个数
int BTreeLeafSize(TR* root);

//计算二叉树第K层的节点个数
int BreeKlevelSize(TR* root, int k);

//计算左子和又子大的节点个数
int BTreeDePth(TR* root);

//二叉树查找
TR* BTreeFind(TR* root, STDataType x);

//判断二叉树是否是完全二叉树
bool BTcomDlete(TR* root);

//销毁二叉树
void BinaryTreeDestory(TR* root);

​

这个源码为二叉树的实现

#include"Tree.h"
#include"队列.h"

TR* BuyTree(STDataType x)
{
	TR* newnode = (TR*)malloc(sizeof(TR));
	assert(newnode);
	newnode->data = x;
	newnode->left = NULL;
	newnode->right = NULL;

	return newnode;
}

void PrevOrder(TR* root)//前序遍历
{
	if (root == NULL)
	{
		printf("NULL->");
		return;
	}

	printf("%c->", root->data);
	PrevOrder(root->left);
	PrevOrder(root->right);
}

void InOrder(TR* root)//中序遍历
{
	if (root == NULL)
	{
		printf("NULL->");
		return;
	}

	PrevOrder(root->left);
	printf("%c->", root->data);
	PrevOrder(root->right);
}

void CurOrder(TR* root)//后续遍历
{
	if (root == NULL)
	{
		printf("NULL->");
		return;
	}

	PrevOrder(root->left);
	PrevOrder(root->right);
	printf("%c->", root->data);
}

TR* CreeTree()
{
	TR*A1 = BuyTree('A');
	TR*B1 = BuyTree('B');
	TR*C1 = BuyTree('C');
	TR*D1 = BuyTree('D');
	TR*E1 = BuyTree('E');

	A1->left = B1;
	A1->right = C1;
	B1->left = D1;
	B1->right = E1;

	return A1;
}

void LeveOreder(TR* root)//层序遍历
{
	Qnene q;
	QueueInit(&q);//初始化
	if (root)
	{
		QueuePush(&q, root);
	}
	while (!QueueEmpty(&q))
	{
		TR* front = QueueHeadTop(&q);
		QueuePop(&q);
		printf("%c->", front->data);

		if (front->left)
		{
			QueuePush(&q, front->left);
		}
		if (front->right)
		{
			QueuePush(&q, front->right);
		}
	}
	QueueDestory(&q);
}
//计算二叉树节点个数
int TreeSize(TR* root)
{
	return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}

//计算二叉树叶子节点个数
int BTreeLeafSize(TR* root)
{
	if (root == NULL)
		return 0;

	if (root->left == NULL && root->right == NULL)
		return 1;

	return BTreeLeafSize(root->left) + BTreeLeafSize(root->right);
}

//计算二叉树第K层的节点个数
int BreeKlevelSize(TR* root, int k)
{
	if (root == NULL)
	return 0;

	if (k == 1)
		return 1;

	return BreeKlevelSize(root->left, k - 1) + BreeKlevelSize(root->right, k - 1);
}

//计算计算左子和又子大的节点个数
int BTreeDePth(TR* root)
{
	if (root == NULL)
		return 0;

	int left = BTreeDePth(root->left);
	int right = BTreeDePth(root->right);

	return left > right ? left + 1 : right + 1;
}

//二叉树查找
TR* BTreeFind(TR* root, STDataType x)
{
	if (root == NULL)
		return 0;

	if (root->data == x)
		return root;

	TR* rel1 = BTreeFind(root->left, x);
	if (rel1)
		return rel1;

	TR* rel2 = BTreeFind(root->right, x);
	if (rel2)
		return rel2;

	return NULL;
}

//判断二叉树是否是完全二叉树
bool BTcomDlete(TR* root)
{
	Qnene p;
	QueueInit(&p);
	if (root)
	{
		QueuePush(&p, root);
	}
	while (!QueueEmpty(&p))
	{
		TR* front = QueueHeadTop(&p);
		QueuePop(&p);
		if (front == NULL)
		{
			break;
		}
		QueuePush(&p, front->left);
		QueuePush(&p, front->right);
	}
	while (!QueueEmpty(&p))
	{
		TR* front = QueueHeadTop(&p);
		QueuePop(&p);
		if (front)
		{
			return false;
			QueueDestory(&p);
		}
	}
	return true;
	QueueDestory(&p);
}

//销毁二叉树
void BinaryTreeDestory(TR* root)
{
	if (root == NULL)
	{
		return;
	}
	BinaryTreeDestory(root->left);
	BinaryTreeDestory(root->right);
	free(root);
}

这个源码为测试二叉树功能

#include"Tree.h"


void Test()
{
	TR* root = CreeTree();

	printf("二叉树前序遍历:\n");
	PrevOrder(root);//二叉树的前序遍历
	printf("\n");

	printf("二叉树中序遍历:\n");
	InOrder(root);//二叉树的中序遍历
	printf("\n");
	printf("二叉树后序遍历:\n");

	CurOrder(root);//二叉树的后续遍历
	printf("\n");

	printf("二叉树层序遍历:\n");
	LeveOreder(root);
	printf("\n");

	printf("计算二叉树节点个数:\n");
	int size = TreeSize(root);
	printf("二叉树节点个数:%d\n", size);

	printf("计算二叉树叶子节点个数:\n");
	int size1 = BTreeLeafSize(root);
	printf("二叉树叶子节点个数:%d\n", size1);

	printf("求第K层的节点个数:\n");
	int size2 = BreeKlevelSize(root, 2);
	printf("第K层节点个数:%d\n", size2);

	printf("计算左子和又子大的节点个数\n");
	int size3=BTreeDePth(root);
	printf("左子或右子大的节点个数为: %d\n", size3);

	printf("查找x的节点\n");
	TR* tree=BTreeFind(root, 'C');
	if (tree != NULL)
	{
		tree->data = 'F';
		LeveOreder(root);
		printf("修改成功!");
	}
	printf("\n");

	printf("判断二叉树是否是完全二叉树\n");
	if (BTcomDlete(root))
	{
		printf("此二叉树是完全二叉树\n");
	}
	else
	{
		printf("此二叉树不是完全二叉树\n");
	}

	printf("二叉树的销毁\n");
	BinaryTreeDestory(root);
	//free(root);
	root = NULL;
	printf("销毁成功!");
}

int main()
{
	Test();

	return 0;
}

如果本篇对您有帮助,希望能获得您的赞!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据结构-二叉树-更新完整版 的相关文章

  • /usr/bin/ld cannot find -lGL

    ubuntu 16 04虚拟机 装的Qt 5 10 随便写了个带UI的Demo 然后报错如下 解决如下 很多Linux发行版本 Qt安装完成后如果直接编译或者运行项目 会出现 cannot find lGL 错误 这是因为Qt找不到Open
  • 【matlab 斩波电路仿真】

    斩波电路仿真 要求 斩波电路原理 基本斩波电路 降压斩波电路搭建 结果分析 要求 斩波电路仿真 斩波电路原理 斩波电路的功能是将直流电变为另一固定电压或者可调电压的直流电 包括直接直流变流电路和简介直流变流电路 其中 直流变流电路也称为斩波
  • 某在线学习平台《数据挖掘》第八章课后习题

    此文章是本人结合课程内容和网上资料整理 难免有误差 仅供参考 1 下面哪种距离度量方法为欧几里得距离 2 以下哪个算法将两个簇的邻近度定义为不同簇的所有点对的平均逐对邻近度 它是一种凝聚层次聚类技术 AMIN 单链 BMAX 全链 C 组平

随机推荐

  • HK32F030MF4P6 SWD管脚功能复用GPIO

    由于电暖控制器项目上管脚不够 需要将SWD管脚复用 使用网上购买的JLINK 下载和串口调试特别方便 应用场景 往往GPIO管脚不够使用 需要将SWD下载管脚复用GPIO功能 需要用到以下设置 下载器需要接上RESET管脚 TSSOP20
  • (四)索引与数据完整性

    一 索引 1 索引的作用 快速存取数据 既可以改善数据库性能 又可以保证列值的唯一性 实现表与表之间的参照完整性 在使用ORDER BY GROUP BY子句进行数据检索时 利用索引可以减少排序和分组的时间 2 索引的分类 索引按照存储方法
  • PyQt5探索-0 用Pycharm配置PyQt5环境

    感觉是时候学习一下PyQt了 决定直接从PyQt5开始 用Pycharm做开发环境 因为之前用的Eric实在感觉不爽 今天先从配置环境开始 先安装好Pycharm Qt 安装Pycharm插件sip PyQt5 pyqt5 tools si
  • 【计算机视觉】论文单词理解—bells and whistles

    一 问题来源 最后在阅读论文的时候 遇到了一个单词 不是很理解 这个单词是bells and whistles 二 单词的理解 bells and whistles 它的含义并不是指 铃铛和口哨 其真正的含义是指 bells and whi
  • Mac 中的sublime text3 如何安装插件

    Mac 中的sublime text3 如何安装插件 相信大家在Windows系统中试用sublime text 的体验非常不错 我也是在Windows系统中使用了两年的时间 才转战Mac系统的 但是说实话 Mac系统好多东西都是十分不习惯
  • 时间序列学习(6)——LSTM中Layer的使用

    文章目录 1 复习一下 nn RNN 的参数 2 LSTM的 init 函数 3 LSTM forward 4 动手写一个简单的lstm层 1 复习一下 nn RNN 的参数 参数介绍 1 input size The number of
  • 梯度下降法(BGD,SGD,MSGD)python+numpy具体实现

    梯度下降是一阶迭代优化算法 为了使用梯度下降找到函数的局部最小值 一个步骤与当前位置的函数的梯度 或近似梯度 的负值成正比 如果相反 一个步骤与梯度的正数成比例 则接近该函数的局部最大值 该程序随后被称为梯度上升 梯度下降也被称为最陡峭的下
  • Proteus8.6软件安装教程

    关注公众号 免费获取资料 简介 是一款嵌入式系统仿真开发软件 同时也是英国Lab Center Electronics公司研发推出的最新的版本 该软件经实现了从原理图设计 单片机编程 系统仿真到PCB设计 真正实现了从概念到产品的完整设计
  • LeetCode338-比特位计数

    开学感觉已经是遥遥无期了 我的论文啊 我的工作啊 我该如何抉择 题目描述 给定一个非负整数 num 对于 0 i num 范围中的每个数字 i 计算其二进制数中的 1 的数目并将它们作为数组返回 示例 1 输入 2 输出 0 1 1 示例
  • deeplin显示安装空间不够,安装Deepin V20需要64GB以上磁盘空间,本文教你减小的方法...

    在安装Deepin V20操作系统时会有一个提示 说至少要64GB磁盘空间 建议在128GB以上 如果你设置少于64GB空间就不能正常安装下去 这时有方法可以解决的 你可以减小安装的磁盘空间 让32G的U盘也能够用上Deepin V20系统
  • 软件设计师上午题——第八章 UML

    软件设计师备考 UML 一 事物 1 UML 2 UML事物 1 结构事务 静态事务 2 行为事务 动态事务 3 分组事务 组织部分 4 注释事务 解释部分 二 关系 1 依赖关系 2 关联 聚合 组合关系 3 泛化关系 4 实现关系 5
  • 基于教学优化算法求解TSP问题(附Matlab代码)

    基于教学优化算法求解TSP问题 附Matlab代码 旅行商问题 Traveling Salesman Problem 简称TSP 是一个经典的组合优化问题 其目标是找到一条最短路径 使得一个旅行商能够访问一系列城市并返回起始城市 同时每个城
  • wordpress发表文章之后查看显示404

    刚刚写了一篇LAMP wordpress搭建博客的 发表成功之后想看一下效果 结果显示404 OMG 难道没成功 在后台所有文章里显示有 但是点击却显示404 404表示为指向的链接不存在 于是发现自己访问的地址为http www zhao
  • Python入门(一)——环境的搭建,创建第一个Python项目:Hello World

    Python入门 一 环境的搭建 创建第一个Python项目 Hello World 一 安装环境 安装就很简单了 我们进入官网Python 然后下载对应的版本就好了 如果你是Liunx的话 可以直接运行python 关于环境的配置 大家百
  • Uncaught SyntaxError: The requested module ‘/node_modules/.vite/...‘ does not provide an export ...

    项目启动正常 但是页面不显示且打印报错 Uncaught SyntaxError The requested module node modules vite deps vue js v 84e66e8d does not provide
  • 缺失值填充2——python 热卡填充(Hot deck imputation)、冷卡填充(Cold deck imputation)

    基本概念 热卡填充 在完整数据中找到一个与它最相似的对象 用最相似的值填充当前值 冷卡填充 通过其他途径找到能填充缺失部分的值 热卡填充其实就是使用KNN去预测的一种特殊形式 KNN是参考K个 而热卡填充是参考最近的1个 所以热卡填充可以用
  • 95-36-025-ChannelHandler-ChannelHandlerAdapter

    文章目录 1 概述 2 继承体系 3 isSharable 1 概述 2 继承体系 3 isSharable 作为ChannelHandler的默认实现 ChannelHandlerAdapter有个重要的方法isSharable 代码如下
  • Windows XP的网上邻居访问设置

    Windows XP的网上邻居访问设置 more Windows XP的网上邻居有许多差强人意的地方 访问速度慢 无法访问其他主机 其实这些问题通过简单的设置都可以很好地解决 在这之前先确保能够互相PING通 1 开启guest账户 2 允
  • JVM---堆(概述)

    堆 概述 一个JVM实例只存在一个堆内存 堆也是Java内存管理的核心区域 Java堆区在JVM启动的时候即被创建 其空间大小也就确定了 是JVM管理的最大一块内存空间 堆内存的大小是可以调节的 Java虚拟机规范 规定 堆可以处于物理 上
  • 数据结构-二叉树-更新完整版

    目录 二叉树初识 实现二叉树的功能 功能前操作 遍历功能 操作 计算 查询功能 源码 因为上次二叉树的文章的功能不全 所以这次更新一个完整版的二叉树文章 这篇文章有些功能是需要用到队列知识的 所以对队列不了解的可以先去看看这篇队列 详解 因