数据结构和算法(5):二叉树

向量允许通过下标或秩,在常数的时间内找到目标对象;然而,一旦需要对这类结构进行修改,那么无论是插入还是删除,都需要耗费线性的时间。
列表允许借助引用或位置对象,在常数的时间内插入或删除元素;但是为了找出居于特定次序的元素,却不得不花费线性的时间,对整个结构进行遍历查找。
树将二者优势结合起来,可以视为 List<List> 或者 List^2

从图论的角度看,树等价于连通无环图。因此与一般的图相同,树也由一组顶点以及联接与其间的若干条边组成。在计算机科学中,往往还会在此基础上,再指定某一特定顶点,并称之为。在指定根节点之后,也称之为有根树。此时,从程序实现的角度,更多地将顶点称作节点

节点之间均有路径,称作连通团
不含环路,称作无环图

任一节点与根之间存在唯一路径。

沿每个节点 v 到根 r 的唯一通路所经过边的数目,称作 v深度。约定根节点的深度depth(r) = 0,故属于第 0 层。
在这里插入图片描述
任一节点v在通往树根沿途所经过的每个节点都是其祖先v是它们的后代。特别地,v 的祖先/后代包括其本身,而 v 本身以外的祖先/后代称作真祖先/真后代。
节点v历代祖先的层次,自下而上以1为单位逐层递减;在每一层次上,v的祖先至多一个。特别地,若节点uv的祖先且恰好比v高出一层,则称uv的父亲,vu的孩子。
v的孩子总数,称作其度数,记作deg(v)。无孩子的节点称作叶节点,包括根在内的其余节点皆为内部节点。
v所有的后代及其之间的联边称作子树,记作subtree(v)。在不致歧义时,往往不再严格区分节点(v)及以之为根的子树(subtree(v))。

T中所有节点深度的最大值称作该树的高度,记作height(T)树的高度总是由其中某一叶节点的深度确定的。
任一节点v所对应子树subtree(v)的高度,亦称作该节点的高度,记作height(v)。特别地,全树的高度亦即其根节点r的高度,height(T) = height(r)

术语:
根节点(Root): 树的顶部节点,没有父节点,是树的起点。
子节点(Child): 根节点下面的节点,每个子节点都有一个父节点。
父节点(Parent): 每个节点都有一个父节点,除了根节点。
叶子节点(Leaf): 没有子节点的节点称为叶子节点。
内部节点(Internal Node): 有子节点的节点称为内部节点。
边(Edge): 连接节点的线段。
路径(Path): 从一个节点到另一个节点的连续边构成的序列。
层级(Level): 根节点位于第一层,每个子节点的层级比其父节点高一层。
高度(Height): 树的高度是树中任何节点到其最远叶子节点的最长路径的长度。
子树(Subtree): 子树是树中的一部分,它本身也是一棵树,包括一个节点以及其所有后代节点。

表示

节点功能
root()根节点
parent()父节点
firstChild()长子
nextSibling()兄弟
insert(i,e)e 作为第 i 个孩子插入
remove(i)删除第 i 个孩子(及其后代)
traverse()遍历

在这里插入图片描述

树的长子兄弟表示法(Child-Sibling Representation)是一种用于表示树结构的方法,也称为左子右兄弟表示法(Left Child Right Sibling Representation)。这种表示法的主要思想是通过两个指针来表示每个节点的孩子和兄弟关系,从而构建树结构。

在长子兄弟表示法中,每个节点有两个指针:

长子指针(Child Pointer): 指向该节点的最左边的孩子节点。
兄弟指针(Sibling Pointer): 指向该节点的右兄弟节点。

使用长子兄弟表示法,可以有效地表示一棵多叉树,其中每个节点可以有任意数量的孩子节点。这种表示法的一个优点是它可以节省内存空间,因为每个节点只需要两个指针。

二叉树

