C++:二叉搜索树(非平衡化)

news2025/4/6 23:11:10

在这里插入图片描述

文章目录

  • 一.二叉搜索树(key_value模型)
  • 二.二叉搜索树的节点删除
  • 三.二叉搜索树类对象其他接口
    • 构造函数,析构函数和赋值运算符重载
    • 节点插入接口和节点查找接口
    • key_value模型二叉搜索树类模板总体代码
  • 四.未经平衡化的二叉搜索树的缺陷

一.二叉搜索树(key_value模型)

  • 树的节点定义:
	template<class K, class V>
	struct BSTreeNode
	{
		BSTreeNode<K, V>* _left;
		BSTreeNode<K, V>* _right;
		//key是用于实现搜索功能以及搜索树其他功能的关键值
		K _key;
		//value用于存储数据
		V _value;
		//树结点的默认构造函数
		BSTreeNode(const K& key = K(), const V& value = V())
			:_left(nullptr)
			, _right(nullptr)
			, _key(key)
			, _value(value)
		{}
	};
  • 如果一颗二叉树是二叉搜索树,则其具有如下性质:
    • 左子树的所有结点的key值都比根结点的key值
    • 右子树的所有结点的key值都比根结点的key值
    • 二叉搜索树的左右子树仍为二叉搜索树
      在这里插入图片描述
  • 二叉搜索树满足递归定义
  • 容易证明,二叉搜索树的中序遍历序列是一个升序序列(因此二叉搜索树具有排序功能,也被称作二叉排序树)
  • 根据搜索树的定义可知,树中不存在key值相同的节点,因此搜索树还具有去重的功能
  • 二叉搜索树C++类模板总览:
	template<class K, class V>
	class BSTree
	{
		typedef BSTreeNode<K, V> Node;
	public:
	//供外界调用的功能接口(通过复用内部私有接口实现)
		
		//强制生成类的默认构造函数
		BSTree() = default; 
		//利用前序遍历递归完成拷贝构造
		BSTree(const BSTree<K,V>& t)
		{
			_root = _Copy(t._root);
		}
		//通过复用拷贝构造实现赋值运算符重载
		BSTree<K,V>& operator =(BSTree<K,V>t)
		{
			std::swap(t._root, _root);
			return (*this);
		}
		//插入节点
		bool InsertR(const K& key, const V& value)
		{
			return _InsertR(_root,key, value);
		}
		//查找节点
		Node* Find(const K& key)
		{
			return _FindR(_root,key);
		}
		//删除节点(这里调用递归的接口)
		bool Erase(const K& key)
		{
			return _EraseR(_root, key);
		}
		//中序遍历搜索树
		void InOrder()
		{
			_InOrder(_root);
		}
		//搜索树的析构函数
		~BSTree()
		{
			_Destroy(_root);
		}
	protected:
	//私有功能接口
		//用于实现拷贝构造的辅助函数(前序递归实现)
		Node* _Copy(const Node* root);
		//后序遍历销毁二叉树
		void _Destroy(Node*& root);
		//递归实现插入节点
		bool _InsertR(Node*& root, const K& key,const V& value);
		//递归实现节点查找
		Node * _FindR(Node*& root, const K& key);
		//递归删除搜索树结点
		bool _EraseR(Node*& root, const K& key);
		//非递归删除搜索树结点
		bool _Erase(Node *&root,const K& key)//中序遍历搜索树
		void _InOrder(Node* root);
		//寻找子树key值最大的结点的接口
		Node* _FindMax(Node* root);
	private:
		//根节点指针
		Node* _root = nullptr;
	};

