【C++】模拟实现二叉搜索树(附源码、测试用例)

2023-11-12

二叉搜索树

一、前言

二、模拟实现

1.构建树的单个节点

2.二叉搜索树的概念

3.构造函数与析构函数

4.赋值与拷贝构造

5.实现插入

6.实现删除

7.实现查找

8.实现遍历

三、源码及部分测试用例


一、前言

        二叉搜索树,和普通的二叉树不同,它除了拥有链表的快速插入的功能,也拥有比肩数组般快速查找的能力。本文主要模拟实现二叉搜索树的增添、删除、查找以及遍历的功能,编译器环境为VS2019。

二、模拟实现

1.构建树的单个节点

        二叉搜索树的单个节点和普通二叉树一样,都是用结构体存储内容,同时使用左右指针指向左右子树,树只要保存最初的根节点即可:

// 树节点
// K表示数据存储类型,V表示对类容的进一步扩展
// 扩展可以是注释,也可以是其他内容
template<class K, class V>
struct BSTreeNode
{
	BSTreeNode<K, V>* left;
	BSTreeNode<K, V>* right;

	K _key;
	V _value;

	BSTreeNode(const K& key, const V& value)
		:left(nullptr)
		, right(nullptr)
		, _key(key)
		, _value(value)
	{}
};

// 搜索二叉树
template<class K, class V>
class BSTree
{
	typedef BSTreeNode<K, V> Node;
public:
private:
    Node* _root;
}

2.二叉搜索树的概念

二叉搜索树相比于普通二叉树有两点不同:

(1)二叉搜索树的所有根节点都比自己的左子树及其子树存储的值要大,同时比自己的右子树及其子树存储的值要小;

(2)二叉搜索树中不能存在相同的值节点。

3.构造函数与析构函数

        因为树初始的存储中只有一个根节点,构造函数中根节点给一个空即可;而二叉树的析构函数则要用到深度优先遍历——因为使用前序中序delete掉根节点后无法再访问到子树,就会造成严重数据泄露。

// 初始化
BSTree()
	:_root(nullptr)
{}

// 析构
~BSTree()
{
	Destory(_root);
}

void Destory(Node*& del)
{
	if (del == nullptr)
		return;

	Destory(del->left);
	Destory(del->right);

	delete del;
	del = nullptr;
}

4.赋值与拷贝构造

        给二叉树的赋值类似于拷贝构造,倒不如说一模一样,赋值和拷贝构造都是给new出来一串一样的树。

        不过有两种实现方法:一种是传统写法,构建一个Copy函数,传入*this指向的树和参数引用的树,通过广度优先遍历一一拷贝过去;另一种则简单粗暴,传入的参数为实参拷贝构造后的树,直接交换*this的根节点和构造的树即可,函数结束时栈帧销毁同时形参自动调用析构函数,而此时的形参是交换后的*this指向的树根节点,不用管即可,当然,这只适用于赋值,因为要调用拷贝构造函数。

        具体实现如下:

// 拷贝构造
BSTree(const BSTree<K, V>& t)
{
	_root = Copy(t._root);
}

// 赋值
BSTree<K, V>& operator=(BSTree<K, V> t)
{
	swap(_root, t._root);
	return *this;
}

5.实现插入

        首先来分析一下,二叉搜索树的要求,要求其左子树比根节点小,右子树比根节点大——因此,每一次比较都是一次大小的筛选——比较大小后选择进入比根节点更小的左树,或进入更大的右树,这也是在不断缩小范围,直到不可缩小大小范围为止,此时是不能继续比较之时,即比较根节点后进入的子树为空之时,插入空节点即可。

// 插入
bool Insert(const K& key, const V& value)
{
	// 排除空
	if (_root == nullptr)
	{
		Node* New = new Node(key, value);
		_root = New;

		return true;
	}

	// 往下查找
	Node* parent = nullptr;
	Node* cur = _root;
	while (cur)
	{
		if (key > cur->_key)
		{
			parent = cur;
			cur = cur->right;
		}
		else if (key < cur->_key)
		{
			parent = cur;
			cur = cur->left;
		}
		else
			return false;
	}

	// 放置新节点
	cur = new Node(key, value);
	if (key > parent->_key)
	{
		parent->right = cur;
	}
	else
	{
		parent->left = cur;
	}

	return true;
}

