数据结构——【万字文章+配图+代码】带你深入理解二叉树

news2024/12/23 13:49:04

1. 二叉树的概念

二叉树是一种有限集合,由根和左右子树构成,每个结点最多有两棵子树,且这两棵子树具有顺序关系
请添加图片描述

2. 二叉树的特殊情况:

2.1 满二叉树:

一个二叉树,如果每次的结点都达到最大值,那么这个数就是满二叉树。如果一个二叉树有k层,且结点的总个数为2^k^-1,则它就是一个满二叉树

请添加图片描述

2.2 完全二叉树:

如果设二叉树的深度为h,那么除了第h层外,其它各层 (即1~h-1层) 的结点数都达到最大个数;同时,第h层所有的结点都连续集中在最左边。满二叉树是一种特殊的完全二叉树。

请添加图片描述

3. 二叉树的性质:

  1. 若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2(i-1)个结点。(第一层1个,第二层2个,第三层4个,第四层8个……)请添加图片描述

  2. 若规定根节点的层数为1,则深度为h的二叉树的最大结点数是2h-1请添加图片描述

  3. 对任何一颗二叉树,如果度为0其叶结点个数为n0,度为2的分支结点个数为n2,则有n0=n2+1

  4. 若规定根节点的层数为1,具有n个结点的满二叉树的深度为h=log2(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否则无右子树

4. 二叉树的存储结构

4.1 顺序结构

二叉树顺序存储在物理上是一个数组,在逻辑上是一棵二叉树

请添加图片描述

4.2 链式结构

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

请添加图片描述

5. 二叉树的实现

5.1 二叉树的创建

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

5.2 二叉树的销毁

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

5.3 二叉树节点个数

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

5.4 二叉树叶子节点个数

//二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root)
{
	if (root == nullptr)
	{
		//如果当前节点为空,返回0
		return 0;
	}
	if (root->_left == nullptr && root->_right == nullptr)
	{
		//如果当前节点是叶子节点,返回1
		return 1;
	}
	//返回左子树叶子节点个数+右子树叶子节点个数
	return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}

5.5 二叉树第k层节点个数

int BinaryTreeLevelKSize(BTNode* root, int k)
{
	if (root == nullptr)
	{
		//如果当前节点为空,返回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;
}

5.6 二叉树查找值为x的节点

//二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	if (root == nullptr)
	{
		//如果当前节点为空,返回nullptr
	}
	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;
	//否则返回nullptr
	return nullptr;
}

5.7 二叉树的前序遍历

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

5.8 二叉树的中序遍历

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

5.9 二叉树的后序遍历

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

5.10 二叉树的层序遍历

//二叉树的层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
	if (root == nullptr)//如果根节点为空,直接返回
	{
		return;
	}
	queue<BTNode*> q;//创建一个队列,用于存储待访问的节点
	q.push(root);//将根节点入队
	while (!q.empty())//当队列不为空时执行循环
	{
		BTNode* node = q.front();//取出队列前面的节点
		q.pop();//将该节点出队
		cout << node->_data <<" ";//输出节点数据
		if (node->_left != nullptr)//如果左子节点不为空,将其入队
		{
			q.push(node->_left);
		}
		if (node->_right != nullptr)//如果右子节点不为空,将其入队
		{
			q.push(node->_right);
		}
	}
}

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

//判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root)
{
	if (root == nullptr) //如果根节点为空,则空树是完全二叉树
	{
		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 != nullptr)//如果左子树不为空
		{
			//如果之前出现过空子树,则该树不是完全二叉树
			if (flag)//如果之前出现过空子树,则该数不是完全二叉树
			{
				return 0;
			}
			queue[rear++] = node->_left;//将左子节点入栈
		}
		else//如果左子树为空
		{
			flag = 1;//标记存在空子树
		}
		if (node->_right != nullptr)//如果右子节点不为空
		{
			//如果之前出现过空子树,则该树不是完全二叉树
			if (flag)
			{
				return 0;
			}
			queue[rear++] = node->_right;//将右子节点入队
		}
		else//如果右子节点为空
		{
			flag = 1;//标记存在空子树
		}
	}
	//如果队列中所有节点均无左右孩子,则该树是完全二叉树
	return 1;
}

5.12 二叉树完整代码

#include<stdlib.h>
#include<iostream>
#include<queue>
using namespace std;
typedef int 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)
{
	//如果数组已经遍历完或者当前节点的是空姐发,则返回空指针
	if (*pi >= n || a[*pi] == '#')
	{
		//当前节点为空,返回NULL
		(*pi)++;
		return nullptr;
	}
	//创建新节点并赋初值
	BTNode* root = new BTNode;
	root->_data = a[*pi];
	root->_left = nullptr;
	root->_right = nullptr;
	(*pi)++;
	root->_left = BinaryTreeCreate(a, n, pi);
	root->_right = BinaryTreeCreate(a, n, pi);
	return root;
}

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

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

