数据结构——二叉树的实现

news2024/12/26 2:42:57

什么是二叉树?

二叉树(binary tree)是指树中节点的度不大于2的有序树,它是一种最简单且最重要的树。二叉树的递归定义为:二叉树是一棵空树,或者是一棵由一个根节点和两棵互不相交的,分别称作根的左子树和右子树组成的非空树;左子树和右子树又同样都是二叉树。
在这里插入图片描述

1.通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树

在这里插入图片描述
这段代码实现了根据前序遍历的数组构建二叉树的过程。其原理是通过递归实现的,对于当前节点,如果它是空节点或者数组已经遍历完,那么返回NULL,否则创建新节点并赋初值,然后递归构建左子树和右子树。具体实现如下:

// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi)
{
	//如果数组已经遍历完或者当前节点是空节点,返回空指针
	if (*pi >= n || a[*pi] == '#')
	{
		//当前节点为空,返回NULL
		(*pi)++;
		return NULL;
	}
	//创建新节点并赋初值
	BTNode* root = new BTNode;
	root->_data = a[*pi];
	root->_left = NULL;
	root->_right = NULL;
	//递归构建左子树和右子树
	(*pi)++;
	root->_left = BinaryTreeCreate(a, n, pi);
	(*pi)++;
	root->_right = BinaryTreeCreate(a, n, pi);
	return root;
}

其中,a表示前序遍历的数组,n表示数组的长度,pi表示数组的当前位置。如果数组已经遍历完或者当前节点是空节点,那么返回空指针。否则,创建一个新节点,并将当前位置向后移动一位,然后递归构建左子树和右子树。最终返回根节点,即构建好的二叉树。

2.二叉树销毁

这段代码实现了二叉树的销毁过程。其原理是通过递归实现的,对于当前节点,如果它为空节点,直接返回;否则递归销毁左子树和右子树,最后释放当前节点的内存。具体实现如下:

// 二叉树销毁
void BinaryTreeDestory(BTNode** root)
{
	if (*root == NULL)
		//如果当前节点为空,直接返回
		return;
	//递归销毁左子树和右子树
	BinaryTreeDestory(&((*root)->_left));
	BinaryTreeDestory(&((*root)->_right));
	//释放当前节点的内存
	free(*root);
	*root = NULL;
}

其中,root表示当前节点的指针,如果当前节点为空,直接返回;否则递归销毁左子树和右子树,最后释放当前节点的内存,并将当前节点的指针设置为NULL。递归过程会一直向下遍历二叉树,直到叶子节点,然后逐层返回,将每个节点释放,并将其左右子节点的内存全部释放。最终得到一个空的二叉树。

3.二叉树节点个数

在这里插入图片描述

// 二叉树节点个数
int BinaryTreeSize(BTNode* root)
{
	if (root == NULL)
		//如果当前节点为空返回0
		return 0;
	//返回左子树节点个数加上右节点个数再加上1(当前节点)
	return BinaryTreeSize(root->_left) +
		BinaryTreeSize(root->_right) + 1;
}

4.二叉树叶子节点个数

这段代码实现了计算二叉树节点个数的过程。其原理是通过递归实现的,对于当前节点,如果它为空节点,直接返回0;否则返回左子树节点个数加上右子树节点个数再加上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);
}

其中,root表示当前节点,如果当前节点为空,直接返回0;否则递归计算左子树节点个数和右子树节点个数,最终返回左子树节点个数加上右子树节点个数再加上1(当前节点),即整棵二叉树的节点个数。递归过程会一直向下遍历二叉树,直到叶子节点,然后逐层返回,并将每个节点的左右子树节点个数相加,最终得到整棵二叉树的节点个数。

5.二叉树第k层节点个数

这段代码实现了计算二叉树叶子节点个数的过程。其原理是通过递归实现的,对于当前节点,如果它为空节点,直接返回0;如果它是叶子节点,返回1;否则返回左子树叶子节点个数加上右子树叶子节点个数。具体实现如下:

//二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
	if (root==NULL)
		//如果当前节点为空,返回0
		return 0;
	if (k == 1)
		//如果当前节点是第k层节点,返回1
		return 1;
	// 返回左子树第 k-1 层节点个数加上右子树第 k-1 层节点个数
	int leftk = BinaryTreeLevelKSize(root->_left, k - 1);
	int rightk = BinaryTreeLevelKSize(root->_right, k - 1);
	return leftk + rightk;
}