二.二叉搜索树的节点删除

  • 搜索树节点删除操作必须保持二叉搜索树的结构性质不变
  • 非递归删除搜索树节点
    • 接口首部:bool _Erase(Node*& root, const K& key) (删除成功则返回true,否则返回false)

    • 代码逻辑思维导图: 在这里插入图片描述

    • 删除情况1演示:在这里插入图片描述

    • 删除情况3演示:在这里插入图片描述

    • 删除情况2演示:在这里插入图片描述

    • 情况2中的子树最值替换删除法保证了搜索树的结构性质以及删除方式的简洁性和逻辑唯一性

    • 非递归删除结点代码:

		//非递归删除节点
		bool _Erase(Node*& root, const K& key)
		{
			Node* precur = nullptr;
			Node* cur = root;
			while (cur)
			{
				if (cur->_key > key)
				{
					precur = cur;
					cur = cur->_left;
				}
				else if (cur->_key < key)
				{
					precur = cur;
					cur = cur->_right;
				}
				else
				{
					//执行删除操作
					//找到待删除节点
					//待删除结点只可能有右孩子
					if (cur->_left == nullptr)
					{
						//判断待删结点是否为根节点
						if (root == cur)
						{
							root = cur->_right;
						}
						else
						{
							//将右孩子交给前驱指针
							if (precur->_left == cur)
							{
								precur->_left = cur->_right;
							}
							else
							{
								precur->_right = cur->_right;
							}
						}
						delete cur;
						cur = nullptr;
						return true;
					}
					//待删除结点只有左孩子
					else if (cur->_right == nullptr)
					{
						//判断待删结点是否为根节点
						if (root == cur)
						{
							root = cur->_left;
						}
						else
						{
							//将左孩子交给前驱指针
							if (precur->_left == cur)
							{
								precur->_left = cur->_left;
							}
							else
							{
								precur->_right = cur->_left;
							}
						}
						delete cur;
						cur = nullptr;
						return true;
					}
					//待删除结点既有左孩子又有右孩子
					else
					{
						//用左子树的最大结点与待删节点进行替换后,再删除待删节点
						Node* Maxpre = cur;
						Node* Max = cur->_left;
						while (Max->_right)
						{
							Maxpre = Max;
							Max = Max->_right;
						}
						std::swap(Max->_key, cur->_key);
						//将左孩子交给前驱指针
						if (Maxpre->_left == Max)
						{
							Maxpre->_left = Max->_left;
						}
						else
						{
							Maxpre->_right = Max->_left;
						}
						delete Max;
						Max = nullptr;
						return true;
					}
				}
			}
			return false;
		}
  • 递归删除搜索树节点:
    • 接口首部bool _EraseR(Node*& root, const K& key)
    • 递归删除搜索树节点算法采用节点指针变量的引用进行传参递归,形参直接引用了当前待操作节点前驱指针,因此在函数中可以直接通过形参待删除节点的前驱指针进行修改,代码书写上会简单很多
    • 递归删除搜索树节点代码:
		//寻找子树最大结点的接口
		Node* _FindMax(Node*root)
		{
			while (root->_right)
			{
				root = root->_right;
			}
			return root;
		}
		bool _EraseR(Node*& root, const K& key)
		{
			if (root == nullptr)
			{
				return false;
			}
			else if (root->_key > key)
			{
				//在左子树中删除节点
				_EraseR(root->_left, key);
			}
			else if (root->_key < key)
			{
				//在右子树中删除节点
				_EraseR(root->_right, key);
			}
			else
			{
				Node* del = root;
				//对待删除节点进行分类讨论,同样分三类进行讨论
				if (root->_left == nullptr)
				{
					//将右子树交给前驱指针
					root = root->_right;
				}
				else if (root->_right == nullptr)
				{
					//将左子树交给前驱指针
					root = root->_left;
				}
				else
				{
					Node* Max = _FindMax(root->_left);
					std::swap(Max->_key, root->_key);
					//递归删除换位后的目标节点
					_EraseR(root->_left, key);
					return true;
				}
				delete del;
				return true;
			}
		}

三.二叉搜索树类对象其他接口

构造函数,析构函数和赋值运算符重载

  • 辅助接口Node* _Copy(const Node* root)
  • 拷贝构造函数BSTree(const BSTree<K,V>& t)
		//强制编译器生成类的默认构造函数
		BSTree() = default;
		//用于实现拷贝构造的辅助函数(前序递归实现树的深拷贝)
		Node* _Copy(const Node* root)
		{
			if (root == nullptr)
			{
				return nullptr;
			}
			Node* Root = new Node(root->_key,root->_value);
			Root->_left = _Copy(root->_left);
			Root->_right = _Copy(root->_right);
			return Root;
		}
		BSTree(const BSTree<K,V>& t)
		{
			_root = _Copy(t._root);
		}
  • 赋值运算符重载:
    • 接口首部:BSTree<K,V>& operator =(BSTree<K,V>t),通过复用拷贝构造实现
		//通过复用拷贝构造实现赋值运算符重载
		BSTree<K,V>& operator =(BSTree<K,V>t)
		{
			std::swap(t._root, _root);
			return (*this);
		}