//二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root)
{
	if (root == nullptr)
	{
		//如果当前节点为空,返回0
		return 0;
	}
	if (root->_left == nullptr && root->_right == nullptr)
	{
		//如果当前节点是叶子节点,返回1
		return 1;
	}
	//返回左子树叶子节点个数+右子树叶子节点个数
	return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}

//二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
	if (root == nullptr)
	{
		//如果当前节点为空,返回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 == nullptr)
	{
		//如果当前节点为空,返回nullptr
	}
	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;
	//否则返回nullptr
	return nullptr;
}

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

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

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

//二叉树的层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
	if (root == nullptr)//如果根节点为空,直接返回
	{
		return;
	}
	queue<BTNode*> q;//创建一个队列,用于存储待访问的节点
	q.push(root);//将根节点入队
	while (!q.empty())//当队列不为空时执行循环
	{
		BTNode* node = q.front();//取出队列前面的节点
		q.pop();//将该节点出队
		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 == nullptr) //如果根节点为空,则空树是完全二叉树
	{
		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 != nullptr)//如果左子树不为空
		{
			//如果之前出现过空子树,则该树不是完全二叉树
			if (flag)//如果之前出现过空子树,则该数不是完全二叉树
			{
				return 0;
			}
			queue[rear++] = node->_left;//将左子节点入栈
		}
		else//如果左子树为空
		{
			flag = 1;//标记存在空子树
		}
		if (node->_right != nullptr)//如果右子节点不为空
		{
			//如果之前出现过空子树,则该树不是完全二叉树
			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<<"二叉树节点个数:" << BinaryTreeSize(root) << endl;
	cout << "二叉树叶子节点的个数:" << BinaryTreeLeafSize(root) << endl;
	cout << "二叉树第1层节点个数:"<<BinaryTreeLevelKSize(root,1)<<endl;
	cout << "二叉树第2层节点个数:" << BinaryTreeLevelKSize(root, 2) << endl;
	cout << "二叉树第3层节点个数:" << BinaryTreeLevelKSize(root, 3) << endl;
	cout << "二叉树查找值为x的节点:"<<BinaryTreeFind(root,'A') << endl;
	cout << "二叉树的前序遍历:";
	BinaryTreePrevOrder(root);
	cout << endl;
	cout << "二叉树的中序遍历:";
	BinaryTreeInOrder(root);
	cout << endl;
	cout << "二叉树的后序遍历:";
	BinaryTreePostOrder(root);
	cout << endl;
	cout << "二叉树的层序遍历:";
	BinaryTreeLevelOrder(root);
	cout << endl;
	if (BinaryTreeComplete(root) == 1)
	{
		cout << "完全二叉是树" << endl;
	}
	else
	{
		cout << "不是完全二叉树" << endl;
	}
	return 0;
}

6. 二叉搜索树

6.1 二叉搜索树概念

二叉搜索搜又称二叉排序树,它或者是一颗空树

  1. 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值

  2. 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值

  3. 它的左右子树也分别为二叉搜索树

6.2 二叉搜索树的查找

  1. 从根开始比较,查找,比根大的往右边走查找,比根小则往左走查找
  2. 最多查找高度次,走到空,还没找到,这个值不存在

6.3 二叉搜索树的插入

  1. 树为空,则直接新增节点,赋值给root指针

  2. 树不空,按二叉搜索树性质查找插入位置,插入新节点

6.4 二叉搜索树的删除

首先查找元素是否在二叉树中,如果不存在,则返回,否则要删除的结点可能分下面四种情况

  1. 要删除的结点无孩子结点
  2. 要删除的结点只有左孩子结点
  3. 要删除的结点只有右孩子结点
  4. 要删除的结点有左、右孩子结点

看起来有待删除结点有4种情况,实际情况1可以与情况2或者3合起来,因此真正的删除过程如下:

情况2:删除该结点且使被删除结点的双亲结点指向被删除节点的左孩子结点——直接删除

情况3:删除该结点且使被删除结点的双亲结点指向被删除结点的右孩子结点——直接删除

情况4:在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除结点中,再来处理该结点的删除问题——替换法删除

6.5 二叉搜索树的实现

#include <iostream>
using namespace std;

struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

