【数据结构】一步到胃,键值对版二叉搜索树

Unlocking Decoding-time Controllability: Gradient-FreeMulti-Objective Alignment with Contrastive Pr 将基于庞大网络语料库训练的大型语言模型(LLMs)(OpenAI,2023;Touvron 等,2023;Google,2023)与人类偏好对齐,是减少产生不安全(Wei 等,2023)、幻觉(Zhang 等,2023b)和有偏见(Gallegos 等,2023)内容的重要一步。随着偏好学习技术(如 PPO(Schulman 等,2017)、DPO(Rafailov 等,2023)及其他变体(Azar 等,2023;Ethayarajh 等,2024; 阅读详情

title: 【数据结构】一步到胃,键值对版二叉搜索树
date: 2024-07-27 08:14:12
tags: 数据结构 二叉树 搜索树
cover: https://picbed0521.oss-cn-shanghai.aliyuncs.com/blogpic/202409230835315.png


原文见我的网站: www.supdriver.top

什么是二叉搜索树

二叉搜索树的定义是一颗二叉树的所有节点满足:根的左右孩子存在时,满足 左孩子 < 根 < 右孩子

递归定义则是:

  1. 左子树的根 < 根 < 右子树的根
  2. 左子树是二叉搜索树,右子树是二叉搜索树

写一个验证二叉搜索树的函数

Leetecode题目链接🔗

封装一个二叉树类

文件布置

  • BSTree.h用于声明和实现BSTree类
  • test.cpp用于测试

头文件

BSTree.h

#include <iostream>
#include <utility>

test.cpp

#include "BSTree.h"

命名空间

namespace key_value

这里使用key_value作为命名空间,表示这是键值表示的搜索二叉树

定义节点

二叉树的节点用于储存键值对和左右指针,并提供默认构造函数,使用初始化列表初始化成员变量

template<class K,class V>
class BSTNode
{
public:
    BSTNode(const K& key = K(), const V& value = V())
        :_left(nullptr)
        , _right(nullptr)
        , _key(key)
        , _value(value)
    {}
    BSTNode<K, V>* _left;//指向左子树
    BSTNode<K, V>* _right;//指向右子树
    K _key;//储存键
    V _value;//储存值
};

封装二叉搜索树

Binary Search Tree,这里用简称BSTree封装

基本架构

鉴于该类的接口基本依赖于成员变量,所以先组织好成员变量

作为一颗二叉树类,成员变量仅需一个指向根的指针即可

再次之前先用typedef定义一个节点类出来用于简化代码

最后提供一个默认构造函数将_root初始化为nullptr

	template<class K,class V>
	class BSTree
	{
		typedef BSTNode<K, V> Node;//使用typedef简化代码
	public:
		BSTree() :_root(nullptr) {}//提供默认构造函数
	private:
		Node* _root;//指向根节点的指针作为成员变量
	};

insert函数

准备好后第一个接口就是insert,用于构建搜索二叉树

这里需要考虑的情况有

  • 空树时的插入
  • 插入的key已存在
  • 一般情况下成功的插入
public:
bool insert(const K& key, const V& value)
{
    if (_root == nullptr)//空树
    {
        _root = new Node(key, value);
        return true;
    }

    Node* cur = _root;
    Node* parent = nullptr;
    while (cur)
    {
        if (key < cur->_key)//key比当前节点小,往左子树走
        {
            parent = cur;
            cur = cur->_left;
        }
        else if (key > cur->_key)//往右子树走
        {
            parent = cur;
            cur = cur->_right;
        }
        else
        {
            return false;//key已存在,插入失败
        }
    }
    //此时cur为nullptr, parent为cur的结点
    if (key < parent->_key)parent->_left = new Node(key, value);
    else parent->_right = new Node(key, value);
    return true;//成功插入
}

in_order函数

使用此函数前序遍历打印二叉树来验证其满足搜索树的性质

这里使用递归打印,所以要借助_in_order子函数

public:
    void in_order()
    {
        _in_order(_root);//传入根结点
        std::cout << std::endl;
    }
protected:
    void _in_order(Node* root)
    {
        if (root == nullptr) return;
        _in_order(root->_left);//先访问左结点
        std::cout << root->_value << " " << std::endl;//再访问根结点
        _in_order(root->_right);//最后访问右结点
    }

然后写一段测试代码测试性质

test.cpp

#include "BSTree.h"
#include <vector>
using namespace std;
int main()
{
	vector<int> arr({ 2,3,1,5,4,6,8,7 });//准备待插入的键值对
	key_value::BSTree<int, int> bst;
	for (int i = 0; i < arr.size(); ++i)
	{
		bst.insert(arr[i],arr[i]);//这里使键值相同,方便观察
	}

	bst.in_order();//测试

	return 0;
}

find函数

可以用find函数查找对应key的结点。

同时观察可知,控制cur和parent的移动的代码段和前面的函数很像,所以给find函数分出来一个_find子函数,并使它返回pair<Node*,Node*>,将这两个指针返回利于其它函数对_find的回调

同时为了简化代码,继续用typedef封装类型

public:
    typedef std::pair< Node*, Node* > PNN;//简化代码
    bool find(const K& key)
    {
        return _find(key).first != nullptr;//检查是否找到
    }
protected:

    PNN _find(const K& key)//返回PNN用于简化其它接口
    {
        if (_root == nullptr) return {nullptr,nullptr};
        Node* cur = _root;
        Node* parent = nullptr;
        while (cur)
        {
            if (key < cur->_key)//key比当前节点小,往左子树走
            {
                parent = cur;
                cur = cur->_left;
            }
            else if (key > cur->_key)//往右子树走
            {
                parent = cur;
                cur = cur->_right;
            }
            else
            {
                //找到key
                return { cur,parent };
            }
        }
        //没找到key,cur为nullptr
        return { nullptr,parent };
    }
重写insert函数
    bool insert(const K& key, const V& value)
    {
        if (_root == nullptr)//空树
        {
            _root = new Node(key, value);
            return true;
        }
        //====修改的部分====
        PNN pnn = _find(key);

        Node* cur = pnn.first;
        Node* parent = pnn.second;

        if (cur != nullptr)//该key已存在,插入失败
        {
            return false;
        }
        //================
        
        //此时cur为nullptr, parent为cur的结点
        if (key < parent->_key)parent->_left = new Node(key, value);
        else parent->_right = new Node(key, value);
        return true;//成功插入
    }

erase函数

这里也可以复用_find来方便地删除结点

这里要考虑的情况有:

  • 树为空
  • 删除最后一个结点
  • 删除根节点
  • 左子树为空(包括叶子结点)
  • 右子树为空
  • 删除一般的结点

当树有>=2个结点,且要删除非叶子结点时,要考虑结点替换,否则二叉树会断掉,这里一般两种策略,取左子树的最右结点(最大结点),或取右子树的最左结点(最小结点)

public:
    bool erase(const K& key)
    {
        if (_root == nullptr)return false;//空树无法删除
        if (_root->_key == key && _root->_left == nullptr && _root->_right == nullptr)//删除最后一个结点
        {
            delete _root;
            _root = nullptr;
        }
        PNN pnn = _find(key);
        Node* cur = pnn.first;
        Node* parent = pnn.second;
        if (cur == nullptr) return false;//没找到该结点

        //下面的cur必不为空
        if(cur->_left == nullptr)
        {
            if (cur == _root)//为根节点时要替换根节点
            {
                Node* right = _root->_right;
                delete _root;
                _root = right;
            }
            //没有左子树,则直接移除结点,右子树替代原结点
            if (cur == parent->_left) parent->_left = cur->_right;
            else parent->_right = cur->_right;
            delete cur;
        }
        else if (cur->_right == nullptr)
        {
            if (cur == _root)
            {
                Node* left = _root->_left;
                delete _root;
                _root = left;
            }
            //直接过继左子树
            if (cur == parent->_left)parent->_left = cur->_left;
            else parent->_right = cur->_left;
        }
        else 
        {
            //找到左子树的最右结点
            Node* _cur = cur->_left;
            Node* _parent = cur;
            while (_cur->_right != nullptr)
            {
                _parent = _cur;
                _cur = _cur->_right;
            }
            //移走结点
            if (_cur == _parent->_left) _parent->_left = nullptr;
            else _parent->_right = nullptr;
            //获取cur的左右结点,必须再移走结点后,否则可能出现指向自己的结点
            _cur->_left = cur->_left;
            _cur->_right = cur->_right;
            //代替cur的位置
            if (cur == _root)//删除根结点时
            {
                delete _root;
                _root = _cur;
            }
            else//删除普通结点时
            {
                if (cur == parent->_left) parent->_left = _cur;
                else parent->_right = _cur;
                delete cur;
            }

        }
        return true;
    }

拷贝构造

利用二叉树的性质,可以再构建个copy子函数来递归拷贝

public:
    BSTree(const BSTree<K>& t)
    {
        _root = Copy(t._root);
    }
protected:
    Node* copy(Node* root)
    {
        if (root == nullptr) return nullptr;//递归出口
        Node* pnode = new Node(root->_key, root->_value);//复制结点
        pnode->_left = copy(root->_left);
        pnode->_right = copy(root->_right);
        return pnode;
    }

析构函数

这里也用destroy子函数来递归地后序遍历依次删除各个结点

public:
    ~BSTree()
    {
        destroy(_root);
    }
protected:
    void destroy(Node* root)
    {
        if (root == nullptr) return;
        destroy(root->_left);
        destroy(root->_right);
        delete root;
    }

至此,一个基本的二叉搜索树已封装完成

实现的功能有

  • 构建二叉搜索树
  • 拷贝复制二叉树
  • 按key值查找
  • 按key值删除

完整代码

#pragma once
#include <iostream>
#include <utility>

namespace key_value
{
	template<class K,class V>
	class BSTNode
	{
	public:
		BSTNode(const K& key = K(), const V& value = V())
			:_left(nullptr)
			, _right(nullptr)
			, _key(key)
			, _value(value)
		{}
		BSTNode<K, V>* _left;//指向左子树
		BSTNode<K, V>* _right;//指向右子树
		K _key;//储存键
		V _value;//储存值
	};

	template<class K,class V>
	class BSTree
	{
		typedef BSTNode<K, V> Node;//使用typedef简化代码
	public:
		BSTree() :_root(nullptr) {}//提供默认构造函数

		BSTree(const BSTree<K, V>& bst)
		{
			_root = copy(bst._root);
		}

		~BSTree()
		{
			destroy(_root);
		}

		bool insert(const K& key, const V& value)
		{
			if (_root == nullptr)//空树
			{
				_root = new Node(key, value);
				return true;
			}
			//====修改的部分====
			PNN pnn = _find(key);

			Node* cur = pnn.first;
			Node* parent = pnn.second;

			if (cur != nullptr)//该key已存在,插入失败
			{
				return false;
			}
			//================
			
			//此时cur为nullptr, parent为cur的结点
			if (key < parent->_key)parent->_left = new Node(key, value);
			else parent->_right = new Node(key, value);
			return true;//成功插入
		}

		void in_order()
		{
			_in_order(_root);//传入根结点
			std::cout << std::endl;
		}
	protected:
		void _in_order(Node* root)
		{
			if (root == nullptr) return;
			_in_order(root->_left);//先访问左结点
			std::cout << root->_value << " ";//再访问根结点
			_in_order(root->_right);//最后访问右结点
		}


	public:
		typedef std::pair< Node*, Node* > PNN;//简化代码
		bool find(const K& key)
		{
			return _find(key).first != nullptr;//检查是否找到
		}
	protected:
	
		PNN _find(const K& key)//返回PNN用于简化其它接口
		{
			if (_root == nullptr) return {nullptr,nullptr};
			Node* cur = _root;
			Node* parent = nullptr;
			while (cur)
			{
				if (key < cur->_key)//key比当前节点小,往左子树走
				{
					parent = cur;
					cur = cur->_left;
				}
				else if (key > cur->_key)//往右子树走
				{
					parent = cur;
					cur = cur->_right;
				}
				else
				{
					//找到key
					return { cur,parent };
				}
			}
			//没找到key,cur为nullptr
			return { nullptr,parent };
		}
	public:

		bool erase(const K& key)
		{
			if (_root == nullptr)return false;//空树无法删除
			if (_root->_key == key && _root->_left == nullptr && _root->_right == nullptr)//删除最后一个结点
			{
				delete _root;
				_root = nullptr;
			}
			PNN pnn = _find(key);
			Node* cur = pnn.first;
			Node* parent = pnn.second;
			if (cur == nullptr) return false;//没找到该结点

			//下面的cur必不为空
			if(cur->_left == nullptr)
			{
				if (cur == _root)//为根节点时要替换根节点
				{
					Node* right = _root->_right;
					delete _root;
					_root = right;
				}
				//没有左子树,则直接移除结点,右子树替代原结点
				if (cur == parent->_left) parent->_left = cur->_right;
				else parent->_right = cur->_right;
				delete cur;
			}
			else if (cur->_right == nullptr)
			{
				if (cur == _root)
				{
					Node* left = _root->_left;
					delete _root;
					_root = left;
				}
				//直接过继左子树
				if (cur == parent->_left)parent->_left = cur->_left;
				else parent->_right = cur->_left;
			}
			else 
			{
				//找到左子树的最右结点
				Node* _cur = cur->_left;
				Node* _parent = cur;
				while (_cur->_right != nullptr)
				{
					_parent = _cur;
					_cur = _cur->_right;
				}
				//移走结点
				if (_cur == _parent->_left) _parent->_left = nullptr;
				else _parent->_right = nullptr;
				//获取cur的左右结点,必须再移走结点后,否则可能出现指向自己的结点
				_cur->_left = cur->_left;
				_cur->_right = cur->_right;
				//代替cur的位置
				if (cur == _root)//删除根结点时
				{
					delete _root;
					_root = _cur;
				}
				else//删除普通结点时
				{
					if (cur == parent->_left) parent->_left = _cur;
					else parent->_right = _cur;
					delete cur;
				}

			}
			return true;
		}


	protected:
		Node* copy(Node* root)
		{
			if (root == nullptr) return nullptr;//递归出口
			Node* pnode = new Node(root->_key, root->_value);//复制结点
			pnode->_left = copy(root->_left);
			pnode->_right = copy(root->_right);
			return pnode;
		}

		void destroy(Node* root)
		{
			if (root == nullptr) return;
			destroy(root->_left);
			destroy(root->_right);
			delete root;
		}
	private:
		Node* _root;//指向根节点的指针作为成员变量
	};
}

相关推荐

PX4实战指南:通过遥控器通道直连实现舵机PWM控制

本文详细介绍了如何通过PX4飞控实现遥控器通道直连控制舵机PWM输出的完整流程。从硬件准备、遥控器配对到PX4参数配置和硬件连接,提供了实战技巧和常见问题解决方案,帮助无人机爱好者快速掌握舵机控制技术。重点讲解了AUX Passthrough模式设置和PWM参数调整等关键步骤。

weixin_29195217的博客 153

C++之二叉搜索树

在本节中,我们来介绍数据结构中一种特殊的二叉树——搜索二叉树。BST的key-only和key-value版本分别适用于不同的场景。选择时需根据具体需求,权衡功能和性能。key-only适合简单的集合操作,而key-value适合需要存储和检索关联值的场景。

H2X7_的博客 833

MEG预处理-Brainstorm

Brainstorm下载和安装 去Brainstorm官网进行下载:打开网页后,点击左侧Download;在跳出来的界面中进行简单的注册,注册完成后可以进行下载 解压后得到“brainstorm3”的文件夹,里面包含Brainstorm工具包的所有文件,把这个文件夹放在某个路径如"E:\matlab_tools\brainstorm3"即可 同样在某个路径建立空的文件夹命名为:brainstorm_db用于工具包运行过程中自动存储生成的文件,所以这个文件中生成的数据不要手动移动删除 在Matlab中,把.

AxeChen的博客 6119

C++数据结构之二叉搜索树

本文系统介绍了二叉搜索树(BST)的概念、特性和实现。二叉搜索树是一种有序数据结构,具有左子树值≤根节点值≤右子树值的特性,其中序遍历会得到有序序列。文章详细阐述了BST的插入、查找和删除操作,指出其时间复杂度在最优情况为O(logN),最差退化为O(N)。接着介绍了两种应用场景:key模型(如停车场系统)和key/value模型(如字典),并分别给出了C++实现代码。最后指出普通BST的性能局限,为后续介绍AVL树和红黑树等平衡二叉搜索树做铺垫。

2301_79976271的博客 642

YOLOV8多模态(可见光+红外光目标检测任务,基于Ultralytics官方代码实现)

torch 2.3.1 torchvision 0.18.1 Python 3.8.19 tensorrt 8.5.3.1DroneVehicle数据集下载地址DroneVehicle 数据集由无人机采集的 56,878 张图像组成,其中一半是 RGB 图像,其余是红外图像。我们为这 5 个类别制作了丰富的注释,其中包含定向边界框。其中,汽车在 RGB 图像中有 389,779 个注释,在

Mjy的博客 7584

信号削峰CFR基础知识介绍(一)

接下来,将得到的峰值分成若干段,在每一段中,仅保留该段内所有峰值中幅度最大的峰值。为了减少不必要的带外泄露,削峰后的信号将通过一个低通滤波器,以减少对应于削峰后信号中尖锐拐角的高频信号。首先,它识别出高于由目标PAPR确定的阈值的峰值。在峰值加窗算法中,削峰是通过在峰值区域将原始信号与一个加窗函数相乘来实现的,如下图所示。其中,w(n) 是一种常见的加窗函数,如凯撒窗、高斯窗和汉明窗等,而 p(n) 是一个加权系数。如上图所示,削峰会导致削峰后的信号出现尖锐的拐角,从而引发不必要的带外辐射(ACP增加)。

weixin_49761275的博客 1549

C++ 浅谈之二叉搜索树

C++ 二叉搜索树

优质后端技术知识记录 674

静态时序分析(STA)—— 标准单元库

目录 1、时序库 概览 2、时序模型 1、基本概念 2、影响因素 3、线性延时模型 4、非线性延时模型 5、单元时序弧 1、组合逻辑单元 2、时序逻辑单元 6、线负载模型 参考说明 上一篇,学习了 STA相关的基本概念,本篇继续学习 STA相关的 标准单元库。 1、时序库 概览 库文件概览: 2、时序模型 1、基本概念 2、影响因素 对于组合逻辑的时序弧而言,其延时的大小取决于: 1、输出负载,即,输出端的电容负载的大小。容性负载越大,...

记录所学,分享知识,结识挚友 2852

数据结构Java版Map&Set&搜索树

目录 1.搜索 1.1概念及场景 1.2模型 2.Map 的使用 2.1 关于Map的说明 2.2 关于Map.Entry的说明,> 2.3 Map 的常用方法说明 3. Set 的说明 3.1常见方法说明 4.搜索树 4.1概念 4.2搜索树的查找 4.3搜索树的插入 4.4搜索树的删除 1.搜索 1.1概念及场景 ①Map和Set的作用: 一种专门用来进行搜索的容器或者数据结构,其搜索的效率与其具体的实例化子类有关。 ②Map和Set相比于其他类型的优

weixin_58850105的博客 820

微信小程序启用蓝牙设备特征值变化时的notify功能

注意:这里的serviceUUID、notifyCharacteristicUUID 我会在后面写入数据时做重点说明。isNotifyBLECharacteristic:false, //是否启用蓝牙设备服务特征 notify。二、启用蓝牙设备特征值变化时的notify功能。下一篇 将继续介绍 微信小程序蓝牙设备写入数据。

wsk198726的专栏 1172

cesium 综合教程200+【目录】(已包含186篇文章)

cesium示例教程100+旨在为开发者提供简单快捷的,。在每一个示例中,解释相应的API知识点,做到。目录中有链接的为已有文章,没链接的为目标文章,不断更新中…

大剑师兰特的GIS世界 8890

【数据结构】二叉搜索树(二叉排序树)

二叉搜索树(Binary Search Tree),也叫二叉排序树或者二叉查找树, 是一种特殊的二叉树结构。它或者是一棵空树,或者具有以下特点:1. 如果根节点的左子树不为空,则左子树上的所有节点都小于等于根节点的值。2. 如果根节点的右子树不为空,则右子树上的所有节点都大于等于根节点的值。3. 它的每一棵子树也都符合前两点特性(每棵子树也都是二叉搜索树)。简单地说,二叉搜索树是一棵中序遍历结果有序的二叉树。一般情况下,二叉搜索树不允许有相同的值出现。

2301_80955819的博客 2366

【第13话:感知算法】库位与可行驶区域检测:自主泊车场景中的检测及语义分割方法

本文提出了一种自动泊车系统中的泊车库位线检测方法,通过逆透视映射(IPM)将车辆摄像头图像转换为鸟瞰视图,消除透视变形。该方法结合目标检测和语义分割模型,先定位库位线候选区域,再生成像素级精确掩码。后处理步骤将掩码转换为结构化输出,包括停车位边界多边形和可行驶区域掩码。整个流程采用深度学习模型和计算机视觉技术,可实现高精度的泊车环境感知,为自动泊车系统提供可靠支持。

一碗白开水一 1160

【数据结构】二叉搜索树底层刨析

之前我们对二叉搜索树进行了初步的认识,本文将对二叉搜索树的底层进行研究。

在这个博客里,我会分享我的技术见解、项目经验和学习笔记,感谢各位支持~ 2310

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

python数据结构 树_用Python实现数据结构之二叉搜索树

二叉搜索树二叉搜索树是一种特殊的二叉树,它的特点是:对于任意一个节点p,存储在p的左子树的中的所有节点中的值都小于p中的值对于任意一个节点p,存储在p的右子树的中的所有节点中的值都大于p中的值一个图例:基于二叉搜索树的这种关系,我们可以用它来实现有序映射遍历二叉搜索树基于二叉搜索树的特性,采用中序遍历的方式可以使得遍历结果是按照从小到大的顺序排列的。了解中序遍历可以参考用Python实现数据结构之...

weixin_39586649的博客 295

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

数据结构之二叉搜索树(BinarySearchTree)

一。定义:二叉搜索树(Binary Search Tree),也称有序二叉树(ordered binary tree),排序二叉树(sorted binary tree),是指一棵空树或者具有下列性质的二叉树: 1. 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 2. 若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 3. 任意节点的左

如风 741

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

数据结构与算法——二叉搜索树,使用TreeMap将键值对存储在一棵二叉搜索树的节点

二叉搜索树,使用TreeMap将键值对存储在一棵二叉搜索树的节点,实现增删查改操作。插入或更新键值对、获取键对应的值、检查是否包含键、返回所有键的有序集合、找到最小/最大键、找到小于等于key的最大键/大于等于key的最小键、区间查询

m0_74556076的博客 464

C++数据结构 : 二叉搜索树

二叉搜索树(BST)是一种高效的数据结构,通过有序的树形存储实现快速查找、插入和删除操作。其核心特性是:左子节点的值 ≤ 当前节点值 ≤ 右子节点的值。 本文将详解BST的原理、实现及应用,包括基础操作、性能分析,以及`key`和`key/value`两种模式的代码实现,帮助你在实际开发中灵活运用这一结构。

m0_74951730的博客 1113

请回答数据结构【二叉搜索树】

请回答数据结构【二叉搜索树】1. BinarySearchTree(二叉排序树)1.0 Intro1.1 concept2. 二叉搜索树快速入门2.1 查找2.2 BSTree应用3. 实现二叉搜索树3.0 搜索二叉树节点3.1 Insert3.2 InOder3.3 Find3.4 Erase3.4.1 抽丝剥茧3.4.2 **躬行实践**3.4.3 化茧成蝶3.4.4 精益求精4. 递归版搜索二叉树4.1 _FindR4.2 InsertR4.3 EraseR5. 深浅拷贝5.1 析构函数5.2 拷贝.

Allen9012的博客 851

【Java数据结构】---Map和Set(二叉搜索树)

在正式谈到Map之前,我们需要对搜索有一个细致明确的认知,以达到我们对Map学习的基础。

optimistic_chen的博客 1206

【数据结构】二叉搜索树的代码实现(C++)

前言 普通的二叉树的增删查改是没有任何意义的; 所以当我们给树加以一些规则他就会发挥很大的作用; 二叉搜索树的概念 二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树: 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值; 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值; 它的左右子树也分别为二叉搜索树; 默认情况下二叉树排序树的数据是不可以有冗余的,相同的数据是不可以再二叉搜索树里; 比如这颗二叉搜索树: 二叉搜索树,又叫搜索二叉树,也叫二叉排序树

呋喃吖的博客 3301

数据结构之进阶二叉树(二叉搜索树和AVL树、红黑树的实现)超详细解析,附实操图和搜索二叉树的实现过程图

二叉搜索树和AVL树、红黑树的实现

溟洵的博客 4109

【数据结构】Java中Map和Set详解(含二叉搜索树和哈希表)

在Java中Map和Set最常见到下面四个实现类,HashMap/TreeMap/HashSet/TreeSet,他们分别与两种数据结构相关,二叉搜索树和哈希表,下面的文章中我会详解这两种数据结构,以及Java是怎样对这两种数据结构进行实现的。

2203_75565612的博客 1501

数据结构-搜索树

二叉搜索树 能够有效地实现有序映射。 二叉搜索树是每个节点p存储一个键值对(k,v)的二叉树,使得: 1.存储在p的左子树的键都小于k; 2.存储在p的右子树的键都大于k。 遍历二叉搜索树 二叉搜索树中关于键的位置的结构特性使得树的遍历是中序遍历。 命题:二叉搜索树的中序遍历是按照键增加的顺序进行的。 除了树本身提供的方法,二叉搜索树还支持一下方法: 操作 作用 first() 返回一个包含最小键的节点,若树为空,则返回None last() 返回一个包含最大键的节点,若树为空,则返回N

weixin_46365033的博客 724

【数据结构】搜索树 与 Java集合框架中的Set,Map

搜索效率杠杠的搜索树与Set和Map~

做梦都想要三十万年薪~ 1896

【数据结构】二叉搜索树

二叉搜索树

qq_66314292的博客 1392
上一篇: Linux文件系统
下一篇: Linux原生线程 与 互斥锁
supdriver
博客等级 码龄3年 192粉丝 40原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值