6.实现删除

        二叉搜索树的删除是最麻烦的,我们一点点来分析,删除的节点共有四种情况:左右子树都为空;仅有左树为空;仅有右树为空;左右子树都不为空。

        若左右子树都为空,将删除节点的父节点直接指向空即可;

        若仅有左子树或右子树为空,此时将父节点指向删除节点的左子树或右子树即可——这种实现方式叫做托管法;

        若左右子树都不为空,此时我们应该让父节点指向哪个节点呢?我们有两种选择方案,取删除节点左树的最大值,亦或是取右树节点的最小值。但他们都存在一个问题,将节点挪上来后,他的子树该怎么办?此处我们取左树最大值来举例,我们找到删除节点左树最大值时,它有一个特性,即没有右子树,最多只有左子树,我们只要将这个节点的左树交给这个节点的父节点托管即可。(取右树最小值时差不多同理)

// 删除
bool Erase(const K& key)
{
	Node* parent = nullptr;

	Node* cur = _root;
	while (cur)
	{
		if (key > cur->_key)
		{
			parent = cur;
			cur = cur->right;
		}
		else if (key < cur->_key)
		{
			parent = cur;
			cur = cur->left;
		}
		// 找到要删除的节点时
		else
		{
			// 左右节点为空:托管
			if (cur->left == nullptr)
			{
				// 判断根节点
				if (cur == nullptr)
				{
					_root = cur->right;
				}
				// 此时不知道cur为左节点还是右节点
				if (parent->right = cur)
				{
					parent->right = cur->right;
				}
				else
				{
					parent->left = cur->right;
				}
			}
			else if (cur->right == nullptr)
			{
				// 判断根节点
				if (cur == nullptr)
				{
					_root = cur->left;
				}
				// 此时不知道cur为左节点还是右节点
				if (parent->right = cur)
				{
					parent->right = cur->left;
				}
				else
				{
					parent->left = cur->left;
				}
			}
			// 左右节点都不为空:替代法
			else
			{
				// 获取左子树最大值
				parent = cur;
				Node* LeftMax = cur->left;
				while (LeftMax->right)
				{
					parent = LeftMax;
					LeftMax = LeftMax->right;
				}

				// 交换节点内容
				std::swap(cur->_key, LeftMax->_key);
				std::swap(cur->_value, LeftMax->_value);

				// 处理LeftMax的左子树
				if (parent->left == LeftMax)
				{
					parent->left = LeftMax->left;
				}
				else
				{
					parent->right = LeftMax->left;
				}

				cur = LeftMax;
			}

			delete cur;
			cur = nullptr;

			return true;
		}
	}
	return false;
}

7.实现查找

        查找没什么好说的,我们在前面已经实现过了,这里我们设置返回值为查找到的节点指针。

// 查找
Node* Find(const K& key)
{
	Node* cur = _root;
	while (cur)
	{
		if (key > cur->_key)
		{
			cur = cur->right;
		}
		else if (key < cur->_key)
		{
			cur = cur->left;
		}
		else
			return cur;
	}
    
    // 没找到
	return nullptr;
}

8.实现遍历

        二叉搜索树的遍历很简单,与它的特性有关,使用中序遍历即可,代码实现如下:

// 中序遍历
void Inorder()
{
	_Inorder(_root);
	cout << endl;
}

void _Inorder(Node* node)
{
	if (node == nullptr)
		return;
	_Inorder(node->left);
	cout << node->_key << ":" << node->_value << " ";
	_Inorder(node->right);
}

三、源码及部分测试用例

#pragma once

// 树节点
template<class K, class V>
struct BSTreeNode
{
	BSTreeNode<K, V>* left;
	BSTreeNode<K, V>* right;

	K _key;
	V _value;

	BSTreeNode(const K& key, const V& value)
		:left(nullptr)
		, right(nullptr)
		, _key(key)
		, _value(value)
	{}
};

// 搜索二叉树
// 1.所有根节点比左树大,比右树小
// 2.不能有相同的值节点
template<class K, class V>
class BSTree
{
	typedef BSTreeNode<K, V> Node;
public:
	// 初始化
	BSTree()
		:_root(nullptr)
	{}