class BST {
public:
    TreeNode* insert(TreeNode* root, int val) {
        if (root == NULL) {
            return new TreeNode(val);
        }
        if (val < root->val) {
            root->left = insert(root->left, val);
        }
        else if (val > root->val) {
            root->right = insert(root->right, val);
        }
        return root;
    }

    void inorderTraversal(TreeNode* root) {
        if (root == NULL) {
            return;
        }
        inorderTraversal(root->left);
        cout << root->val << " ";
        inorderTraversal(root->right);
    }
};

int main() {
    BST bst;
    TreeNode* root = NULL;
    root = bst.insert(root, 5);
    root = bst.insert(root, 3);
    root = bst.insert(root, 7);
    root = bst.insert(root, 2);
    root = bst.insert(root, 4);
    root = bst.insert(root, 6);
    root = bst.insert(root, 8);

    cout << "中序遍历二叉搜索树:";
    bst.inorderTraversal(root);
    cout << endl;

    return 0;
}

6.6 二叉搜索树的应用

  1. K模型:K模型即只有key作为关键码,结构中只需要存储key即可,关键码即为需要搜索到的值

  2. KV模型:每一个关键码key,都有与之对应的值Value,即<Key,Value>的键值对,比如:英汉词典、统计单词次数

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

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

相关文章

07-Eventing及实践

1 Knative Eventing的相关组件 Knative Eventing具有四个最基本的组件&#xff1a;Sources、Brokers、Triggers 和 Sinks 事件会从Source发送至SinkSink是能够接收传入的事件可寻址&#xff08;Addressable&#xff09;或可调用&#xff08;Callable&#xff09;资源 Knative S…

二维码智慧门牌管理系统升级解决方案:房屋管理

文章目录 前言一、一站式服务二、全方位管理三、未来展望四、智慧解决方案 前言 科技带来智慧生活 随着科技的不断发展&#xff0c;智能化已经成为我们生活的重要组成部分。二维码智慧门牌管理系统是这一趋势中的关键工具之一。除了提供标准地址服务外&#xff0c;该系统还为房…

全栈开发中的安全注意事项:最佳实践和工具

安全性是当今数字环境中最重要的问题&#xff0c;而在全栈开发中这一点尤为重要。当企业努力创建强大且动态的应用程序时&#xff0c;他们必须应对复杂的安全威胁领域。在本文中&#xff0c;我们将探讨开发人员可以用来确保安全的全栈开发环境的最佳实践和工具。 1.1 全栈开发的…

电脑软件:推荐一款非常实用的屏幕截图软件

目录 一、功能介绍 二、软件特色 三、常用快捷键 四、软件总结 五、软件下载 FastStone Capture是一款功能强大的屏幕截图软件&#xff0c;它可以帮助用户轻松地捕获屏幕上的任何区域&#xff0c;并将其保存为各种格式的图像文件。以下是关于FastStone Capture软件的一些详…

小信砍柴的题解

目录 原题描述&#xff1a; 时间&#xff1a;1s 空间&#xff1a;256M 题目描述&#xff1a; 输入格式&#xff1a; 输出格式&#xff1a; 样例1输入&#xff1a; 题目大意&#xff1a; 主要思路&#xff1a; 注意事项&#xff1a; 总代码&#xff1a; 原题描述&#…

59. 螺旋矩阵 II(java实现,史上最详细教程,想学会的进!!!)

今天来分享一下螺旋矩阵的解题思路及代码的实现。 题目描述如下&#xff1a; 首先拿到这道题&#xff0c;首先不要慌张&#xff0c;我们来仔细分析一下会发现并没有那么难。 首先看下边界的元素是1、2、3递增的&#xff0c;那么我们也许可以根据这一点先把边界的元素一个一个给…

上下界取min/max的线段树问题:P8518 [IOI2021] 分糖果

https://www.luogu.com.cn/problem/P8518 没有要求在线&#xff0c;显然离线&#xff08;。维护时间戳&#xff0c;上线段树。 好了&#xff0c;我们现在知道一个人的曲线变化了。怎么做呢&#xff1f; 前面所有碰上下界的都是没用的&#xff01;我们只需要找最后一段的时间…

TrustZone之顶层软件架构

在处理器中的TrustZone和系统架构中,我们探讨了硬件中的TrustZone支持,包括Arm处理器和更广泛的内存系统。本主题关注TrustZone系统中发现的软件架构。 一、顶层软件架构 下图显示了启用TrustZone的系统的典型软件栈: 【注意】:为简单起见,该图不包括管理程序,尽管它们可…

【C语言】鹏哥C语言刷题训练营——第5节内容笔记(含代码全面分析和改进,讲解)