在这里插入图片描述

  • 析构函数:
    • 后序遍历递归释放所有节点
    • 辅助接口:void _Destroy(Node*& root);
		//后序遍历销毁二叉树
		void _Destroy(Node*& root)
		{
			if (root == nullptr)
			{
				return;
			}
			_Destroy(root->_left);
			_Destroy(root->_right);
			delete root;
			root = nullptr;
		}
		//搜索树的析构函数
		~BSTree()
		{
			_Destroy(_root);
		}

节点插入接口和节点查找接口

  • 节点插入接口
    • 辅助接口bool _InsertR(Node*& root, const K& key,const V& value);,通过递归实现节点的插入
    • 供外界调用的接口:bool InsertR(const K& key, const V& value);
		//递归插入节点
		bool _InsertR(Node*& root, const K& key,const V& value)
		{
			if (root == nullptr)
			{
				//找到空位置则插入
				root = new Node(key,value);
				return true;
			}
			else if (root->_key > key)
			{
				return _InsertR(root->_left, key,value);
			}
			else if (root->_key < key)
			{
				return _InsertR(root->_right, key,value);
			}
			else
			{
				//找到相同节点则插入失败
				//插入操作中体现了搜索树的去重功能
				return false;
			}
		}
		//插入节点
		bool InsertR(const K& key, const V& value)
		{
			return _InsertR(_root, key, value);
		}
  • 节点查找接口
    • 递归实现:
		//递归实现查找
		Node * _FindR(Node*& root, const K& key)
		{
			if (root == nullptr)
			{
				//找到空则说明结点不存在
				return nullptr;
			}
			else if (root->_key > key)
			{
				return _FindR(root->_left,key);
			}
			else if (root->_key < key)
			{
				return _FindR(root->_right,key);
			}
			else
			{
				return root;
			}
		}
		//查找节点
		Node* Find(const K& key)
		{
			return _FindR(_root, key);
		}

key_value模型二叉搜索树类模板总体代码