其中,root表示当前节点,如果当前节点为空,直接返回0;如果当前节点是叶子节点,返回1;否则递归计算左子树叶子节点个数和右子树叶子节点个数,最终返回左子树叶子节点个数加上右子树叶子节点个数,即整棵二叉树的叶子节点个数。递归过程会一直向下遍历二叉树,直到叶子节点,然后逐层返回,并将每个节点的左右子树叶子节点个数相加,最终得到整棵二叉树的叶子节点个数。

6.二叉树查找值为x的节点

这段代码实现了在二叉树中查找值为x的节点的过程。其原理是通过递归实现的,对于当前节点,如果它为空节点,返回NULL;如果它的值等于x,返回指向当前节点的指针;否则在左子树中查找x,如果找到了,返回指向左子树中x的节点的指针;否则在右子树中查找x,如果找到了,返回指向右子树中x的节点的指针;如果左右子树都没有找到,返回NULL。具体实现如下:

// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
		//如果当前节点为空,返回NULL
		return 0;
	if (root->_data == x)
		//如果当前节点的值等于x,返回指向当前节点的指针
		return root;
	//在左子树中查找x
	BTNode* lret = BinaryTreeFind(root->_left, x);
	// 如果在左子树中找到了 x,返回指向左子树中 x 的节点的指针
	if (lret)
	{
		return lret;
	}
	//在右子树中查找x
	BTNode* rret = BinaryTreeFind(root->_right, x);
	// 如果在右子树中找到了 x,返回指向右子树中 x 的节点的指针
	if (rret)
	{
		return rret;
	}
	//否则,返回NULL
	return NULL;
}

其中,root表示当前节点,x表示要查找的值。如果当前节点为空,返回NULL;如果当前节点的值等于x,返回指向当前节点的指针;否则在左子树中查找x,如果找到了,返回指向左子树中x的节点的指针;否则在右子树中查找x,如果找到了,返回指向右子树中x的节点的指针;如果左右子树都没有找到,返回NULL。递归过程会一直向下遍历二叉树,直到找到值为x的节点或者遍历到叶子节点,然后逐层返回,找到值为x的节点或者返回NULL。

7.二叉树前序遍历

前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树。
这段代码实现了二叉树的先序遍历过程。其原理是通过递归实现的,对于当前节点,如果它为空节点,直接返回;否则打印当前节点的值,并递归遍历左子树和右子树。具体实现如下:

// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root)
{
	if (root == NULL)
	{
		//如果当前节点为空,直接返回
		return;
	}
	// 打印当前节点的值,并递归打印左子树和右子树
	printf("%c ", root->_data);
	BinaryTreePrevOrder(root->_left);
	BinaryTreePrevOrder(root->_right);
}

其中,root表示当前节点。如果当前节点为空,直接返回;否则先打印当前节点的值,然后递归遍历左子树和右子树。递归过程会一直向下遍历二叉树,直到遍历到叶子节点,然后逐层返回,逐个打印节点的值,最终得到整棵二叉树的先序遍历序列。

8.二叉树中序遍历

中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树。若二叉树为空则结束返回,否则:
(1)中序遍历左子树
(2)访问根结点
(3)中序遍历右子树

这段代码实现了二叉树的中序遍历过程。其原理是通过递归实现的,对于当前节点,如果它为空节点,直接返回;否则先递归遍历左子树,打印当前节点的值,再递归遍历右子树。具体实现如下:

// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
	if (root == NULL)
	{
		// 如果当前节点为空,直接返回
		return;
	}
	// 递归打印左子树,打印当前节点的值,再递归打印右子树	
	BinaryTreePrevOrder(root->_left);
	printf("%c ", root->_data);
	BinaryTreePrevOrder(root->_right);
}

其中,root表示当前节点。如果当前节点为空,直接返回;否则先递归遍历左子树,打印当前节点的值,再递归遍历右子树。递归过程会一直向下遍历二叉树,直到遍历到叶子节点,然后逐层返回,逐个打印节点的值,最终得到整棵二叉树的中序遍历序列。

9.二叉树后序遍历

