【数据结构之二叉树的构建和遍历】

数据结构学习笔记---009

  • 数据结构之二叉树
    • 1、二叉树的概念和结构
      • 1.1、回顾二叉树的重要性质
      • 1.2、回顾二叉树的主要分类
      • 1.1、如何实现二叉树?
    • 2、二叉树的实现
      • 2.1、二叉树的BinaryTree.h
      • 2.2、二叉树的BinaryTree.c
        • 2.2.1、二叉树的构建
        • 2.2.2、二叉树销毁
        • 2.2.3、二叉树前序、中序、后序遍历操作
        • 2.2.4、二叉树取结点个数操作
        • 2.2.5、二叉树取叶子结点个数操作
        • 2.2.6、取二叉树的高度/深度操作
        • 2.2.7、二叉树取第k层结点个数操作
        • 2.2.8、二叉树取查找值为x的节点操作
        • 2.2.9、二叉树层序遍历操作
        • 2.2.10、二叉树判断是否为完全二叉树操作
        • 2.2.11、二叉树的判空
      • 2.3、二叉树的main.c
    • 3、二叉树OJ巩固练习
      • 3.1、练习题1:二叉树的深度
      • 3.2、练习题2:单值二叉树
      • 3.3、练习题3:相同的树
      • 3.4、练习题4:二叉树的前序遍历 存入数组
      • 3.5、练习题5:对称二叉树
      • 3.6、练习题6:另一棵树的子树
      • 3.7、练习题7:计算左叶子节点个数

数据结构之二叉树

前言:
前篇学习了 数据结构之树和二叉树的基本概念知识,那么这篇继续完善二叉树的相关知识并完成实现二叉树的构建和遍历的内容。

/知识点汇总/

1、二叉树的概念和结构

因为前篇已经非常详细的单独学习了数和二叉树的基本知识概念,那么这里就简单回顾一下即可。
概念
二叉树(Binary Tree)是树形结构的一个重要类型。每个节点最多只能有两棵子树,且有左右之分。
它的定义可以概括为:一个n个有限元素的集合,该集合或者为空、或者由一个称为根的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成。
形象一点就是:

(1)空二叉树——(a);
(2)只有一个根结点的二叉树——(b);
(3)只有左子树——©;
(4)只有右子树——(d);
(5)完全二叉树——(e)

1.1、回顾二叉树的重要性质

1.二叉树第i层上的结点数目最多为2^(i-1) (i≥1)。
2.深度为k的二叉树至多有2^k-1个结点(k≥1)。
3.包含n个结点的二叉树的高度至少为log2(n+1)。
4.在任意一棵二叉树中,若终端结点的个数为n0,度为2的结点数为n2,则n0=n2+1。
5.如果有一颗n个结点的完全二叉树(其深度为⌊log2n⌋+1)的结点按层序编号(从第一层到最后一层,每层从左到右),对任一结点i(1≤i≤n):
1)如果i=1,则结点i是二叉树的根,无双亲;如果i>1,则其双亲是结点⌊i/2⌋。
2)如果2i>n,则结点i无左孩子(结点i为叶子结点);否则其左孩子LCHILD(i)是结点2i。
3)如果2i+1>n,则结点i无右孩子,否则其右孩子RCHILD(i)是结点2i+1。

1.2、回顾二叉树的主要分类

1.满二叉树:如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,那么这棵二叉树就被称为满二叉树。
2.完全二叉树:除最后一层外,每一层上的结点数均达到最大值;在最后一层上只缺少右边的若干结点。每个结点最多有两个子树,因此不存在度大于2的结点。左子树和右子树是有顺序的,次序不能任意颠倒。
3.二叉搜索树(二叉排序树):可以为空树,或者是具备如下性质:若它的左子树不空,则左子树上的所有结点的值均小于根节点的值;若它的右子树不空,则右子树上的所有结点的值均大于根节点的值,左右子树分别为二叉排序树。
4.平衡二叉树:这是一种概念,是二叉查找树的一个进化体,它有几种实现方式:红黑树、AVL树。平衡二叉树的特点是任意节点的子树的高度差都小于等于1。