namespace key_value
{
#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 = K(), const V& value = V())
			:_left(nullptr)
			, _right(nullptr)
			, _key(key)
			, _value(value)
		{}
	};


	template<class K, class V>
	class BSTree
	{
		typedef BSTreeNode<K, V> Node;
	public:
		//强制生成类的默认构造函数
		BSTree() = default;
		//利用前序遍历递归完成拷贝构造
		BSTree(const BSTree<K,V>& t)
		{
			_root = _Copy(t._root);
		}
		//通过复用拷贝构造实现赋值运算符重载
		BSTree<K,V>& operator =(BSTree<K,V>t)
		{
			std::swap(t._root, _root);
			return (*this);
		}
		//插入节点
		bool InsertR(const K& key, const V& value)
		{
			return _InsertR(_root, key, value);
		}
		//查找节点
		Node* Find(const K& key)
		{
			return _FindR(_root, key);
		}
		//删除节点
		bool Erase(const K& key)
		{
			return _EraseR(_root, key);
		}
		//中序遍历搜索树
		void InOrder()
		{
			_InOrder(_root);
		}
		//搜索树的析构函数
		~BSTree()
		{
			_Destroy(_root);
		}
	protected:
		//用于实现拷贝构造的辅助函数(前序递归实现树的深拷贝)
		Node* _Copy(const Node* root)
		{
			if (root == nullptr)
			{
				return nullptr;
			}
			Node* Root = new Node(root->_key,root->_value);
			Root->_left = _Copy(root->_left);
			Root->_right = _Copy(root->_right);
			return Root;
		}
		//后序遍历销毁二叉树
		void _Destroy(Node*& root)
		{
			if (root == nullptr)
			{
				return;
			}
			_Destroy(root->_left);
			_Destroy(root->_right);
			delete root;
			root = nullptr;
		}
		//递归插入节点
		bool _InsertR(Node*& root, const K& key,const V& value)
		{
			if (root == nullptr)
			{
				//找到空位置则插入
				root = new Node(key,value);
				return true;
			}
			else if (root->_key > key)
			{
				return _InsertR(root->_left, key,value);
			}
			else if (root->_key < key)
			{
				return _InsertR(root->_right, key,value);
			}
			else
			{
				//找到相同节点则插入失败
				return false;
			}
		}
		//递归实现查找
		Node * _FindR(Node*& root, const K& key)
		{
			if (root == nullptr)
			{
				//找到空则说明结点不存在
				return nullptr;
			}
			else if (root->_key > key)
			{
				return _FindR(root->_left,key);
			}
			else if (root->_key < key)
			{
				return _FindR(root->_right,key);
			}
			else
			{
				return root;
			}
		}
		//非递归删除节点
		bool _Erase(Node*& root, const K& key)
		{
			Node* precur = nullptr;
			Node* cur = root;
			while (cur)
			{
				if (cur->_key > key)
				{
					precur = cur;
					cur = cur->_left;
				}
				else if (cur->_key < key)
				{
					precur = cur;
					cur = cur->_right;
				}
				else
				{
					//执行删除操作
					//找到待删除节点
					//待删除结点只可能有右孩子
					if (cur->_left == nullptr)
					{
						//判断待删结点是否为头节点
						if (root == cur)
						{
							root = cur->_right;
						}
						else
						{
							if (precur->_left == cur)
							{
								precur->_left = cur->_right;
							}
							else
							{
								precur->_right = cur->_right;
							}
						}
						delete cur;
						cur = nullptr;
						return true;
					}
					//待删除结点只有左孩子
					else if (cur->_right == nullptr)
					{
						//判断待删结点是否为头节点
						if (root == cur)
						{
							root = cur->_left;
						}
						else
						{
							if (precur->_left == cur)
							{
								precur->_left = cur->_left;
							}
							else
							{
								precur->_right = cur->_left;
							}
						}
						delete cur;
						cur = nullptr;
						return true;
					}
					//待删除结点既有左孩子又有右孩子
					else
					{
						//用左子树的最大结点与待删节点进行替换后,再删除待删节点
						Node* Maxpre = cur;
						Node* Max = cur->_left;
						while (Max->_right)
						{
							Maxpre = Max;
							Max = Max->_right;
						}
						std::swap(Max->_key, cur->_key);
						if (Maxpre->_left == Max)
						{
							Maxpre->_left = Max->_left;
						}
						else
						{
							Maxpre->_right = Max->_left;
						}
						delete Max;
						Max = nullptr;
						return true;
					}
				}
			}
			return false;
		}
		//递归删除搜索树结点
		bool _EraseR(Node*& root, const K& key)
		{
			if (root == nullptr)
			{
				return false;
			}
			else if (root->_key > key)
			{
				_EraseR(root->_left, key);
			}
			else if (root->_key < key)
			{
				_EraseR(root->_right, key);
			}
			else
			{
				Node* del = root;
				if (root->_left == nullptr)
				{
					root = root->_right;
				}
				else if (root->_right == nullptr)
				{
					root = root->_left;
				}
				else
				{
					Node* Max = _FindMax(root->_left);
					std::swap(Max->_key, root->_key);
					_EraseR(root->_left, key);
					return true;
				}
				delete del;
				return true;
			}
		}
		//中序遍历搜索树
		void _InOrder(Node* root)
		{
			if (root == nullptr)
			{
				return;
			}
			_InOrder(root->_left);
			cout << "结点的key值:" << root->_key << ' ' << "节点的value:" << root->_value << endl;
			_InOrder(root->_right);
		}
		//寻找子树最大结点的接口
		Node* _FindMax(Node* root)
		{
			while (root->_right)
			{
				root = root->_right;
			}
			return root;
		}
	private:
		Node* _root = nullptr;
	};
}