二叉树(Binary Tree): 每个节点最多有两个子节点的树。
深度为 k k k 的节点,至多 2 k 2^k 2k 个。
n n n 个节点、高度为 h h h 的二叉树中 h < n < 2 n + 1 h<n<2^{n+1} h<n<2n+1
1) n = h + 1 n = h+1 n=h+1时,退化成一条单链;
2) n = 2 h + 1 − 1 n = 2^{h+1} -1 n=2h+11时,即所谓满二叉树

描述多叉树:二叉树是多叉树的特例,但在有根且有序时,其描述能力却足以覆盖后者。

实现

BinNode 模板类

template <typename T> struct BinNode;
template <typename T> using BinNodePosi = BinNode<T>*; //节点位置template <typename T> struct BinNode { //二叉树节点模板类
// 成员(为简化描述起见统一开放,读者可根据需要进一步封装)T data; //数值BinNodePosi<T> parent, lc, rc; //父节点及左、右孩子Rank height; //高度(通用)Rank npl; //Null Path Length(左式堆,也可直接用height代替)RBColor color; //颜色(红黑树)
// 构造函数BinNode() : parent(NULL), lc(NULL), rc(NULL), height(0), npl(1), color(RB_RED) {}BinNode(T e, BinNodePosi<T> p = NULL, BinNodePosi<T> lc = NULL,BinNodePosi<T> rc = NULL, int h = 0, int l = 1, RBColor c = RB_RED): data(e), parent(p), lc(lc), rc(rc), height(h), npl(l), color(c) {}// 操作接口Rank size(); //统计当前节点后代总数,亦即以其为根的子树的规模BinNodePosi<T> insertAsLC(T const&); //作为当前节点的左孩子插入新节点BinNodePosi<T> insertAsRC(T const&); //作为当前节点的右孩子插入新节点BinNodePosi<T> succ(); //取当前节点的直接后继template <typename VST> void travLevel(VST&); //子树层次遍历template <typename VST> void travPre(VST&); //子树先序遍历template <typename VST> void travIn(VST&); //子树中序遍历template <typename VST> void travPost(VST&); //子树后序遍历
// 比较器、判等器(各列其一,其余自行补充)bool operator< (BinNode const& bn) { return data < bn.data; } //小于bool operator== (BinNode const& bn) { return data == bn.data; } //等于
};

BinNode 接口

template <typename T> BinNodePosi<T> BinNode<T>::insertAsLC( T const& e ){ return lc = new BinNode( e, this ); } //将e作为当前节点的左孩子插入二叉树template <typename T> BinNodePosi<T> BinNode<T>::insertAsRC( T const& e ){ return rc = new BinNode( e, this ); } //将e作为当前节点的右孩子插入二叉树template <typename T> Rank BinNode<T>::size() { //统计当前节点后代总数,即以其为根的子树规模Rank s = 1; //计入本身if ( lc ) s += lc->size(); //递归计入左子树规模if ( rc ) s += rc->size(); //递归计入右子树规模return s;
}

孩子接入都可以在 O ( 1 ) \mathcal O(1) O(1)时间内完成,而获取 size() 需要遍历,因此需要时间为 O ( n ) \mathcal O(n) O(n)

BinTree 模板类

#include "BinNode.h" //引入二叉树节点类
template <typename T> class BinTree { //二叉树模板类
protected:Rank _size; BinNodePosi<T> _root; //规模、根节点virtual Rank updateHeight(BinNodePosi<T> x); //更新节点x的高度void updateHeightAbove(BinNodePosi<T> x); //更新节点x及其祖先的高度
public:BinTree() : _size(0), _root(NULL) {} //构造函数~BinTree() { if (0 < _size) remove(_root); } //析构函数Rank size() const { return _size; } //规模bool empty() const { return !_root; } //判空BinNodePosi<T> root() const { return _root; } //树根BinNodePosi<T> insert(T const&); //插入根节点BinNodePosi<T> insert(T const&, BinNodePosi<T>); //插入左孩子BinNodePosi<T> insert(BinNodePosi<T>, T const&); //插入右孩子BinNodePosi<T> attach(BinTree<T>*&, BinNodePosi<T>); //接入左子树BinNodePosi<T> attach(BinNodePosi<T>, BinTree<T>*&); //接入右子树Rank remove(BinNodePosi<T>); //子树删除BinTree<T>* secede(BinNodePosi<T>); //子树分离template < typename VST> //操作器void travLevel(VST & visit) { if (_root) _root->travLevel(visit); } //层次遍历template < typename VST> //操作器void travPre(VST & visit) { if (_root) _root->travPre(visit); } //先序遍历template < typename VST> //操作器void travIn(VST & visit) { if (_root) _root->travIn(visit); } //中序遍历template < typename VST> //操作器void travPost(VST & visit) { if (_root) _root->travPost(visit); } //后序遍历bool operator<(BinTree<T> const& t) //比较器(其余自行补充){ return _root && t._root && lt(_root, t._root); }bool operator==(BinTree<T> const& t) //判等器{ return _root && t._root && (_root == t._root); }
}; //BinTree