后序遍历首先遍历左子树,然后遍历右子树,最后访问根结点,在遍历左、右子树时,仍然先遍历左子树,然后遍历右子树,最后遍历根结点。即:
若二叉树为空则结束返回,
否则:
(1)后序遍历左子树
(2)后序遍历右子树
(3)访问根结点

这段代码实现了二叉树的后序遍历过程。其原理是通过递归实现的,对于当前节点,如果它为空节点,直接返回;否则先递归遍历左子树和右子树,再打印当前节点的值。具体实现如下:

// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
	if (root == NULL)
	{
		// 如果当前节点为空,直接返回
		return;
	}
	// 递归打印左子树和右子树,再打印当前节点的值
	BinaryTreePrevOrder(root->_left);
	BinaryTreePrevOrder(root->_right);
	printf("%c ", root->_data);
}

其中,root表示当前节点。如果当前节点为空,直接返回;否则先递归遍历左子树和右子树,再打印当前节点的值。递归过程会一直向下遍历二叉树,直到遍历到叶子节点,然后逐层返回,最终得到整棵二叉树的后序遍历序列。

10.层序遍历

这段代码实现了二叉树的层序遍历过程。其原理是通过队列实现的,先将根节点入队,然后循环从队列中取出节点并打印节点的值,如果节点有左子节点,就将左子节点入队,如果节点有右子节点,就将右子节点入队,直到队列为空为止。具体实现如下:

// 层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
	if (root == nullptr) {
		return;
	}

	std::queue<BTNode*> q;
	q.push(root);

	while (!q.empty()) {
		BTNode* node = q.front();
		q.pop();

		std::cout << node->_data << " ";

		if (node->_left != nullptr) {
			q.push(node->_left);
		}

		if (node->_right != nullptr) {
			q.push(node->_right);
		}
	}
}

其中,root表示根节点。首先将根节点入队,然后循环从队列中取出节点并打印节点的值,如果节点有左子节点,就将左子节点入队,如果节点有右子节点,就将右子节点入队,直到队列为空为止。这个过程会按照层序遍历的顺序依次遍历二叉树的每一层节点,从而得到整棵二叉树的层序遍历序列。

11.判断二叉树是否是完全二叉树

这段代码实现了判断二叉树是否为完全二叉树的过程。其原理是通过层序遍历和队列实现的,在层序遍历的过程中判断每个节点是否有左右子树,如果有就将它们入队,如果没有就将一个标志位设为1,表示之后遍历到的节点必须都是叶子节点,否则该树就不是完全二叉树。如果遍历到了一个节点,发现它的左子树或右子树为空,且之前已经出现过空子树,则该树就不是完全二叉树。如果遍历到队列中所有节点,均无右子树,则该树是完全二叉树。具体实现如下:

// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root) {
	if (root == NULL) {
		// 空树是完全二叉树
		return 1;
	}

	BTNode* queue[1000];
	int front = 0, rear = 0;
	queue[rear++] = root;

	int flag = 0; // 是否出现过空子树的标志

	while (front < rear) {
		BTNode* node = queue[front++];

		if (node->_left != NULL) {
			// 如果之前出现过空子树,则该树不是完全二叉树
			if (flag) {
				return 0;
			}
			queue[rear++] = node->_left;
		}
		else {
			flag = 1;
		}

		if (node->_right != NULL) {
			// 如果之前出现过空子树,则该树不是完全二叉树
			if (flag) {
				return 0;
			}
			queue[rear++] = node->_right;
		}
		else {
			flag = 1;
		}
	}

	// 如果队列中所有节点均无右孩子,则该树是完全二叉树
	return 1;
}

其中,root表示根节点。首先判断根节点是否为空,如果是,则空树是完全二叉树,直接返回1。然后定义一个队列,将根节点入队,并定义一个标志位flag表示是否出现过空子树。接下来,在队列不为空的情况下,从队列中取出一个节点,判断该节点的左右子树是否为空,如果有子树,则将子树入队;如果子树为空,则将标志位flag设为1表示之后遍历到的节点必须都是叶子节点。如果遍历到了一个节点,发现它的左子树或右子树为空,且之前已经出现过空子树,则该树就不是完全二叉树,直接返回0。如果遍历到队列中所有节点,均无右子树,则该树是完全二叉树,返回1。这个过程可以判断二叉树是否为完全二叉树。