四.未经平衡化的二叉搜索树的缺陷

  • 二叉搜索树的节点插入,删除,查找操作的时间复杂度取决于搜索树的高度
  • 在相同节点数量下,完全二叉树的高度是最小的,搜索树为完全二叉树时,节点插入,删除,查找操作的时间复杂度都为O(logN)
  • 然而,相同的结点集合,构造出的二叉搜索树高度是不确定的(有时甚至会直接构造出单链表的线性形状,此时搜索树便退化为线性表),比如:在这里插入图片描述
  • 因此,想让二叉搜索树在实际场景中发挥作用,就需要平衡化算法对其进行优化(所谓平衡化就是改变搜索树的结构使其接近完全二叉树)
    在这里插入图片描述

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

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

相关文章

华为OD机试真题B卷 JavaScript 实现【数据最节约的备份方法】,附详细解题思路

一、题目描述 有若干个文件&#xff0c;使用刻录光盘的方式进行备份&#xff0c;假设每张光盘的容量是500MB。 求使用光盘最少的文件分布方式&#xff0c;所有文件的大小都是整数的MB&#xff0c;且不超过500MB&#xff0c;文件不能分隔、分卷打包。 二、输入描述 每组文件…

mysql服务器启动和关闭

Windows 系统下启动停止 MySQL 服务的方式主要有以下两种&#xff1a; 通过计算机管理方式通过CMD命令行方式 备注: 测试数据库版本为MySQL5.7。 安装mysql服务器版本5.7成功&#xff0c;且加入系统变量成功之后&#xff0c;按照以下步骤启动/停止服务器。 一、通过计算机管…