1.1、如何实现二叉树?

二叉树的存储结构分类
1.二叉树的数组存储结构
一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费等问题。
并且实际应用中,也只有堆会用数组的形式存储。因为堆满足完全二叉树

typedef int HPDataType;
typedef struct Heap
{
	HPDataType* a;
	int size;
	int capacity;
}HP;

2、二叉树的链式存储结构
常用链表来指示元素的逻辑关系。
通常,以链表中的每一个结点,三个域组成,分别是数据域、左指针域和右指针域,左指针指向左孩子,右指针指向右孩子。
链式结构也分为二叉链和三叉链,一般是二叉链。高阶数据结构涉及三叉链。

typedef int BTDataType;
typedef struct BinaryTreeNode
{
	BTDataType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}TreeNode;

2、二叉树的实现

2.1、二叉树的BinaryTree.h

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

typedef char BTDataType;

typedef struct BinaryTreeNode
{
	BTDataType Val;
	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);

// 二叉树的高度/深度
int BinaryTreeHeight(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);


//创建队列结构体成员与变量
typedef struct BinaryTreeNode* QDatetype;//注意这里的返回类型和参数与二叉树的接口类型要对应

typedef struct QueueNode
{
	QDatetype val;
	struct QueueNode* next;
}QNode;

typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;

//队列初始化
void QueueInit(Queue* pq);

//队列销毁
void QueueDestory(Queue* pq);

//元素入队
void QueuePush(Queue* pq, QDatetype x);

//元素出队
void QueuePop(Queue* pq);

//获取队头元素
QDatetype QueueFront(Queue* pq);

//获取队尾元素
QDatetype QueueBack(Queue* pq);

//获取队列元素个数或队列大小
int QueueSize(Queue* pq);

//队列判断空
bool QueueEmpty(Queue* pq);

// 层序遍历
void BinaryTreeLevelOrder(BTNode* root);

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

//写法2:
//int BinaryTreeComplete2(BTNode* root);

2.2、二叉树的BinaryTree.c

2.2.1、二叉树的构建
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi)
{
	assert(a);
	if (a[*pi] == '#' || *pi >= n)
	{
		++(*pi);
		return NULL;
	}
	BTNode* root = (BTNode*)malloc(sizeof(BTNode));
	if (root == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	root->Val = a[*pi];
	++(*pi);
	root->left = BinaryTreeCreate(a, n, pi);
	root->right = BinaryTreeCreate(a, n, pi);
	return root;
}
2.2.2、二叉树销毁
// 二叉树销毁
void BinaryTreeDestory(BTNode** root)
{
	if (*root == NULL)
	{
		return;
	}
	BinaryTreeDestory(&(*root)->left);
	BinaryTreeDestory(&(*root)->right);
	free(*root);
	*root = NULL;
}
2.2.3、二叉树前序、中序、后序遍历操作
// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root)
{
	if (root == NULL)
	{
		//printf("# ");
		return;
	}
	printf("%c ", root->Val);
	BinaryTreePrevOrder(root->left);
	BinaryTreePrevOrder(root->right);
}

// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
	if (root == NULL)
	{
		//printf("# ");
		return;
	}
	BinaryTreeInOrder(root->left);
	printf("%c ", root->Val);
	BinaryTreeInOrder(root->right);
}

// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
	if (root == NULL)
	{
		//printf("# ");
		return;
	}
	BinaryTreePostOrder(root->left);
	BinaryTreePostOrder(root->right);
	printf("%c ", root->Val);
}

2.2.4、二叉树取结点个数操作
// 二叉树节点个数
int BinaryTreeSize(BTNode* root)
{
	return root == NULL ? 0 : BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}
2.2.5、二叉树取叶子结点个数操作
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root)
{
	//为空返回0,不能assert,否则递归走不动
	if (root == NULL)
	{
		return 0;
	}
	//只有根节点或叶子节点,则返回1
	if (root->left == NULL && root->right == NULL)
	{
		return 1;
	}
	//其余情况的叶子节点=左子树叶子节点+右子树叶子节点
	return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}