高度更新

二叉树任一节点的高度,都等于其孩子节点的最大高度加一。

节点自身很难发现后代的变化,因此采用另一处理策略:一旦有节点加入或离开二叉树,则更新其所有祖先的高度

在每一节点v处,只需读出其左、右孩子的高度并取二者之间的大者,再计入当前节点本身,就得到了v的新高度。通常,接下来还需要从v出发沿parent指针逆行向上,依次更新各代祖先的高度记录。

template <typename T> Rank BinTree<T>::updateHeight( BinNodePosi<T> x ) //更新节点x高度{ return x->height = 1 + max( stature( x->lc ), stature( x->rc ) ); } //具体规则,因树而异template <typename T> void BinTree<T>::updateHeightAbove( BinNodePosi<T> x ) //更新高度{ while ( x ) { updateHeight( x ); x = x->parent; } } //从x出发,覆盖历代祖先。可优化

更新每一节点本身的高度,只需执行两次getHeight()操作、两次加法以及两次取最大操作,不过常数时间,故updateHeight()算法总体运行时间也是O(depth(v) + 1),其中depth(v)为节点v的深度。

节点插入

template <typename T> BinNodePosi<T> BinTree<T>::insert( T const& e ){ _size = 1; return _root = new BinNode<T>( e ); } //将e当作根节点插入空的二叉树template <typename T> BinNodePosi<T> BinTree<T>::insert( T const& e, BinNodePosi<T> x ){ _size++; x->insertAsLC( e ); updateHeightAbove( x ); return x->lc; } // e插入为x的左孩子template <typename T> BinNodePosi<T> BinTree<T>::insert( BinNodePosi<T> x, T const& e ){ _size++; x->insertAsRC( e ); updateHeightAbove( x ); return x->rc; } // e插入为x的右孩子

若二叉树T中某节点x的右孩子为空,则可为其添加一个右孩子。可调用x->insertAsRC()接口,将二者按照父子关系相互联接,同时通 过updateHeightAbove()接口更新x所有祖先的高度,并更新全树规模。左侧节点的插入过程与此相仿,可对称地调用insertAsLC()完成。

先序遍历

遍历: 按照某种次序访问树中各节点,每个节点被访问恰好一次。
在这里插入图片描述

二叉树遍历的全局次序由局部次序规则确定。
按惯例左孩子优先于右孩子,故若将节点及其孩子分别记作V、L和R,则如图所示,局部访问的次序有VLR、LVR和LRV三种选择。根据节点V在其中的访问次序,这三种策略也相应地分别称作先序遍历、中序遍历和后序遍历。

template <typename T, typename VST> //元素类型、操作器
void travPre_R ( BinNodePosi(T) x, VST& visit ) { //二叉树先序遍历算法(逑弻版)if ( !x ) return;visit ( x->data );travPre_R ( x->lc, visit );travPre_R ( x->rc, visit );
}//T(n)=O(n)

在这里插入图片描述

迭代实现(1)

使用辅助栈的特性实现