Xubuntu22.04之绘制正弦波(一百七十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

测试人生 | 三十而已,何需惧怕!年薪40W+涨薪幅度超40%

关于我&#xff0c;普通二本&#xff0c;非计算机专业&#xff0c;培训出身&#xff0c;北漂&#xff0c;五年多的工作经验&#xff0c;做过外包&#xff0c;中间有过频繁的跳槽经历&#xff0c;手工点点点为主&#xff0c;最近确认了新Offer&#xff0c;远程办公&#xff0c;涨…

G - 1-n数组

第四次题组 [Cloned] - Virtual Judge (vjudge.net) 【题目描述】 给你一个数组一个a[n]组成n正整数。您可以对其执行操作。 在一个操作中&#xff0c;您可以替换数组的任何元素一个我​跟⌊/2​​⌋ 看看您是否可以多次应用该操作&#xff08;可能操作为0&#xff09; 来制…

Apache Commons CSV 基本使用

Apache Commons CSV 基本使用 文章目录 Apache Commons CSV 基本使用一、概述1、简介2、主要特点3、官方资料 二、基本使用1、引入依赖2、读取 .csv 文件文件内容读取文件 3、写入文件写入文件写入结果 一、概述 1、简介 Apache Commons CSV是Apache软件基金会的一个开源项目…

Android——认识Android (Android发展简介)(一)

如果想要学习好Android开发&#xff0c;首先需要能够熟练应用以下的几个知识&#xff1a; JavaSE : 理解面向对象&#xff0c;掌握网络通信&#xff0c;掌握集合&#xff0c;掌握IO操作&#xff0c;要懂得图形化界面swing。 JavaEE&#xff1a;也需要一定的了解&#xff0c;以…

mysql简单入门常见的语句使用

一、安装mysql 二、数据库操作 1、进入本地数据库 win r 运行cmd.exe 输入命令 mysql -uroot -p 敲回车&#xff1b;随后输入密码&#xff1b; -u用户名 -p密码; 1.1 连接远程数据库:mysql -h ip地址 -u 用户名 -p mysql -h 10.10.25.159 -u root -p root-h主机名…

git push 报错 error: src refspec master does not match any 解决

真是TN的邪了门了&#xff0c;今天在Gitee上创建了一个新项目&#xff0c;然后要把本地的代码push上去时&#xff0c;报了如下错误&#xff1a; ➜ *** git:(main) git push -u origin "master" error: src refspec master does not match any error: failed to pu…

Windows上通过CMake编译COLMAP源码操作步骤

COLMAP源码&#xff1a;https://github.com/colmap/colmap &#xff0c;最新的稳定版本位于master分支&#xff0c;最新的开发版本位于dev分支&#xff0c;这里使用master分支进行编译&#xff0c;commit id为1555ff0。官方推荐使用vs2019&#xff0c;使用vs2022有一些已知bugs…

Metasploit介绍

Metasploit介绍 我们经常在电影里看到有关黑客的镜头&#xff0c;他们通常在几个屏幕上一顿操作就能轻松“黑“进各种系统。这样的场景是不是很熟悉&#xff0c;是不是很羡慕&#xff1f; 今天我来介绍一下Metasploit Framework&#xff0c;简称MSF。这个工具就可以做到“Hacki…

Qt5.12.6配置Android Arm开发环境(windows)

1. 安装jdk1.8 2.安装Android Studio 并安装 SDK 与NDK SDK Tools 选择 26.0.3 SDK Platform 选择 Android SDK Platform 26 NDK选择19版本 安卓ARM环境配置成功如下: JDK1.8 , SDK 26 , NDK 19 在安装QT时要选择 ARMv7(32位CPU)与ARM64-v8a(64位CPU) 选择支持android平台…

全国各个省份市区县明细数据

全国总共有23个省、5个自治区、4个直辖市、2个特别行政区。 此数据包含省、市、区、县数据&#xff0c;共2886个。——更新于2023年6月10日 费了不少时间&#xff0c;暂时应该没有比我更全的了~~~细致到区县了 包括台湾省&#xff1a;台北市,新北市,桃园市,台中市,台南市,高…

计算机网络-子网划分

计算机网络-子网划分与CRC差错校验 文章目录 计算机网络-子网划分与CRC差错校验IP地址的分类A类地址B类地址C类地址D类地址和E类地址和特殊IP地址子网掩码实战&#x1f4aa; IP协议是 TCP/IP体系中最主要的协议之一&#xff0c;也是最重要的互联网协议之一。 IP协议是32位&am…

ubuntu22.04.2安装onlyoffice(不更改默认端口版)

目录 一、配置阿里源 二、postgresql数据库 &#xff08;一&#xff09;安装postgresql &#xff08;二&#xff09;创建postgresql数据库和用户 三、安装 rabbitmq 四、安装nginx-extras 五、安装ONLYOFFICE Docs &#xff08;一&#xff09;Add GPG key &#xff08…

【html总结--详细版】

目录 一、html 常用的标签 二、列表分为有序列表、无序列表、自定义列表 有序列表&#xff1a; 无序列表&#xff1a; 自定义列表&#xff1a; 三、hr 四、特殊符号 五、div和span 六、图片的属性 七、超链接 八、table表格的基本结构 table的属性 tr的属性 td的属性…

(七)CSharp-刘铁锰版-事件

一、初步了解事件 定义&#xff1a;单词 Event &#xff0c;译为“事件” 《牛津词典》中的解释是“a thing that happens,especially something important”通顺的解释就是“能够发生的什么事情” 角色&#xff1a; 使对象或类具备通知能力的成员 &#xff08;中译&#x…

数据可视化大屏人员停留系统的开发实录(默认加载条件筛选、单击加载、自动刷新加载、异步加载数据)

项目需求 录入进入房间的相关数据&#xff1b;从进入时间开始计时&#xff0c;计算滞留房间的时间&#xff1b;定时刷新数据&#xff0c;超过30分钟的人数&#xff0c;进行红色告警&#xff1b; 实现流程 为了完整地实现上述需求&#xff0c;我们可以按照以下步骤开发&#…

Log4j2漏洞复现补丁绕过

漏洞复现 这里我一共使用了两个jdk版本 8u202的情况比较特殊&#xff0c;其实我今天凌晨在家里用的也是8u202的版本&#xff0c;失败了。今天来公司也是用的8u202版本的jdk&#xff0c;成功了。我仔细研究了两者的不同&#xff0c;我发现唯一不同的就是我公司这个idea启的proie…

NLP——分布式语义 Distributional Semantics:Word Vectors;Word2Vec

文章目录 传统语义数据集的缺点分布式语义Word Vectors 词向量Count-based 基于统计的方法Document 作为上下文 —— 向量空间模型&#xff08;VSM&#xff09;TF-IDF 更加有效的编码方式降维Singular Value Decomposition neighbor words 作为上下文 基于深度学习的方法Word2V…