12.完整代码

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string.h>
#include<assert.h>
#include<stdio.h>
#include<limits.h>
#include<stdbool.h>
#include<queue>
using namespace std;
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);

// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi)
{
	//如果数组已经遍历完或者当前节点是空节点,返回空指针
	if (*pi >= n || a[*pi] == '#')
	{
		//当前节点为空,返回NULL
		(*pi)++;
		return NULL;
	}
	//创建新节点并赋初值
	BTNode* root = new BTNode;
	root->_data = a[*pi];
	root->_left = NULL;
	root->_right = NULL;
	//递归构建左子树和右子树
	(*pi)++;
	root->_left = BinaryTreeCreate(a, n, pi);
	(*pi)++;
	root->_right = BinaryTreeCreate(a, n, pi);
	return root;
}
// 二叉树销毁
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)
		//如果当前节点为空返回0
		return 0;
	//返回左子树节点个数加上右节点个数再加上1(当前节点)
	return BinaryTreeSize(root->_left) +
		BinaryTreeSize(root->_right) + 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)
{
	if (root==NULL)
		//如果当前节点为空,返回0
		return 0;
	if (k == 1)
		//如果当前节点是第k层节点,返回1
		return 1;
	// 返回左子树第 k-1 层节点个数加上右子树第 k-1 层节点个数
	int leftk = BinaryTreeLevelKSize(root->_left, k - 1);
	int rightk = BinaryTreeLevelKSize(root->_right, k - 1);
	return leftk + rightk;
}

// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
		//如果当前节点为空,返回NULL
		return 0;
	if (root->_data == x)
		//如果当前节点的值等于x,返回指向当前节点的指针
		return root;
	//在左子树中查找x
	BTNode* lret = BinaryTreeFind(root->_left, x);
	// 如果在左子树中找到了 x,返回指向左子树中 x 的节点的指针
	if (lret)
	{
		return lret;
	}
	//在右子树中查找x
	BTNode* rret = BinaryTreeFind(root->_right, x);
	// 如果在右子树中找到了 x,返回指向右子树中 x 的节点的指针
	if (rret)
	{
		return rret;
	}
	//否则,返回NULL
	return NULL;
}

// 二叉树前序遍历 
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;
	}
	// 递归打印左子树,打印当前节点的值,再递归打印右子树	
	BinaryTreePrevOrder(root->_left);
	printf("%c ", root->_data);
	BinaryTreePrevOrder(root->_right);
}

// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
	if (root == NULL)
	{
		// 如果当前节点为空,直接返回
		return;
	}
	// 递归打印左子树和右子树,再打印当前节点的值
	BinaryTreePrevOrder(root->_left);
	BinaryTreePrevOrder(root->_right);
	printf("%c ", root->_data);
}

// 层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
	if (root == nullptr) {
		return;
	}

	std::queue<BTNode*> q;
	q.push(root);

	while (!q.empty()) {
		BTNode* node = q.front();
		q.pop();

		std::cout << node->_data << " ";

		if (node->_left != nullptr) {
			q.push(node->_left);
		}

		if (node->_right != nullptr) {
			q.push(node->_right);
		}
	}

}

// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root) {
	if (root == NULL) {
		// 空树是完全二叉树
		return 1;
	}

	BTNode* queue[1000];
	int front = 0, rear = 0;
	queue[rear++] = root;

	int flag = 0; // 是否出现过空子树的标志

	while (front < rear) {
		BTNode* node = queue[front++];

		if (node->_left != NULL) {
			// 如果之前出现过空子树,则该树不是完全二叉树
			if (flag) {
				return 0;
			}
			queue[rear++] = node->_left;
		}
		else {
			flag = 1;
		}

		if (node->_right != NULL) {
			// 如果之前出现过空子树,则该树不是完全二叉树
			if (flag) {
				return 0;
			}
			queue[rear++] = node->_right;
		}
		else {
			flag = 1;
		}
	}

	// 如果队列中所有节点均无右孩子,则该树是完全二叉树
	return 1;
}
int main()
{
	BTDataType a[] = { 'A', 'B', 'D', '#', '#', 'E', '#', 'H', '#', '#', 'C', 'F', '#', '#', 'G', '#', '#' };
	int n = sizeof(a) / sizeof(a[0]);
	int i = 0;
	BTNode* root = BinaryTreeCreate(a, n, &i);
	//cout << root << endl;
	/*cout <<"BinaryTreeSize:" << BinaryTreeSize(root) << endl;
	cout << "BinaryTreeLeafSize:" << BinaryTreeLeafSize(root) << endl;
	cout <<"BinaryTreeLevelKSize:" << BinaryTreeLevelKSize(root, 1) << endl;
	cout << "BinaryTreeFind:" << BinaryTreeFind(root, 'A') << endl;*/
	 //BinaryTreePrevOrder(root);
	//BinaryTreeInOrder(root);
	//BinaryTreePostOrder(root);
	//BinaryTreeLevelOrder(root);
	//cout<<BinaryTreeComplete(root) << endl;
	//cout << BinaryTreeComplete(root) << endl;
}

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

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