2.2.6、取二叉树的高度/深度操作
int BinaryTreeHeight(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	return fmax(BinaryTreeHeight(root->left), BinaryTreeHeight(root->right)) + 1;
}
2.2.7、二叉树取第k层结点个数操作
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
	assert(k > 0);
	//为空
	if (root == NULL)
		return 0;
	//根节点
	if (k == 1)
		return 1;
	//其余层,递归k-1
	return BinaryTreeLevelKSize(root->left, k - 1) + BinaryTreeLevelKSize(root->right, k - 1);
}
2.2.8、二叉树取查找值为x的节点操作
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	//参数为空
	if (root == NULL)
	{
		return NULL;
	}
	//根节点匹配,则返回空节点
	if (root->Val == 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;
}
2.2.9、二叉树层序遍历操作
//队列初始化
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}

//队列销毁
void QueueDestory(Queue* pq)
{
	assert(pq);
	//工作指针,遍历销毁
	QNode* cur = pq->phead;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}

//元素入队
void QueuePush(Queue* pq, QDatetype 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++;
}

//元素出队
void QueuePop(Queue* pq)
{
	assert(pq);
	//判空,空队列不能出队
	assert(pq->phead);
	//兼容只有一个节点的情况
	//delfront保存当前头指针地址,以便free掉,并防止内存泄漏
	QNode* delfront = pq->phead;
	//首元素出队,头指针直接后移即可
	pq->phead = pq->phead->next;
	free(delfront);
	delfront = NULL;
	//只有一个节点时,出队后,为空,那么尾指针也得置空
	if (pq->phead == NULL)
	{
		pq->ptail = NULL;
	}
	pq->size--;
}

//获取队头元素
QDatetype QueueFront(Queue* pq)
{
	assert(pq);
	//判空,为空没有元素取
	assert(pq->phead);
	return pq->phead->val;
}

//获取队尾元素
QDatetype QueueBack(Queue* pq)
{
	assert(pq);
	//判空,为空没有元素取
	assert(pq->phead);
	return pq->ptail->val;
}

//获取队列元素个数或队列大小
int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}

//队列判断空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->phead == NULL;
}

// 层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
	assert(root);
	//创建队列
	Queue q;
	QueueInit(&q);
	if (root)
	{
		QueuePush(&q, root);
	}
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		printf("%c ", front->Val);
		if (front->left)
		{
			QueuePush(&q, front->left);
		}
		if (front->right)
		{
			QueuePush(&q, front->right);
		}
		QueuePop(&q);
	}
	printf("\n");
	QueueDestory(&q);
}

2.2.10、二叉树判断是否为完全二叉树操作

判断完全二叉树的思路1;
1.如果树为空,直接返回错误;
2.如果树非空,层序遍历二叉树;
3.如果一个结点左右孩子均Not NULL时,则pop该结点,将其左右孩子入队列;
4.如果遇到一个结点,左孩子为空,而右孩子非空,则一定不为完全二叉树;
5.如果遇到一个结点,左孩子不为空,而右孩子为空;或者是左右孩子均为空,则结点之后的队列的结点都为叶子结点;
满足以上条件则为完全二叉树,否则不是完全二叉树。
核心思想:类似于层序一层层的节点构造而成,即最后一层的节点上面的层节点都是满的。前提是最后一层不是根节点,即第一层.
所以遍历不连续就不是完全二叉树,并且队列比栈适用于判断的重要原因之一就是,第一个NULL出队列时,所有的非空节点一定会进队列。

// 判断二叉树是否是完全二叉树
bool BinaryTreeComplete(BTNode* root)
{
	assert(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);
	}
	//因为出到空,退出循环后,再写一个循环判断队列里是否还有非空
	//若有非空,则false,若没有非空或不进入循环,则true
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		//遇见空就结束
		if (front)
		{
			QueueDestory(&q);
			return false;
		}
	}
	QueueDestory(&q);
	return true;
}