	// 拷贝构造
	BSTree(const BSTree<K, V>& t)
	{
		_root = Copy(t._root);
	}

	BSTree<K, V>& operator=(BSTree<K, V> t)
	{
		swap(_root, t._root);
		return *this;
	}

	~BSTree()
	{
		Destory(_root);
	}

	// 插入
	bool Insert(const K& key, const V& value)
	{
		// 排除空
		if (_root == nullptr)
		{
			Node* New = new Node(key, value);
			_root = New;

			return true;
		}

		// 往下查找
		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (key > cur->_key)
			{
				parent = cur;
				cur = cur->right;
			}
			else if (key < cur->_key)
			{
				parent = cur;
				cur = cur->left;
			}
			else
				return false;
		}

		// 放置新节点
		cur = new Node(key, value);
		if (key > parent->_key)
		{
			parent->right = cur;
		}
		else
		{
			parent->left = cur;
		}

		return true;
	}

	// 查找
	Node* Find(const K& key)
	{
		Node* cur = _root;
		while (cur)
		{
			if (key > cur->_key)
			{
				cur = cur->right;
			}
			else if (key < cur->_key)
			{
				cur = cur->left;
			}
			else
				return cur;
		}

		return nullptr;
	}

	// 删除
	bool Erase(const K& key)
	{
		Node* parent = nullptr;

		Node* cur = _root;
		while (cur)
		{
			if (key > cur->_key)
			{
				parent = cur;
				cur = cur->right;
			}
			else if (key < cur->_key)
			{
				parent = cur;
				cur = cur->left;
			}
			// 找到要删除的节点
			else
			{
				// 左右节点为空:托管
				if (cur->left == nullptr)
				{
					// 判断根节点
					if (cur == nullptr)
					{
						_root = cur->right;
					}
					// 此时不知道cur为左节点还是右节点
					if (parent->right = cur)
					{
						parent->right = cur->right;
					}
					else
					{
						parent->left = cur->right;
					}
				}
				else if (cur->right == nullptr)
				{
					// 判断根节点
					if (cur == nullptr)
					{
						_root = cur->left;
					}
					// 此时不知道cur为左节点还是右节点
					if (parent->right = cur)
					{
						parent->right = cur->left;
					}
					else
					{
						parent->left = cur->left;
					}
				}
				// 左右节点都不为空:替代法
				else
				{
					// 获取左子树最大值
					parent = cur;
					Node* LeftMax = cur->left;
					while (LeftMax->right)
					{
						parent = LeftMax;
						LeftMax = LeftMax->right;
					}

					// 交换节点内容
					std::swap(cur->_key, LeftMax->_key);
					std::swap(cur->_value, LeftMax->_value);

					// 处理LeftMax的左子树
					if (parent->left == LeftMax)
					{
						parent->left = LeftMax->left;
					}
					else
					{
						parent->right = LeftMax->left;
					}

					cur = LeftMax;
				}

				delete cur;
				cur = nullptr;

				return true;
			}
		}
		return false;
	}

	// 中序遍历
	void Inorder()
	{
		_Inorder(_root);
		cout << endl;
	}

private:
	Node* _root;

	Node* Copy(Node* root)
	{
		if (root == nullptr)
			return nullptr;

		Node* NewRoot = new Node(root);
		NewRoot->_key = root->_key;

		NewRoot->left = Copy(root->left);
		NewRoot->right = Copy(root->right);
		return NewRoot;
	}

	void Destory(Node*& del)
	{
		if (del == nullptr)
			return;

		Destory(del->left);
		Destory(del->right);

		delete del;
		del = nullptr;
	}

	void _Inorder(Node* node)
	{
		if (node == nullptr)
			return;
		_Inorder(node->left);
		cout << node->_key << ":" << node->_value << " ";
		_Inorder(node->right);
	}#pragma once

// 树节点
template<class K, class V>
struct BSTreeNode
{
	BSTreeNode<K, V>* left;
	BSTreeNode<K, V>* right;

	K _key;
	V _value;

	BSTreeNode(const K& key, const V& value)
		:left(nullptr)
		, right(nullptr)
		, _key(key)
		, _value(value)
	{}
};

// 搜索二叉树
// 1.所有根节点比左树大,比右树小
// 2.不能有相同的值节点
template<class K, class V>
class BSTree
{
	typedef BSTreeNode<K, V> Node;
public:
	// 初始化
	BSTree()
		:_root(nullptr)
	{}