系列文章目录 身躯已然冰封&#xff0c;灵魂仍旧火热 本文由睡觉待开机原创&#xff0c;未经允许不得转载。 本内容在csdn网站首发 欢迎各位点赞—评论—收藏 如果存在不足之处请评论留言&#xff0c;共同进步&#xff01; 文章目录 系列文章目录前言题目链接&#xff08;有需要…

计算机组成原理——数制与编码

1.在以下编码中&#xff0c;零的表示唯一的是&#xff08;C&#xff09; A.反码 B.原码 C.补码 D.原码和移码 2.假设某数的真值为-100 1010B&#xff0c;在计算机内部表示为1011 0110B&#xff0c;该数采用的编码为&#xff08;D&#xff09; A.移码 B.原码 C.反码 D.补码 3.…

Linux shell编程学习笔记36:read命令

目录 0 前言1 read命令的功能、格式、返回值和注意 1.1 命令功能1.2 命令格式1.3 返回值1.4 注意事项2 命令应用实例 2.1 一次读入多个变量值2.2 不指定变量名2.3 测试read命令的返回值2.3 指定输入时限并进行相应处理2.4 -t 指定结束符2.5 -n 指定输入字符个数2.6 -N 指定输入…

分类预测 | Matlab实现AOA-SVM算术优化支持向量机的数据分类预测【23年新算法】

分类预测 | Matlab实现AOA-SVM算术优化支持向量机的数据分类预测【23年新算法】 目录 分类预测 | Matlab实现AOA-SVM算术优化支持向量机的数据分类预测【23年新算法】分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现AOA-SVM算术优化支持向量机的数据分类预测…

css的filter全属性介绍

原图&#xff1a; 模糊&#xff08;blur&#xff09; 单位可为px或rem&#xff0c;值越大&#xff0c;越模糊 filter:blur(3px) filter:blur(0.3rem) 亮度(brightness) 值可为数字或百分数&#xff0c;小于1时&#xff0c;亮度更暗&#xff1b;等于1时&#xff0c;无变化&am…

微信支付怎么申请0.2费率

作为移动支付的主流方式&#xff0c;微信收款和支付宝为商家带来了便利的同时&#xff0c;每笔交易都要收取的0.6&#xff05;收款手续费也成为商家的负担。现在使用现金支付的人少之又少&#xff0c;为了给顾客带来便捷的购物体验&#xff0c;所以即便是要付出手续费&#xff…

十四、YARN核心架构

1、目标 &#xff08;1&#xff09;掌握YARN的运行角色和角色之间的关系 &#xff08;2&#xff09;理解使用容器做资源分配和隔离 2、核心架构 &#xff08;1&#xff09;和HDFS架构的对比 HDFS架构&#xff1a; YARN架构&#xff1a;&#xff08;主从模式&#xff09; &…

visual stdio code运行vue3

npm init vuelatest 该命令初始化vue项目 使用visual stdio code创建vue项目 ,这边是vue-project文件夹 vs code打开项目 vscode操作vue项目 vscode操作vue项目

【Leetcode】旋转矩阵

题目链接&#xff1a;https://leetcode.cn/problems/rotate-matrix-lcci/description/ 题目描述 给你一幅由 N N 矩阵表示的图像&#xff0c;其中每个像素的大小为 4 字节。请你设计一种算法&#xff0c;将图像旋转 90 度。 不占用额外内存空间能否做到&#xff1f; 示例 …

找出一个二维数组中的鞍点

找出一个二维数组中的鞍点&#xff0c;即该位置上的元素在该行上的最大、在该列上最小。也有可能没有鞍点。 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> int main() {int a[10][10] { 0 };int n 0, m 0;int i 0, j 0;printf("请输入这个数组有n行m列…

算法学习——栈与队列

栈与队列 栈与队列理论基础用栈实现队列思路代码 用队列实现栈思路代码 删除字符串中的所有相邻重复项思路代码 有效的括号思路代码 逆波兰表达式求值思路代码 滑动窗口最大值思路代码未完待续 前 K 个高频元素思路代码拓展 总结栈在系统中的应用括号匹配问题字符串去重问题逆波…

FPGA时序分析与时序约束(二)——时钟约束

目录 一、时序约束的步骤 二、时序网表和路径 2.1 时序网表 2.2 时序路径 三、时序约束的方式 三、时钟约束 3.1 主时钟约束 3.2 虚拟时钟约束 3.3 衍生时钟约束 3.4 时钟组约束 3.5 时钟特性约束 3.6 时钟延时约束 一、时序约束的步骤 上一章了解了时序分析和约束…