相关文章

【实验七】界面化和事件处理

1、完成书上239页实验题目1和题目2 题目1 package chap10.test; //awt是一个软件包&#xff0c;包含用于创建用户界面和绘制图形图像的所有分类。 import java.awt.BorderLayout;//边界管理器import java.awt.Color; import java.awt.FlowLayout;//流布局一般用来安排面板中的…

Django_自定义文件存储类并将图片上传到FastDFS

目录 将图片到FastDFS和浏览的流程图 使用自定义文件存储类 1、定义存储类 2、创建FastDFS的配置文件 3、修改settings.py配置 4、上传图片进行验证 4.1 定义一个包含ImageField字段的模型类 4.2 登录django的admin后台 4.3 上传图片 4.4 查看图片 源码等资料获取方…

What Is the Character Limit for ChatGPT? 聊天GPT的字符限制是多少?

The character limit for ChatGPT text prompts is 4096 characters, and there’s also a limit of 4096 tokens per conversation. If you aren’t sure how many tokens your prompt uses, you can calculate that with OpenAI’s Tokenizer tool. ChatGPT 文本提示的字符限…

AutoHand第三人称的AutoHandVRIK开启和关闭

第三人称结构 第三人称在AutoHandVRIK脚本初始化完毕后&#xff0c;会出把两只手提到玩家对象根部对象上&#xff0c;并且在原始的模型手的位置创建了新的对象&#xff08;leftHandFollowTarget&#xff0c;rightHandFollowTarget&#xff09;&#xff0c;副VRIK大概用途就是I…

从字母百分比看字符串处理的奥妙

本篇博客会讲解力扣“2278. 字母在字符串中的百分比”的解题思路&#xff0c;这是题目链接。 本题的思路是&#xff0c;统计字符letter在字符串s中出现的次数cnt&#xff0c;以及字符串s的长度n&#xff0c;其中n也可以使用strlen来求。最终要求计算的百分比是cnt*100/n。 int…

性能测试工具LoadRunne函数如何使用详解(上)

性能测试工具LoadRunner是软件测试行业主流测试工具&#xff0c;也是软件测试实验室在申请CNAS/CMA资质、测试质量体系建设一定会用到的一款软件测试工具。LoadRunner的函数是是组成测试脚本的最小单元&#xff0c;它真实模拟 一个个请求操作&#xff0c;并接收返回结果。学习L…

王道考研数据结构——顺序表

08 线性表的基本概念 对参数的修改结果需要“带回来”就使用引用类型的参数 顺序表的定义&#xff1a; 顺序存储、链式存储 sizeof(int)、sizeof(MyStruct) 顺序表的扩展 虽然大小改变&#xff0c;但是时间开销大 让代码健壮&#xff1a;对数据操作的合法性进行检查&#xf…

How to Write and Publish a Scientific Paper-How to Prepare Effective Graphs

How to Prepare Effective Graphs WHEN NOT TO USE GRAPHS 在上一章中&#xff0c;我们讨论了某些不应该制成表格的数据类型。它们也不应该被转换成图表。基本上&#xff0c;图表都是图形表格。 要点是这样的。某些类型的数据&#xff0c;特别是稀疏类型或单调重复的类型&am…

细节决定成败,聊聊JS的类型(下)

讲完了基本类型&#xff0c;我们来介绍一个现象&#xff1a;类型转换。 因为 JS 是弱类型语言&#xff0c;所以类型转换发生非常频繁&#xff0c;大部分我们熟悉的运算都会先进行类型转换。大部分类型转换符合人类的直觉&#xff0c;但是如果我们不去理解类型转换的严格定义&a…