	// 拷贝构造
	BSTree(const BSTree<K, V>& t)
	{
		_root = Copy(t._root);
	}

	BSTree<K, V>& operator=(BSTree<K, V> t)
	{
		swap(_root, t._root);
		return *this;
	}

	~BSTree()
	{
		Destory(_root);
	}

	// 插入
	bool Insert(const K& key, const V& value)
	{
		// 排除空
		if (_root == nullptr)
		{
			Node* New = new Node(key, value);
			_root = New;

			return true;
		}

		// 往下查找
		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (key > cur->_key)
			{
				parent = cur;
				cur = cur->right;
			}
			else if (key < cur->_key)
			{
				parent = cur;
				cur = cur->left;
			}
			else
				return false;
		}

		// 放置新节点
		cur = new Node(key, value);
		if (key > parent->_key)
		{
			parent->right = cur;
		}
		else
		{
			parent->left = cur;
		}

		return true;
	}

	// 查找
	Node* Find(const K& key)
	{
		Node* cur = _root;
		while (cur)
		{
			if (key > cur->_key)
			{
				cur = cur->right;
			}
			else if (key < cur->_key)
			{
				cur = cur->left;
			}
			else
				return cur;
		}

		return nullptr;
	}

	// 删除
	bool Erase(const K& key)
	{
		Node* parent = nullptr;

		Node* cur = _root;
		while (cur)
		{
			if (key > cur->_key)
			{
				parent = cur;
				cur = cur->right;
			}
			else if (key < cur->_key)
			{
				parent = cur;
				cur = cur->left;
			}
			// 找到要删除的节点
			else
			{
				// 左右节点为空:托管
				if (cur->left == nullptr)
				{
					// 判断根节点
					if (cur == nullptr)
					{
						_root = cur->right;
					}
					// 此时不知道cur为左节点还是右节点
					if (parent->right = cur)
					{
						parent->right = cur->right;
					}
					else
					{
						parent->left = cur->right;
					}
				}
				else if (cur->right == nullptr)
				{
					// 判断根节点
					if (cur == nullptr)
					{
						_root = cur->left;
					}
					// 此时不知道cur为左节点还是右节点
					if (parent->right = cur)
					{
						parent->right = cur->left;
					}
					else
					{
						parent->left = cur->left;
					}
				}
				// 左右节点都不为空:替代法
				else
				{
					// 获取左子树最大值
					parent = cur;
					Node* LeftMax = cur->left;
					while (LeftMax->right)
					{
						parent = LeftMax;
						LeftMax = LeftMax->right;
					}

					// 交换节点内容
					std::swap(cur->_key, LeftMax->_key);
					std::swap(cur->_value, LeftMax->_value);

					// 处理LeftMax的左子树
					if (parent->left == LeftMax)
					{
						parent->left = LeftMax->left;
					}
					else
					{
						parent->right = LeftMax->left;
					}

					cur = LeftMax;
				}

				delete cur;
				cur = nullptr;

				return true;
			}
		}
		return false;
	}

	// 中序遍历
	void Inorder()
	{
		_Inorder(_root);
		cout << endl;
	}

private:
	Node* _root;

	Node* Copy(Node* root)
	{
		if (root == nullptr)
			return nullptr;

		Node* NewRoot = new Node(root);
		NewRoot->_key = root->_key;

		NewRoot->left = Copy(root->left);
		NewRoot->right = Copy(root->right);
		return NewRoot;
	}

	void Destory(Node*& del)
	{
		if (del == nullptr)
			return;

		Destory(del->left);
		Destory(del->right);

		delete del;
		del = nullptr;
	}

	void _Inorder(Node* node)
	{
		if (node == nullptr)
			return;
		_Inorder(node->left);
		cout << node->_key << ":" << node->_value << " ";
		_Inorder(node->right);
	}