2.2.11、二叉树的判空
//二叉树判空
bool BinaryTreeEmpty(BTNode* root)
{
	return root == NULL;
}

2.3、二叉树的main.c

#include "BinaryTree.h"

int main()
{
	char str[] = "ABC##DE#G##F###";// ABC##DE#G##F###
	//char str2[] = "ABCDEGF";
	int len = strlen(str);
	int NodeNum = 0;
	BTNode* tree = BinaryTreeCreate(str, len, &NodeNum);

	printf("前序遍历:");
	// 二叉树前序遍历 
	BinaryTreePrevOrder(tree);
	printf("\n");

	printf("中序遍历:");
	// 二叉树中序遍历
	BinaryTreeInOrder(tree);
	printf("\n");

	printf("后序遍历:");
	// 二叉树后序遍历
	BinaryTreePostOrder(tree);
	printf("\n");

	// 二叉树节点个数
	printf("节点个数:%d\n", BinaryTreeSize(tree));

	printf("层序遍历:");
	// 层序遍历
	BinaryTreeLevelOrder(tree);
	printf("\n");

	//二叉树判空
	if (BinaryTreeEmpty(tree))
	{
		printf("空树\n");
	}
	else
	{
		printf("非空树\n");
	}

	// 判断二叉树是否是完全二叉树
	if (BinaryTreeComplete(tree))
	{
		printf("是完全二叉树\n");
	}
	else
	{
		printf("非完全二叉树\n");
	}

	// 二叉树叶子节点个数
	printf("叶子节点:%d\n", BinaryTreeLeafSize(tree));

    //计算二叉树的高度
	printf("二叉树的高度:%d\n", BinaryTreeHeight(tree));

	// 二叉树第k层节点个数
	printf("第k层叶子节点:%d\n", BinaryTreeLevelKSize(tree, 3));

	// 二叉树查找值为x的节点
	printf("第k层叶子节点:%c\n", BinaryTreeFind(tree, 'E')->Val);

	// 二叉树销毁
	BinaryTreeDestory(&tree);
	return 0;
}

运行结果,如图所示
在这里插入图片描述

3、二叉树OJ巩固练习

3.1、练习题1:二叉树的深度

核心思想就是取左右子树叶子节点的高度,将比较大的值+根节点的第一层即可。因为计算是以0计算所以需要把第一层加回来。或者+1也可以理解为(考虑只有根节点),加自己本身这层,就像数数需要加上自己。
方法1:fmax调用库函数更方便,fmax用于比较出较大值并返回较大值。头文件:<math.h>
方法2:通过变量保存,递归的值,最后比较大小之后加回第一层。

//方法1:fmax函数
/**/
int calculateDepth(struct TreeNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	return fmax(calculateDepth(root->left), calculateDepth(root->right)) + 1;
}


//方法2:保存变量
/**/
int calculateDepth(struct TreeNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	int left = calculateDepth(root->left);
	int right = calculateDepth(root->right);
	return left > right ? left + 1 : right + 1;
}

3.2、练习题2:单值二叉树

单值二叉树(每个节点都具有相同的值) — 给定的二叉树是单值二叉树就返回true,否则就返回false
思路:排除法和分治法,检查每个节点和他的孩子的值是否匹配。

bool isUnivaTree(struct TreeNode* root)
{
	if (root == NULL)
	{
		return true;
	}
	//排除法,排除左孩子值与其父节点值不等
	if (root->left && root->lefd->val != root->val)
	{
		return false;
	}
	//排除法,排除右孩子值与其父节点值不等
	if (root->right && root->right->val != root->val)
	{
		return false;
	}
	//执行递归,返回结果,若是不满足上述排除的情况,说明满足单值二叉树
	return isUnivaTree(root->left) && isUnivaTree(root->right);
}

3.3、练习题3:相同的树