template <typename T, typename VST> //元素类型、操作器
void travPre_I1( BinNodePosi<T> x, VST& visit ) { //二叉树先序遍历算法(迭代版#1)Stack<BinNodePosi<T>> S; //辅助栈if ( x ) S.push( x ); //根节点入栈while ( !S.empty() ) { //在栈变空之前反复循环x = S.pop(); visit( x->data ); //弹出并访问当前节点,其非空孩子的入栈次序为先右后左if ( HasRChild( *x ) ) S.push( x->rc );//右孩子先入后出if ( HasLChild( *x ) ) S.push( x->lc );//左孩子后入先出}
}

迭代实现(2)

//从当前节点出发,沿左分支不断深入,直至没有左分支的节点;沿途节点遇到后立即访问
template<typename T,typename VST>	//分摊O(1)
static void visitAlongLeftBranch(BinNodePosi(T) x,VST & visit,Stack<BinNodePosi(T)>& S){while(x){	//反复地visit(x->data);	//访问当前节点S.push(x->rChild);	//右孩子(右子树)入栈(将来逆序出栈)x=x->lChild;	//沿左侧链下行}	//只有右孩子,NULL可能入栈
}

在这里插入图片描述
先序遍历序列可分解为两段:沿最左侧通路自顶而下访问的各节点,以及自底而上遍历的对应右子树。

template <typename T, typename VST> //元素类型、操作器
void travPre_I2 ( BinNodePosi(T) x, VST& visit ) { //二叉树先序遍历算法(迭代版#2)Stack<BinNodePosi(T)> S; //辅助栈while ( true ) {visitAlongLeftBranch ( x, visit, S ); //从当前节点出发,逐批讵问if ( S.empty() ) break; //直到栈空x = S.pop(); //弹出下一批的起点}
}

使用了一个辅助栈,逆序记录最左侧通路上的节点,以便确定其对应右子树自底而上的遍历次序

中序遍历

在这里插入图片描述
按照中序遍历规则,为遍历非空的(子)树x,将依次递归遍历其左子树、访问节点x、递归遍历其右子树

template <typename T, typename VST> //元素类型、操作器void travIn_R ( BinNodePosi(T) x, VST& visit ) { //二叉树中序遍历算法(递归版)if ( !x ) return;travIn_R ( x->lc, visit );visit ( x->data );travIn_R ( x->rc, visit );
}//O(n)

在这里插入图片描述
从根出发沿左分支下行,直至最深的节点

template <typename T> //从当前节点出发,沿左分支不断深入,直至没有左分支的节点
static void goAlongLeftBranch ( BinNodePosi(T) x, Stack<BinNodePosi(T)>& S ) {while ( x ) { S.push ( x ); x = x->lc; } //当前节点入栈后随即向左侧分支深入,迭代直到无左孩子
}template <typename T, typename VST> //元素类型、操作器
void travIn_I1 ( BinNodePosi(T) x, VST& visit ) { //二叉树中序遍历算法(迭代版#1)Stack<BinNodePosi(T)> S; //辅助栈while ( true ) {goAlongLeftBranch ( x, S ); //从当前节点出发,逐批入栈if ( S.empty() ) break; //直至所有节点处理完毕x = S.pop(); visit ( x->data ); //弹出栈顶节点并访问之x = x->rc; //转向右子树(可能为空)}
}

在全树及其中每一棵子树的根节点处,该算法首先调用函数goAlongLeftBranch(),沿最左侧通路自顶而下抵达末端节点 L d L_d Ld 。在此过程中,利用辅助栈逆序地记录和保存沿途经过的各个节点,以便确定自底而上各段遍历子序列最终在宏观上的拼接次序。

后序遍历

在这里插入图片描述
与先序与中序遍历类似地,自底而上地沿着该通路,整个后序遍历序列也可分解为若干个片段。每一片段,分别起始于通路上的一个节点,并包括三步:访问当前节点,遍历以其右兄弟(若存在)为根的子树,以及向上回溯至其父节点(若存在)并转入下一片段