牛客练习赛113

A小红的基环树 题目描述 定义基环树为n个节点、n条边的、没有自环和重边的无向连通图。 定义一个图的直径是任意两点最短路的最大值。 小红想知道&#xff0c;n个节点构成的所有基环树中&#xff0c;最小的直径是多少&#xff1f; 思路分析 特判n3时为1&#xff0c;其他时候都…

行业追踪,2023-07-11,新增加 rps50 排名,汽车零部件回落 10 日均线,直接反弹

自动复盘 2023-07-11 成交额超过 100 亿 排名靠前&#xff0c;macd柱由绿转红 成交量要大于均线 有必要给每个行业加一个上级的归类&#xff0c;这样更能体现主流方向 rps 有时候比较滞后&#xff0c;但不少是欲杨先抑&#xff0c; 应该持续跟踪&#xff0c;等 macd 反转时参与…

Stable Diffusion - 提示词翻译插件 sd-webui-prompt-all-in-one

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/131649921 sd-webui-prompt-all-in-one 是一个基于 stable-diffusion-webui 的扩展&#xff0c;目的是提高 提示词/反向提示词 输入框的使用体验&…

汽车应用级MS35774/MS35774A低噪声 256 细分微步进电机驱动

MS35774/MS35774A 是一款高精度、低噪声的两相步进 电机驱动芯片&#xff0c;芯片内置功率MOSFET &#xff0c;长时间工作的平均电 流可以达到 1.4A &#xff0c;峰值电流 2A 。芯片集成了过温保护、欠压 保护、过流保护、短地保护、短电源保护功能。 主要特点 ◼ 2 相步进…

【python】Excel文件的插入操作

上篇文章写了pandas读取Excel文件的操作&#xff0c;但实际应用中&#xff0c;我们还需要对Excel指定单元格进行写入操作。 pandas模块写入 pandas模块方法写入&#xff0c;简单粗暴&#xff0c;就是把整个Excel文件重写 import pandas as pdfile_path 测试用例.xlsx # 读取Ex…

【Java基础】符号位、原码、补码、反码、位逻辑运算符、位移运算符、复合位赋值运算符

文章目录 前言&#xff1a;符号位、原码、补码、反码1.是什么2.各种码转换 一.二进制高低位1.1.什么是高低位1.2.高低位交换 二.位逻辑运算符位与运算 &位或运算 |异或运算 ^取反运算 ~ 三.位移运算符左位移运算符 <<右位移运算符 >>1.正数右移&#xff1a;2.负…

什么是QPS,什么是RT

&#x1f3c6;今日学习目标&#xff1a; &#x1f340;什么是QPS&#xff0c;什么是RT ✅创作者&#xff1a;林在闪闪发光 ⏰预计时间&#xff1a;30分钟 &#x1f389;个人主页&#xff1a;林在闪闪发光的个人主页 &#x1f341;林在闪闪发光的个人社区&#xff0c;欢迎你的加…

生产慢查询问题分析

1.问题描述 7月1日零点set_24出现大量慢查询告警&#xff0c;经DBA定位为子系统涉及的一条查询语句出现慢查询&#xff0c;引起set_24的cpu使用率突增&#xff0c;触发大量告警&#xff0c;查看生产执行计划发现慢查询为索引跳变引起&#xff1b;具体出现问题的sql语句如下&am…

【裸机开发】I2C 通信接口(三)—— I2C 底层驱动接口实现

目录 一、I2C 初始化 二、产生开始 / 停止信号 1、开始信号 2、重复开始信号 3、停止信号 三、向总线上发送数据&#xff08;阻塞模式&#xff09; 四、从总线上读取数据&#xff08;阻塞模式&#xff09; 五、整合&#xff1a;数据读写统一调用接口 一、I2C 初始化 初…

springboot驾校管理系统

框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.3.9 …

springboot+dynamic-datasource实现多数据源动态切换,非@DS注解方式

springbootdynamic-datasource实现多数据源动态切换&#xff0c;非注解 一、前言二、方案思路三、代码实现 一、前言 最近在分析SaaS平台多租户的功能&#xff0c;必然涉及数据库部分的功能&#xff0c;多租户的设计方案要考虑租户隔离数据和租户共享数据&#xff0c;共享数据…