public:
	void TestBSTree1()
	{
		BSTree<string, string> dict;
		dict.Insert("insert", "插入");
		dict.Insert("sort", "排序");
		dict.Insert("right", "右边");
		dict.Insert("date", "日期");

		string str;
		while (cin >> str)
		{
			BSTreeNode<string, string>* ret = dict.Find(str);
			if (ret)
			{
				cout << ret->_value << endl;
			}
			else
			{
				cout << "无此单词" << endl;
			}
		}
	}

	void TestBSTree2()
	{
		// 统计水果出现的次数
		string arr[] = { "西瓜", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };
		BSTree<string, int> countTree;
		for (auto& str : arr)
		{
			auto ret = countTree.Find(str);
			if (ret == nullptr)
			{
				countTree.Insert(str, 1);
			}
			else
			{
				ret->_value++;
			}
		}

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

【C++】模拟实现二叉搜索树(附源码、测试用例) 的相关文章

  • 检查空参数的最佳方法(保护子句)

    例如 您通常不希望构造函数中的参数为空 因此看到类似的内容是很正常的 if someArg null throw new ArgumentNullException nameof someArg if otherArg null throw
  • 以相反的顺序迭代可变参数模板参数

    如果我手动反转传递给它的模板参数的顺序 以下代码将起作用 template
  • SL4 AutoCompleteBox 重复筛选结果问题

    我在 AutoCompleteBox 过滤方面遇到问题 它似乎记住了之前的过滤器 例如 我输入 A 它会返回 1 项 我删除 A 并输入 Z 这应该返回 1 项 问题是它返回 A 过滤器加上 Z 的结果 我删除 Z 并输入 S 这会带回 2
  • 切换图片框可见性 C#

    为什么图片框控件的可见性属性在这里不起作用 我最初将它们设置为 false 以便在屏幕加载时它们不可见 但后来我想切换这个 我已完成以下操作 但似乎不起作用 这是一个 Windows 窗体应用程序 private void Action w
  • 如何将pdf页面设置设置为打印属性对话框?

    大家好 我想知道如何设置 pdf 页面设置到打印属性对话框 例如 如果我的 PDF 页面设置为横向 则布局会自动显示横向而不是纵向 如果我的 PDF 页面设置为纵向 则布局会自动显示纵向 我在这个主题上做了很多研发 但没有找到任何满意的链接
  • C# 中附加/分离事件处理程序的不同方式有什么区别

    我的问题有两个部分 首先 我们可以通过以下两种方式附加事件处理程序 myObject MyEvent new EventHandler MyHandler myObject MyEvent MyHandler 据我了解 这两者是等价的 在第
  • 通过引用传递时取消引用指针

    当通过引用传递给函数时取消引用指针时会发生什么 这是一个简单的例子 int returnSame int example return example int main int inum 3 int pinum inum std cout
  • 为什么假设 send 可能返回的数据少于在阻塞套接字上传输的请求数据?

    在流套接字上发送数据的标准方法始终是调用 send 并写入一大块数据 检查返回值以查看是否发送了所有数据 然后再次调用 send 直到整个消息被接受 例如 这是一个常见方案的简单示例 int send all int sock unsign
  • 如何将字节块读入结构体

    我有一个需要处理的资源文件 它包含一组文件 首先 资源文件列出了其中包含的所有文件 以及一些其他数据 例如在此结构中 struct FileEntry byte Value1 char Filename 12 byte Value2 byt
  • 用 C# 制作 Vista 风格的应用程序

    我正在运行 Windows Vista 并且希望外观看起来像常规 Vista 程序 有没有关于如何构建 Vista 风格应用程序的真正好的教程 文章 我还想学习如何使用本机代码并将其转换为 C 如this http bartdesmet n
  • 使用 openssl 检查服务器安全协议

    我有一个框架应用程序 它根据使用方式连接到不同的服务器 对于 https 连接 使用 openssl 我的问题是 我需要知道我连接的服务器是否使用 SSL 还是 TLS 以便我可以创建正确的 SSL 上下文 目前 如果我使用错误的上下文尝试
  • 使用scanf()时如何区分整数和字符

    我只是使用该功能scanf 代码如下 scanf d a printf d a 当我输入1时 它会像我想要的那样打印1 但即使我输入 1a 它也会像以前一样打印 1 当用户输入非整数时 例如 2 3 12ab 1 a 我想向用户显示 输入整
  • 线程安全的 C++ 堆栈

    我是 C 新手 正在编写一个多线程应用程序 不同的编写者将对象推入堆栈 读者将它们从堆栈中拉出 或至少将指针推入对象 C 中是否有任何内置结构可以在不添加锁定代码等的情况下处理此问题 如果没有 那么 Boost 库呢 EDIT 你好 感谢您
  • c# 如何生成锦标赛括号 HTML 表

    所以我已经被这个问题困扰了三个星期 但我一生都无法弄清楚 我想做的是使用表格获得这种输出 演示 http www esl world net masters season6 hanover sc2 playoffs rankings htt
  • 如何在 C# 中使用 XmlDsigC14NTransform 类

    我正在尝试使用规范化 xml 节点System Security Cryptography Xml XMLDsigC14nTransformC net Framework 2 0 的类 该实例需要三种不同的输入类型 NodeList Str
  • C# 中处理 SQL 死锁的模式?

    我正在用 C 编写一个访问 SQL Server 2005 数据库的应用程序 该应用程序是数据库密集型的 即使我尝试优化所有访问 设置适当的索引等 我预计迟早会遇到死锁 我知道为什么会发生数据库死锁 但我怀疑我能否在某个时候发布不发生死锁的
  • realloc():重新分配为 char * 上的 strcat 腾出空间时下一个大小无效 [重复]

    这个问题在这里已经有答案了 我在以下代码中收到无效内存错误 printf s n FINE 5 printf s LENGTH IS d n FINE 6 strlen buffer char realloc buffer strlen b
  • 无法通过 LINQ to Entities 使用某些功能?

    我正在尝试使用 LINQ 查询在项目上实现搜索功能 由于数据有时包含带有重音符号和其他符号的字符 因此我创建了一种方法来删除这些字符以进行搜索 这是我的代码 var addresses from a in db Addresses join
  • 程序退出后,TcpListener Socket 仍处于活动状态

    当我的程序退出时 我试图停止 TCP 侦听器 我不关心套接字或任何活动客户端套接字上当前活动的任何数据 套接字清理代码本质上是 try myServer Server Shutdown SocketShutdown Both catch E
  • 在何处将 CFLAG(例如 -std=gnu99)添加到 (Eclipse CDT) 自动工具项目中

    我有一个简单的 Autotools C 项目 不是 C 其框架是由 Eclipse CDT Juno 为我创建的 CFLAG 通过检查 似乎是 g O2 我希望所有生成的 make 文件也具有 std gnu99附加到 CFLAG 因为我使

随机推荐

  • 推荐VSC中一款好用的插件------Code Runner插件

    推荐VSC中一款好用的插件 Code Runner插件 Code Runner插件非常好用 可以运行的语言有 Run C C Java JS PHP Python Perl Ruby Go Lua Groovy PowerShell CMD
  • 软件系统工具-架构师真题(六)

    不属于可修改性考虑的内容 2016 可维护性 可扩展性 结构重构 可变性 答案 D 解析 可修改性指快速较高的性能价格进行系统优化 包括可维护性 可扩展性 结构重组和可移植性四个方面 软件系统工具中 软件评价工具属于 逆向工程工具 开发信息
  • Qt 帮助框架简介

    概述 Qt帮助系统包括生成和查看Qt帮助文件的工具 此外 它还提供了以编程方式访问帮助内容的类 以便能够将在线帮助集成到Qt应用程序中 实际的帮助数据 也就是目录 索引关键字或HTML文档 都包含在Qt压缩帮助文件中 所以 一个这样的帮助文
  • ssm美食论坛系统毕业设计源码191023

    目 录 摘要 1 绪论 1 1 研究背景及意义 1 2开发现状 1 3论文结构与章节安排 2 美食论坛系统系统分析 2 1 可行性分析 2 2 系统流程分析 2 2 1 数据流程 3 3 2 业务流程 2 3 系统功能分析 2 3 1数据增
  • vue 使用fs_node.js 中的 fs 模块的使用

    let fs require fs 检测是文件还是目录 名字 回调函数 fs stat package json err data gt if err console log err return console log 是文件 data
  • win10下载编译webrtc源码

    win10系统下载编译webrtc源码 一 下载安装VS2017 目前最新版本的webrtc已经可以用Vs2019 但是因为我们要使用的webrtc版本是以前的版本 旧版webrtc源码中vs toolchain py中指定了vs2017
  • AI日报|哈佛“AI教授”即将上线;首个生成式AI技能专业证书来了;电话推销员很烦?AI帮你“制裁”他

    今日值得关注的人工智能新动态 将GPT 4用在课程设计中 哈佛大学 AI教授 即将上线 微软推出首个生成式AI技能专业证书 纽约州议会 伤害或羞辱他人的deepfake是非法的 阿诺德 施瓦辛格 终结者 中的AI已成现实 AI诊断 老年痴呆
  • 函数粘合云服务提供端到端解决方案

    作者 西流 阿里云技术专家 导读 阿里云Serverless 产品函数计算可以作为粘合剂 串联其他云服务提供端到端解决方案 从而简化编程模型 快速实现最上层的业务目标 传统单体应用的拆解 首先我们来看下单体应用里面常见的两个编程模型 如上图
  • 【华为OD统一考试B卷

    华为OD统一考试A卷 B卷 新题库说明 2023年5月份 华为官方已经将的 2022 0223Q 1 2 3 4 统一修改为OD统一考试 A卷 和OD统一考试 B卷 你收到的链接上面会标注A卷还是B卷 请注意 根据反馈 目前大部分收到的都是
  • Hive SQL 2023必考常用窗口函数及面试题

    一 窗口函数概述 窗口函数也称为OLAP函数 OLAP 是OnLine Analytical Processing 的简称 意思是对数据库数据进行实时分析处理 例如 市场分析 创建财务报表 创建计划等日常性商务工作 窗口函数就是为了实现OL
  • 使用TensorFlow、Keras和深度学习实现像素无序超分辨率

    使用TensorFlow Keras和深度学习实现像素无序超分辨率 pixel shuffle Super Resolution 像素无序 洗牌超分辨率 Deep Learning Super Sampling DLSS 深度学习超级采样
  • flask_sqlalchemy中的db.session.query()和model.query()的区别

    先申明一下 我喜欢从问题入手 问题描述 使用db session commit 提交数据后 使用model query 查不到新增加的数据 问题原因分析 db session commit 是提交了数据到数据库 但是没有刷新模型映射中的数据
  • 使用Fabric8 kubernetes-client java client 操作kuberntes 自定义资源CR

    kubernetes client fabric8 to interact with kubernetes custom resources kubernetes中的一切东西都叫做 resource k8s 默认的提供了很多 resourc
  • 【Python】初识Python

    目录 执行Python的文件有三种方式 注释的细节 算术运算符 变量 输入与输出函数 input函数 print函数 强制类型转换函数 Python程序的特点 Python源程序本质上是一个特殊格式的文本文件 只不过它的后缀扩展名是 py
  • python将秒数转化为时间格式

    1 转化成时间格式 seconds 35400 m s divmod seconds 60 h m divmod m 60 print d 02d 02d h m s 结果 9 50 00 2 转化成日期时间格式 import time t
  • 服务service设置

    2017 03 10 一点简单的讲解 http cwtea blog 51cto com 4500217 842002 service命令只有很简单的几个参数 start restart reload status stop 不能利用这个命
  • 自学Python能学会吗?

    这是一个非常好的问题 作为一名IT从业者 同时也是一名教育工作者 我来回答一下 首先 随着当前Python语言的应用越来越普遍 很多职场人和大学生都希望能够通过掌握Python语言来提升职场价值和岗位竞争力 由于Python语言本身比较简单
  • FreeRTOS-信号量详解

    作者简介 嵌入式入坑者 与大家一起加油 希望文章能够帮助各位 个人主页 rivencode的个人主页 系列专栏 玩转FreeRTOS 保持学习 保持热爱 认真分享 一起进步 目录 前言 一 信号量的简介 二 FreeRTOS信号量 1 二值
  • 牛客题:Java静态块、构造块执行顺序

    public class Test public static Test t1 new Test 静态变量 构造块 System out println AAA 静态块 static System out println BBB publi
  • 【C++】模拟实现二叉搜索树(附源码、测试用例)

    二叉搜索树 一 前言 二 模拟实现 1 构建树的单个节点 2 二叉搜索树的概念 3 构造函数与析构函数 4 赋值与拷贝构造 5 实现插入 6 实现删除 7 实现查找 8 实现遍历 三 源码及部分测试用例 一 前言 二叉搜索树 和普通的二叉树