template <typename T, typename VST> //元素类型、操作器
void travPost_R ( BinNodePosi(T) x, VST& visit ) { //二叉树后序遍历算法(逑弻版)if ( !x ) return;travPost_R ( x->lc, visit );travPost_R ( x->rc, visit );visit ( x->data );
}

在这里插入图片描述

template <typename T> //在以S栈顶节点为根的子树中,找到最高左侧可见叶节点
static void gotoHLVFL ( Stack<BinNodePosi(T)>& S ) { //沿途所遇节点依次入栈while ( BinNodePosi(T) x = S.top() ) //自顶而下,反复检查当前节点(即栈顶)if ( HasLChild ( *x ) ) { //尽可能向左if ( HasRChild ( *x ) ) S.push ( x->rc ); //若有右孩子,优先入栈S.push ( x->lc ); //然后才转至左孩子} else //实不得已S.push ( x->rc ); //才向右S.pop(); //迒回乀前,弹出栈顶癿空节点
}template <typename T, typename VST>
void travPost_I ( BinNodePosi(T) x, VST& visit ) { //二叉树的后序遍历(迭代版)Stack<BinNodePosi(T)> S; //辅助栈if ( x ) S.push ( x ); //根节点入栈while ( !S.empty() ) {if ( S.top() != x->parent ) //若栈顶非当前节点之父(则必为其右兄),此时需gotoHLVFL ( S ); //在以其右兄为根的子树中,找刡HLVFL(相当于递归深入其中)
x = S.pop(); visit ( x->data ); //弹出栈顶(即前一节点之后继),并访问问之
}
}

可见,在每一棵(子)树的根节点,该算法都首先定位对应的HLVFL节点。同时在此过程中,依然利用辅助栈逆序地保存沿途所经各节点,以确定遍历序列各个片段在宏观上的拼接次序。

层次遍历

在这里插入图片描述
迭代式层次遍历则需要使用与栈对称的队列结构

template <typename T> template <typename VST> //元素类型、操作器
void BinNode<T>::travLevel ( VST& visit ) { //二叉树层次遍历算法Queue<BinNodePosi(T)> Q; //辅助队列Q.enqueue ( this ); //根节点入队while ( !Q.empty() ) { //在队列再次变空之前,反复迭代BinNodePosi(T) x = Q.dequeue(); visit ( x->data ); //取出队首节点幵讵问之if ( HasLChild ( *x ) ) Q.enqueue ( x->lc ); //左孩子入队if ( HasRChild ( *x ) ) Q.enqueue ( x->rc ); //右孩子入队}
}

Huffman 树

Prefix-free code:不同字符的编码互不为前缀,故不致歧义。
Huffman树(也称为霍夫曼树)是一种用于数据压缩的二叉树,通常用于编码和解码数据。
Huffman树的主要思想是使用不等长的编码来表示不等概率的字符或符号,以便更频繁出现的字符使用较短的编码,从而实现数据压缩。

Huffman树的构建过程通常包括以下步骤:
1)统计每个字符或符号在数据中出现的频率,然后将它们作为叶子节点构建初始的一棵二叉树。每个叶子节点的权重等于字符的频率。
2)创建一个优先队列(通常使用最小堆或最小优先队列),并将所有的叶子节点插入到队列中,根据权重进行排序。
3)从优先队列中取出权重最小的两个节点,合并它们,然后将合并后的节点插入回队列中。合并后的节点的权重等于两个子节点的权重之和。
4)重复步骤3,直到队列中只剩下一个节点,这个节点就是Huffman树的根节点。
5)构建完整的Huffman树后,为每个字符或符号分配一个唯一的编码,编码规则是:从根节点出发,左子树路径标记为0,右子树路径标记为1,直到到达叶子节点。这样,每个字符都有一个不同长度的二进制编码。

Huffman树的一个关键特性是,具有较高频率的字符拥有较短的编码,而较低频率的字符拥有较长的编码。这种编码方式可以有效地减小数据的存储或传输空间,因为常用字符的编码较短,不常用字符的编码较长。