相同的树 — 给你两棵二叉树的根节点p和q,编写一个函数来检验这两棵树是否相同(如果这两棵树的结构和节点值相同,则认为是相同的)
思路:排除法和分治法,自己比,左子树比,右子树比

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);
}

3.4、练习题4:二叉树的前序遍历 存入数组

这道题的关键在于获取结点个数开辟数组,并涉及前序遍历的参数设计细节问题。
方法1:递归法
方法2:全局变量法(不推荐)
方法3:指针法

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

void preorder(struct TreeNode* root, int* a, int i)
{
	if (root == NULL)
		return;
	a[i++] = root->val;
	preorder(root->left,a,i);
	preorder(root->right,a,i);
}
//全局变量法
//int i = 0;
//void preorder(struct TreeNode* root, int* a)
//{
//	if (root == NULL)
//		return;
//	a[i++] = root->val;
//	preorder(root->left, a);
//	preorder(root->right, a);
//}

//指针法
void preorder(struct TreeNode* root, int* a, int* pi)
{
	if (root == NULL)
		return;
	a[(*pi)++] = root->val;
	preorder(root->left, a, pi);
	preorder(root->right, a, pi);
}

int* preorderTraversal(struct TreeNode* root, int* returnSize)
{
	int n = TreeSize(root);
	int* a = (int*)malloc(sizeof(int) * n);
	*returnSize = n;
	
    //方法1:递归法
	preorder(root, a, 0);
    
    //方法2:全局变量法(不推荐)
	//i= 0; --- 必须置0
	//preorder(root, a); -- 全局变量法,但尽量不用
    
    //方法3:指针法
	//int i = 0;
	//preorder(root, a, &i);
	return a;
}

3.5、练习题5:对称二叉树

对称(镜像)二叉树 — 给你一个二叉树的根结点root,检查它是否轴对称。
思路:设计一个复用函数,继续利用排除法和递归遍历,排除不成立的结果,能成功返回的对称二叉树。

bool _isSymmetric(struct TreeNode* root1, struct TreeNode* root2)
{
	if (root1 == NULL && root2 == NULL)
	{
		return true;
	}
	//一个为空,另一个不为空
	if (root1 == NULL || root2 == NULL)
	{
		return false;
	}
	//都不为空
	if (root1->val != root2->val)
	{
		return false;
	}
	return _isSymmetric(root1->left, root2->right) && _isSymmetric(root1->right, root2->left);
}
bool isSymmetric(struct TreeNode* root)
{
	return _isSymmetric(root->left, root->right);
}

3.6、练习题6:另一棵树的子树

另一棵树的子树:给两颗二叉树,检验一棵树是否包含另一棵树的子树。
思路:结合上面相同的树的方法,去匹配子树

//相同的树
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)
		return false;
	//根节点匹配,调用相同的树方法,去匹配
	if (root->val == subRoot->val)
		return isSameTree(root, subRoot);
	//递归前序遍历匹配
	return isSameTree(root, subRoot) || 
	isSameTree(root->left, subRoot) || 
	isSameTree(root->right, subRoot);
}

3.7、练习题7:计算左叶子节点个数

计算二叉树中左叶子节点的个数。
思路:递归遍历左右子树,累计左叶子节点个数即可。
1.判断是否为空
2.判断是否为左叶子节点
3.递归累加。

// 二叉树左叶子节点个数
int BinaryTreeLeftLeafSize(BTNode* root)
{
	//为空返回0
	if (root == NULL)
	{
		return 0;
	}
	//判断有左孩子,并是左叶子节点
	if (root->left && root->left->left == NULL && root->left->right == NULL)
	{
		return 1;
	}
	//其余情况的左叶子节点=左子树叶子节点+右子树叶子节点
	return BinaryTreeLeftLeafSize(root->left) + BinaryTreeLeftLeafSize(root->right);
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Time Series】LSTM代码实战

一、简介 还是那句话&#xff0c;"时间序列金融"是一个很有"钱"景的话题&#xff0c;还是想尝试采用Stock时间序列预测任务DeepLearning。本文提供了LSTM预测股票的源代码。 二、算法原理 长短期记忆网络&#xff08;LSTM&#xff09;是一种特殊的循环神经…

以“美”为鉴,探寻香港比特币现货ETF的未来发展

出品&#xff5c;欧科云链研究院 作者&#xff5c;Hedy Bi 根据The Block于1月29日的报道&#xff0c;嘉实国际成为了首家向香港证监会提交比特币现货ETF申请的机构。早在去年12月22日&#xff0c;香港证监会发布了《有关证监会认可基金投资虚拟资产的通函》&#xff0c;明确…

突破瓶颈,提升开发效率:Spring框架进阶与最佳实践-IOC

IOC相关内容 1.1 bean基础配置1.1.1 bean基础配置(id与class)1.1.2 bean的name属性步骤1&#xff1a;配置别名步骤2:根据名称容器中获取bean对象步骤3:运行程序 1.1.3 bean作用范围scope配置1.1.3.1 验证IOC容器中对象是否为单例验证思路具体实现 1.1.3.2 配置bean为非单例1.1.…

C++文件操作(1)

C文件操作 1.文本的写入及读取文本文件写入文本文件读取 2.二进制文件的写入及读取二进制文件写入二进制文件读取 3.小结 C也有处理文件的能力&#xff0c;其功能实现依赖文件流。文件流是C中用来处理文件输入输出的一种流类。文件流可以用于从文件中读取数据或将数据写入到文件…

开发工具git分支冲突解决

在团队协作的软件开发过程中&#xff0c;Git是一款广泛使用的版本控制系统。然而&#xff0c;当多个开发者同时修改同一文件或代码段时&#xff0c;就会产生分支冲突。解决这些冲突需要仔细的协调和技术知识。本篇博客将介绍Git分支冲突的解决方法&#xff0c;以及开发工具和最…

四工序开料机可以加工什么产品

四工序开料机是木工机械设备中一款重要设备&#xff0c;该设备主要的功能是开料、打孔、拉槽等&#xff0c;一机多用&#xff0c;凭借多功能的加工效果&#xff0c;实现高速加工的效果&#xff0c;那么这样的设备可以加工什么类型的产品呢&#xff1f;大家对此了解多少呢&#…

idea报错 :(java: 找不到符号)

java: 找不到符号 符号: 变量 adminService 位置: 类 com.example.controller.WebController 查到网上一个办法&#xff1a;因为项目是maven&#xff1a;先点clean在点package

anaconda离线安装包的方法

当设备没有网络时&#xff0c;可以使用有网络的设备先下载所需安装包&#xff0c;然后离线拷贝到需要安装的设备&#xff0c;最后安装。 一. 下载所需安装包 下载命令&#xff1a;使用pip download。详细描述参见pip download -h 以"blind-watermark"为例。 pip …

一站式在线协作办公软件ONLYOFFICE,协作更便捷

1、ONLYOFFICE是什么&#xff1f; ONLYOFFICE是一款功能强大的在线协作办公软件&#xff0c;可以创建编辑Word文档、Excel电子表格&#xff0c;PowerPoint&#xff08;PPT&#xff09;演示文稿、Forms表单等多种文件。ONLYOFFICE支持多个平台&#xff0c;无论使用的是 Windows、…

真机调试,微信小程序,uniapp项目在微信开发者工具中真机调试,手机和电脑要连同一个wifi,先清空缓存,页面从登录页进入,再点真机调试,这样就不会报错了

微信小程序如何本地进行真机调试&#xff1f;_unity生成的微信小程序怎么在电脑上真机测试-CSDN博客 微信小程序 真机调试 注意事项 uniapp项目在微信开发者工具中真机调试&#xff0c;手机和电脑要连同一个wifi&#xff0c;先清空缓存&#xff0c;页面从登录页进入&#xf…

怎么保护U盘数据?如何提高U盘的安全性?

U盘作为常用的移动储存设备&#xff0c;能够帮我们存储大量数据。而为了避免数据泄露&#xff0c;我们需要采用专业的方式提高U盘的安全性。那么&#xff0c;怎么保护U盘数据呢&#xff1f;下面我们就一起来了解一下。 如何提高U盘的安全性&#xff1f; 提高U盘数据安全性的方…

3DMAX一键生成样条线纤维插件使用方法

3DMAX一键生成样条线纤维插件使用教程 3DMAX一键生成样条线纤维插件&#xff0c;是一个强大的脚本工具&#xff0c;用于围绕选定的样条线路径创建纤维。它有许多设置用于微调纤维的形状和材质。 【适用版本】 3dMax2010 – 2024&#xff08;不仅限于此范围&#xff09; 【安装…

Rust基础篇之注释、函数

&#x1f339;作者主页&#xff1a;青花锁 &#x1f339;简介&#xff1a;Java领域优质创作者&#x1f3c6;、Java微服务架构公号作者&#x1f604; &#x1f339;简历模板、学习资料、面试题库、技术互助 &#x1f339;文末获取联系方式 &#x1f4dd; 往期专栏回顾 专栏描述…

Wireshark网络协议分析 - UDP协议

在我的博客阅读本文 文章目录 1. 基础2. 实战2.1. 用Go写一个简单的UDP服务器与客户端2.2. Wireshark抓包分析 3. UDP与TCP的区别4. 参考资料 1. 基础 UDP包的数据结构&#xff1a; 2. 实战 2.1. 用Go写一个简单的UDP服务器与客户端 我们这里使用Golang写了一个简单的9830端…

appsmith安装手记:4.Sql server数据库容器安装

appsmith安装好&#xff0c;那就可以看是练练手。 数据当然是来自数据库&#xff0c;那就连接局域网中现成的一台数据库服务器试试&#xff0c;但是连接数据库的时候一直错误。 找到/home/appsmith/backend 目录下的日志&#xff0c;看到了错误&#xff1a; [rootlocalhost bac…

【HarmonyOS应用开发】ArkUI 开发框架-基础篇-第二部分(八)

八、Column&Row组件的使用 概述 一个丰富的页面需要很多组件组成&#xff0c;那么&#xff0c;我们如何才能让这些组件有条不紊地在页面上布局呢&#xff1f;这就需要借助容器组件来实现。 容器组件是一种比较特殊的组件&#xff0c;它可以包含其他的组件&#xff0c;而…

Qt 调用系统键盘

Wow64DisableWow64FsRedirection(&pvoid) 函数用于禁用 32 位 Windows 程序对文件系统重定向的支持。它将禁用文件系统重定向&#xff0c;以便在运行 32 位应用程序时&#xff0c;可以访问 64 位系统目录。pvoid 是一个指向先前启用的文件系统重定向状态的指针。 构建了要…

《动手学深度学习(PyTorch版)》笔记4.8

注&#xff1a;书中对代码的讲解并不详细&#xff0c;本文对很多细节做了详细注释。另外&#xff0c;书上的源代码是在Jupyter Notebook上运行的&#xff0c;较为分散&#xff0c;本文将代码集中起来&#xff0c;并加以完善&#xff0c;全部用vscode在python 3.9.18下测试通过。…

文本三剑客之grep

目录 一、正则表达式 1、什么是正则表达式 2、元字符 3、扩展正则表达式元字符 二、grep 一、正则表达式 1、什么是正则表达式 REGEXP&#xff1a; Regular Expressions&#xff0c;由一类特殊字符及文本字符所编写的模式&#xff0c;其中有些字符&#xff08;元字符&#…

DevOps落地笔记-04|看板方法:成员工作内容清楚明白方法

上一讲主要介绍了用户故事以及如何通过讲好用户故事解决团队沟通的问题&#xff0c;争取达成共识。当团队都理解了用户需求之后&#xff0c;就进入到后续的产品设计、代码开发、功能测试、直到生产部署等环节了。作为软件从业人员都知道&#xff0c;后续的步骤不太可能一帆风顺…