若考虑出现频率,完全二叉树或满树未必最优。
若考虑字符各自的出现频率,则可将带权平均编码长度取作编码树 T 的叶节点带权平均深度(weighted average leaf
depth): w a l d ( T ) = ∑ x ∈ ∑ p ( x ) ⋅ ∣ r p s ( x ) ∣ wald(T) = \sum_{x\in \sum}p(x)\cdot |rps(x)| wald(T)=xp(x)rps(x)

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Springboot整合JWT完成验证登录

目录 一、引入依赖二、JwtUtil 代码解读三、LoginController 代码解读四、整体代码五、结果展示 一、引入依赖 <dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></depende…

el-table 实现表、表格行、表格列合并

最近写vue开发项目的时候&#xff0c;很多地方用到了Element组件中的Table 表格。经过一周的边学边做&#xff0c;我总结了以下三种有关表格的合并方法。 一、合并表头 话不多说&#xff0c;先看效果图 代码如下&#xff1a; 表格结构如上&#xff0c;其中:header-cell-style对…

233062C++QTday5

实现一个图形类&#xff08;Shape&#xff09;&#xff0c;包含受保护成员属性&#xff1a;周长、面积&#xff0c; 公共成员函数&#xff1a;特殊成员函数书写 定义一个圆形类&#xff08;Circle&#xff09;&#xff0c;继承自图形类&#xff0c;包含私有属性&#xff1a;半…

自动化测试框架unittest与pytest的区别!

引言   前面文章已经介绍了python单元测试框架&#xff0c;大家平时经常使用的是unittest&#xff0c;因为它比较基础&#xff0c;并且可以进行二次开发&#xff0c;如果你的开发水平很高&#xff0c;集成开发自动化测试平台也是可以的。而这篇文章主要讲unittest与pytest的区…

QQ 逻辑漏洞可执行文件 漏洞复现

本文由掌控安全学院- wax 投稿 首先拿到QQ的版本&#xff0c;目前可测试版本包括QQ最新版本&#xff0c;TIM最新版本 新创建一个bat文件&#xff08;这个可以随意&#xff0c;上马的也可以&#xff0c;exe也可以&#xff09; &#xff0c;本次测试内容如下首先向你的手机端发一…

对接西部数据Western Digital EDI 系统

近期我们为国内某知名电子产品企业提供EDI解决方案&#xff0c;采用知行之桥 EDI 系统作为核心组件&#xff0c;成功与西部数据Western Digital&#xff08;简称西数&#xff09;建立EDI连接&#xff0c;实现数据安全且自动化传输。 EDI实施需求 EDI连接 传输协议&#xff1a;A…

数据结构 排序

目录 第八章 排序8.1排序的基本概念1. 概念2. 排序算法的分类 8.2 插入排序8.2.1 直接插入排序8.2.2 算法效率分析8.2.2 折半插入排序总结8.2.3 希尔排序 8.3 交换排序8.3.1冒泡排序8.3.2快速排序&#xff08;了解栈的过程&#xff09; 8.4 选择排序8.4.1 简单选择排序8.4.2 堆…

小工具之视频抽帧

视频抽帧工具&#xff0c;所有视频所在目录以及抽帧图片保存路径 单个视频抽帧操作步骤&#xff1a; 选择文件路径->选择保存路径->拖动跳帧间隔->点击抽取帧 批量视频抽帧操作步骤&#xff1a; 选择文件夹路径->选择保存路径->拖动跳帧间隔->点击抽取帧 imp…

iview label-in-value 和 @on-change 的使用

在select加上label-in-value 之后&#xff0c;就可以调用通过on-change默认的方法&#xff0c;获取到value和label的值了 <Select v-model"params.area" placeholder"选择区县" label-in-value clearable style"width: 102px"><Option…

pip和conda的环境管理,二者到底应该如何使用

关于pip与conda是否能混用的问题&#xff0c;Anaconda官方早就给出了回答 先说结论&#xff0c;如果conda和pip在相同环境下掺杂使用&#xff0c;尤其是频繁使用这两个工具进行包的安装&#xff0c;可能会导致环境状态混乱 就像其他包管理器一样&#xff0c;大部分这些问题均…

mysql在ubuntu上命令行登陆密码不正确

1.登陆提示如下 2.使用mysql -u root -p登录也是类似的 3.打开宝塔面板 点击root密码&#xff0c;更改密码后即可在命令行界面登录 4.登录效果如下

深度学习环境搭建——之Anaconda3安装配置

序言&#xff1a; 工作中一直从事的是FPGA嵌入式开发&#xff0c;图像处理相关的工作。目前随着AI的浪潮&#xff0c;也被动卷入到深度学习的漩涡中&#xff0c;为了不被漩涡卷入深渊&#xff0c;只能自学些深度学习相关的知识&#xff0c;俗话说“好记性不如烂笔头”何况已经…

profinet是什么?

profinet是什么&#xff1f; 参考&#xff1a;一文读懂Profibus、Profinet、Ethernet的区别 PROFINETPROFIbusetherNET&#xff0c;把Profibus的主从结构移植到以太网上&#xff0c;所以profinet会有Controller和Device&#xff0c;他们的关系可以简单的对应于profibus的Maste…

【C++】构造函数意义 ( 构造函数显式调用与隐式调用 | 构造函数替代方案 - 初始化函数 | 初始化函数缺陷 | 默认构造函数 )

文章目录 一、构造函数意义1、类的构造函数2、构造函数显式调用与隐式调用3、构造函数替代方案 - 初始化函数4、初始化函数缺陷5、默认构造函数6、代码示例 - 初始化函数无法及时调用 一、构造函数意义 1、类的构造函数 C 提供的 构造函数 和 析构函数 作为 类实例对象的 初始化…

长短期记忆网络(LSTM)

概念 三个门&#xff1a;遗忘门、输入门、输出门 候选记忆单元 记忆单元 隐状态 ot 控制是否让输出&#xff0c;是否要进行重置。 总结 代码实现 import torch from torch import nn from d2l import torch as d2lbatch_size,num_steps 32,35 train_iter,vocab d2l.load_…

Linux中安装MySQL_图解_2023新

1.卸载 为了避免不必要的错误发生,先将原有的文件包进行查询并卸载 // 查询 rpm -qa | grep mysql rpm -qa | grep mari// 卸载 rpm -e 文件名 --nodeps2.将安装包上传到指定文件夹中 这里采用的是Xftp 3.将安装包进行解压 tar -zxvf 文件名 -C 解压路径4.获取解压的全路…

day55:C++ day5,运算符重载剩余部分、静态成员、继承

#include <iostream> #include <cstring> #define pi 3.14 using namespace std;class Shape { protected:double round;double area; public://无参构造Shape():round(40),area(100){cout<<"Shape::无参构造函数&#xff0c;默认周长为40&#xff0c;面…

sql 时间函数

1&#xff0c;前提 今天看同事写的sql里面出现了时间类的函数&#xff0c;平时自己也经常用到&#xff0c;每次都要百度&#xff0c;还不如自己整理记录在一起&#xff0c;方便后续使用。 2&#xff0c;sql时间函数 2.1 获取当前时间&#xff1a; selectNOW() as 当前日期时…

docker 部署 node.js(express) 服务

1、在 express 项目根目录下新增 Dockerfile 文件&#xff0c;内容如下&#xff1a; 创建服务容器的方法&#xff0c;可以根据自己的情况选择&#xff1a; 1、以下示例为宿主机没有安装 node 环境的写法&#xff1b; 2、先在本地构建包含 node 和 express 的基础镜像&#xff0…

JavaScript中的事件捕获(event capturing)和事件冒泡(event bubbling)

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 事件捕获和事件冒泡⭐ 事件捕获&#xff08;Event Capturing&#xff09;示例&#xff1a; ⭐ 事件冒泡&#xff08;Event Bubbling&#xff09;示例&#xff1a; ⭐ 应用场景⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开…