二叉树遍历 和 线索二叉树

文章目录

    • 1.1 二叉树遍历
      • 1.1 前提
      • 问题1: 什么叫二叉树的遍历?
        • 二叉树的三种遍历:
        • 三个概念:遍历 和 访问 和 经过
        • 重要概念:遍历过程中的经过节点,不代表访问节点
      • 问题2:遍历和访问的联系?
      • 问题3:这个有顺序的编号的意义是什么?
      • 问题4:什么是访问?如何对节点进行访问?
    • 1.2 二叉树遍历代码:二叉树的遍历
      • 1.递归类型的二叉树遍历:
        • 1.先序遍历
        • 2.中序遍历
        • 3.后续遍历
        • 概念一:
        • 概念二:visit()函数是访问当前节点,PreOrder()这个函数是按照先序访问树节点(也称作遍历);
      • 2.非递归类型的二叉树遍历
    • 1.3:通过遍历序列构造二叉树
      • 思路: 通过(先序 + 中序) / ( 后序 + 中序) / ( 层次 + 中序) 三种组合构建二叉树;
      • 其中三种组合特点是 : 有一个遍历能很简单的提供根节点,中序能根据根节点划分左右子树,然后根据中序划分的左右子树的长度,再去找提供根节点那个序列中的左右子树,进行迭代;
    • 2.1 线索二叉树
      • 2.1.1 建立线索二叉树
        • 前提1:线索二叉树说的直接前驱(前驱节点),直接后继(后继节点)是 将二叉树遍历后得到的访问顺序中 每个节点在该顺序中的前后继:
        • 前提2:建立二叉线索树的过程本质是在进行一次 二叉树遍历过程中完成的。
        • 代码讲解:王道配套视频讲解的很好,但是有一些细节视频里面没有细讲。我们通过代码讲解
        • 中序建立线索二叉树
          • 解释:关于先序线索二叉树建立createInthread()函数中的代码{ pre->rchild = null; }解释
        • **先序建立线索二叉树**:
          • 解释:关于先序遍历createInthread()函数中在PreThread()函数执行后 { pre->rchild = null; }能够直接这样设定的原因
          • 解释:关于PreThread()函数中,当我们访问完当前节点我们需要判断当前节点左子树是否是空,才能决定是否让其左子树进行遍历而右子树却不需要判定。
            • 疑问点:当访问节点结束时为什么不用判断该节点右指针指向的是线索还是儿子,只用对当前节点左子树进行判空?
            • 疑问点:为什么只有先序用进行这样的判断:
        • 后序建立线索二叉树
          • 解释:关于{ pre->rchild = null; } 这里我们加了 if(pre - > rtag == 1)判断!!!!
        • pre的改进:
      • 2.1.2 遍历线索二叉树
        • 遍历中序线索二叉树
        • 两个概念:
          • 第一个概念:访问中序线索二叉树的中序序列下的第一个节点:
          • 解释:p->ltag == 0,表示p的左子树非空,所以树p中访问的第一个节点是树p中最左的节点,树p中最左的节点的特征就是p的左子树的左子树的左子树..........中第一个出现p->ltag==1的节点,在众多嵌套左子树中第一个没有左子树的节点。
          • 第二个概念:求中序线索二叉树中节点P在中序序列下的后继:
          • 解释:求当前节点的p的后继节点;
        • 遍历给定根节点的中序线索二叉树按照中序线索遍历二叉树:
        • 解释:我们知道一颗树的根节点的时候遍历树的中序

1.1 二叉树遍历

1.1 前提

二叉树遍历我将围绕诸多概念问题进行展开。

问题1: 什么叫二叉树的遍历?

​ 答: 这个问题看似简单,但实际上有很多坑,我们知道二叉树的遍历分为三种分别是“ 先序遍历”,“中序遍历”。“后续遍历”

​ 这里我再次重申什么叫做二叉树的遍历?请认真思考,或者看书找答案。

二叉树的三种遍历:

​ 先序遍历 : 根遍历 、 左子树遍历、右子树遍历

​ 中序遍历 : 左子树遍历、 根遍历 、右子树遍历

​ 后序遍历 : 左子树遍历、右子树遍历、根遍历

注意:我这里为什么要重复三次遍历?

三个概念:遍历 和 访问 和 经过

​ 遍历是相对于树而言的;

​ 访问是相对于节点和树而言的;

​ 经过也是相对于节点而言的;

重要概念:遍历过程中的经过节点,不代表访问节点

​ 当我用中序来遍历子树时:遍历过程中我正在 访问的是节点是 A节点,但我能不能确定我下一个访问谁?

​ 答:可以,我下一个访问的是A节点的右子树遍历过程中最左的节点!注意是最左的节点,这个概念是不是很少提及,这些过程都是在递归中完成的自然就会被虚化,导致你将遍历中的下一个访问和遍历中当前访问节点的左右子树搞混。 这有点深如探讨了。先不如此深入等我们讲到二叉线索树再继续探讨。

​ 通过这个概念是不是明白了 遍历 访问 经过的概念的细微差别。

问题2:遍历和访问的联系?

​ 遍历二叉树的过程就是访问二叉树每一个节点的过程,且每一个节点只访问一次;

​ 遍历中访问节点的顺序根据二叉树的形态以及你选择怎么样遍历(三种遍历选择)是有关联的;

​ 并且遍历过程中你会得到一串有顺序的二叉树节点的编号。

问题3:这个有顺序的编号的意义是什么?

这个有顺序的编号就是 你访问二叉树节点的先后顺序,注意是访问顺序,要和经过顺序区分开。

问题4:什么是访问?如何对节点进行访问?

其实你获得这串顺序编号就是通过访问操作而来的

假设访问操作是 visit(p) #p是指向被访问的节点

只需要你将visit函数编写为:“输出参数p所指向地址的节点的编号

void visit(二叉树结构的指针类型 p)
{printf("%c",p->data)  #我们在遍历中默认:二叉树结构中data存储的是二叉树的编号。
}

通过上述代码你在用遍历过程中根据visit添加位置的不同就能确定二次树的访问顺序

到这里你应该已经能明白大部分的问题了,我们开始通过代码对知识的巩固。

1.2 二叉树遍历代码:二叉树的遍历

1.递归类型的二叉树遍历:

1.先序遍历
void PreOrder(BiTree p)
{visit(p);                 # 访问节点pPreOrder(p->plchild);     # 遍历节点p的左子树PreOrder(p->prchild);     # 遍历节点p的右子树
}
注:BiTree是二叉树的结构体的指针类型,所以p就是二叉树类型的指针。
只有visit(p)操作是在访问p,而其他两个操作相当于在访问p的左右子树。
2.中序遍历
void InOrder(BiTree p)
{PreOrder(p->plchild);     # 遍历节点p的左子树visit(p);                 # 访问节点pPreOrder(p->prchild);     # 遍历节点p的右子树
}
注:BiTree是二叉树的结构体的指针类型,所以p就是二叉树类型的指针。
只有visit(p)操作是在访问p,而其他两个操作相当于在访问p的左右子树。
3.后续遍历
void PostOrder(BiTree p)
{PreOrder(p->plchild);     # 遍历节点p的左子树,也可以理解这一步是在访问该函数p节点之前的那些节点。PreOrder(p->prchild);     # 遍历节点p的右子树visit(p);                 # 访问节点p}
注:BiTree是二叉树的结构体的指针类型,所以p就是二叉树类型的指针。
只有visit(p)操作是在访问p,而其他两个操作相当于在访问p的左右子树。

通过对三种遍历的代码的书写,是不是就有开始晕递归了!!!!!

哈哈哈,慢慢来,let’s go!!!

概念一:

​ 上述三个遍历如果都没有visit§这个操作是不是都是一样的了

void Order(BiTree p)
{PreOrder(p->plchild);     # 遍历节点p的左子树PreOrder(p->prchild);     # 遍历节点p的右子树	
}

​ 这个过程是不是就是但单纯的**”经过“一遍二叉树,注意这里是经过,单单是经过的顺序是和先序遍历是一样的**。

​ 然而我们的编写 先序、中序、后续其实并没有”节点改变“经过顺序,而是通过对**“节点访问” 进行了限定**,此时访问对象被分为三个对象:当前树的根节点,当前树左子树、当前树的右子树。

​ 当我们想先按照先序访问:我们就把访问根节点放在访问另外两位的前面就会确保当前这颗树的三个访问对象按照先序的设定进行访问,注意此时我们把访问左右子树分别看作一个整体。然而左子树右子树都是我们访问这个根节点所在的二叉树是一个结构,所以让左子树和右子树上的节点进行了相同模式的访问。

概念二:visit()函数是访问当前节点,PreOrder()这个函数是按照先序访问树节点(也称作遍历);

两个操作都是访问 一个是对节点的访问,一个是对树的访问(也叫遍历)

2.非递归类型的二叉树遍历

​ 其实非递归类型的二叉树遍历就是线索二叉树,我们从根节点按照先序(中序/后序)一直找当前访问节点的后继的过程,然后将其进行数学归纳后的结果。

这里我感觉王道书上也写的比较笼统,能看懂书上分析的逻辑,但是要按照线索二叉树求节点后继的那种方法去做才能理解更加透彻。

1.3:通过遍历序列构造二叉树

思路: 通过(先序 + 中序) / ( 后序 + 中序) / ( 层次 + 中序) 三种组合构建二叉树;

其中三种组合特点是 : 有一个遍历能很简单的提供根节点,中序能根据根节点划分左右子树,然后根据中序划分的左右子树的长度,再去找提供根节点那个序列中的左右子树,进行迭代;

如下图是先序:

在这里插入图片描述

2.1 线索二叉树

2.1.1 建立线索二叉树

通过学习线索二叉树我得到的一些感悟:

前提1:线索二叉树说的直接前驱(前驱节点),直接后继(后继节点)是 将二叉树遍历后得到的访问顺序中 每个节点在该顺序中的前后继:

例如 中序遍历二叉树得到一个访问顺序 : A S D F G H J

则G的前驱是F,G的后继是H。

这个前驱和后继 就是访问过程中该点之前访问的节点和该店之后要访问的节点。

前提2:建立二叉线索树的过程本质是在进行一次 二叉树遍历过程中完成的。

​ 中序线索二叉树建立就是进行中序遍历节点过程中建立线索

​ 先序线索二叉树建立就是进行先序遍历节点过程中建立线索

​ 后序线索二叉树建立就是进行后序遍历节点过程中建立线索

代码讲解:王道配套视频讲解的很好,但是有一些细节视频里面没有细讲。我们通过代码讲解
中序建立线索二叉树
中序遍历根据二叉树线索化的条件对访问操作的改进注:这里pre和p传进来的是引用。
void InThread(ThreadTree &p,ThreadTree &pre)
{if(P!=null){InThread(p-lchild,pre)   这里相当于访问当前节点前的所以节点{#这里面的代码相当于中序遍历的 visit()我们在遍历的过程中进行了建立线索的进行的操作如下;1:当“真在遍历节点的左子树为空我们将他的左指针指向刚刚访问过的那个节点”2:如果正在访问节点的前一个节点不为空,且前一个节点的右子树为空,就让前一个节点的右子树指针指向当前节点。3:当前节点访问操作以及实现,但是要将当前节点变成 下一个访问的节点的上一个节点,也就是将p赋值给pre指针。if(p->lclild==null){p -> lchild = pre;p -> ltag = 1;}if(pre->rclild==null && pre!= null ){pre -> rchild = p;pre -> rtag = 1;}将当前节点设置为前pre = p;}Inthread(p->rchild,pre)  这里相当于访问当前节点前的所以节点}}
void createInthread(ThreadTree T)
{	ThreadTree pre = null;if(t!=null){	InThread(T,pre);{#注意我这是在这里加了代码块{},并没有递进结构pre->rchild = null;pre - rtag=1;#这一块代码有讲究:我们这里是中序遍历,InThread结束后 p是指向null的,pre指向最后一个被访问的节点;为什么能直接最后一个将其设置为空 而且 将rtag设置为1(表明最后一个几点没有右子树)证明:当pre指向最后一个节点时,根据中序遍历的特点,若此节点在树结构中后有右子树,则这个节点一定不是最后一个节点,最后一个访问的节点应该在这个节点的右子树,因为题目中中序已经访问完毕,所以pre指向一定是最后一个节点,所以这个节点的右子树一定是空,也即是说p要指向空,从而根据线索化中的设定,当pre的右子树为空让pre的右子树等于p,所以才有pre->rchild = null(p)		}}}

这里我们有一个点需要证明解释一下:为什么在createInthread()函数中,InThread()函数执行后我们直接将pre当前指向的节点的右孩子指向了空?

解释:关于先序线索二叉树建立createInthread()函数中的代码{ pre->rchild = null; }解释

问:为什么能直接最后一个节点的右指针设置为空,且将rtag设为1?

​ 第一步:我们从执行的角度分析:当结束InThread()函数执行结束后的pre指针是指向最后一个节点的,这里是无可置疑的,既然pre是指向最后一个遍历的节点所以最后一个节点的后边是空节点,因此 p 也就一定指向null。

​ 第二步:我们分析中序遍历:中序遍历是先遍历左子树,再遍历根节点,再遍历右子树,如果最后一个节点有右子树的情况下,这个节点能成为最后一个被遍历的节点?这里很容易理解当存在右子树是时,该节点是不能成为最后一个节点的,所有我们能够证明中序遍历最后一个节点一定是没有右子树的,所有我们可以直接将pre所指向的节点的右子树指向空。

​ 第三步:我们将pre设置为空,其实就是将他线索到p了,所以将rtag设为1

当我们用先序和后续建立线索二叉树有什么区别?

先序建立线索二叉树

1:则需要更改OrdThread()遍历二叉树函数中 遍历当前节点和左右子树对象的顺序,代码如下

注:这里pre和p传进来的是引用。
void PreThread(ThreadTree &p,ThreadTree &pre)
{if(P!=null){{#这里面的代码相当于先序遍历的 visit()我们在遍历的过程中进行了建立线索的进行的操作如下;1:当“真在遍历节点的左子树为空我们将他的左指针指向刚刚访问过的那个节点”2:如果正在访问节点的前一个节点不为空,且前一个节点的右子树为空,就让前一个节点的右子树指针指向当前节点。3:当前节点访问操作以及实现,但是要将当前节点变成 下一个访问的节点的上一个节点,也就是将p赋值给pre指针。if(p->lclild==null){p -> lchild = pre;p -> ltag = 1;}if(pre->rclild==null && pre!= null ){pre -> rchild = p;pre -> rtag = 1;}将当前节点设置为前pre = p;}#这里我们明白这些子树的访问都是在该节点之后进行的*******重点,讲解在下边if(p-ltag==0){InThread(p-lchild,pre)   这里相当于访问当前节点左子树的所有节点}Inthread(p->rchild,pre)  这里相当于访问当前节点右子树的所以节点}}

2:修改createInthread()函数,因为createtthread()中{ pre->rchild = null; }这个步骤是因为中序遍历的特点才能这样直接写,先序遍历我们没有证明,其实先序也是可以这样写,如下证明:

void createInthread(ThreadTree T)
{	ThreadTree pre = null;if(t!=null){	PreThread(T,pre);{pre->rchild = null;pre - rtag=1;}}
}
解释:关于先序遍历createInthread()函数中在PreThread()函数执行后 { pre->rchild = null; }能够直接这样设定的原因

​ 我们这里是先序遍历,OrdThread结束后 p是指向null的,pre指向最后一个被访问的节点;

问:为什么能直接最后一个节点的右指针设置为空,且将rtag设为1?

​ 第一步:我们从执行的角度分析:当结束OrdThread()函数后的,pre指针是指向最后一个节点的,这里是无可置疑的,既然pre是指向最后一个遍历的节点所以最后一个节点的后边是空节点,因此 p 也就一定指向null。

​ 第二步:我们分析先序遍历:先序遍历是先遍历根节点,在遍历它的两个子树,如果最后一个节点有右子树的情况下,这个节点能成为最后一个被遍历的节点?这里很容易理解是不能的,所有我们能够证明先序遍历最后一个节点一定是没有子孙(包括没有右子树)的,所有我们可以直接将pre所指向的节点的右子树指向空。

​ 第三步:我们将pre设置为空,其实就是将他线索到p了,所以将rtag设为1

解释:关于PreThread()函数中,当我们访问完当前节点我们需要判断当前节点左子树是否是空,才能决定是否让其左子树进行遍历而右子树却不需要判定。

​ 前提:在线索化过程中 ,每一次访问节点时,只会对当前被访问节点的左子树指针进行线索化 和 被访问节点的前一个节点的右子树指针进行线索化,当前访问的节点的右子树指针是没有发生改变的。

​ 关于这个点王道视频讲的很清楚:我们用图和文字也进行解释如下:

在这里插入图片描述

用图举例,如果我们当前访问的是D节点时:

​ 我们会进行两步操作:第一:判断D节点的左子树是否为空,当D节点左子树为空时,将D节点的左指针线索化到pre所指向的B节点。

​ 第二:判断D节点的前一个节点B的右子树是否为空,若B节点右子树为空时,我们将其右子树线索化到D节点。

​ 当访问完D节点,正常我们该进行PreThread(p->lchild);

​ 于是变引发了问题! 如上图:当我们进行PreThread(p->lchild); 此时D节点的左子树指向B节点,当对B节点进行访问,当我们访问完B节点就开始对他的左子树进行访问,我们就又回到了D节点,从而无线循环下去,所以我们限定:只有当被访问节点左子树不空的时候我们才对其访问也就是ltag==0时。

疑问点:当访问节点结束时为什么不用判断该节点右指针指向的是线索还是儿子,只用对当前节点左子树进行判空?

​ 答:根据前提可知,我们访问当前节点时并不会对右指针进行线索化,所以不会造成这样的问题。

疑问点:为什么只有先序用进行这样的判断:

​ 答:因为只有先序遍历,在根节点访问完成后会去访问左子树,而中序和后序在根节点访问完成后不会对其左子树访问,因此不会造成这种情况。

后序建立线索二叉树

后序建立线索二叉树的遍历过程到这里应该能够很简单是理解

注:这里pre和p传进来的是引用。
void OrdThread(ThreadTree &p,ThreadTree &pre)
{if(P!=null){#这里我们明白这些子树的访问都是在该节点之前进行的InThread(p-lchild,pre)   这里相当于访问当前节点左子树的所有节点Inthread(p->rchild,pre)  这里相当于访问当前节点右子树的所以节点{#这里面的代码相当于先序遍历的 visit()我们在遍历的过程中进行了建立线索的进行的操作如下;1:当“真在遍历节点的左子树为空我们将他的左指针指向刚刚访问过的那个节点”2:如果正在访问节点的前一个节点不为空,且前一个节点的右子树为空,就让前一个节点的右子树指针指向当前节点。3:当前节点访问操作以及实现,但是要将当前节点变成 下一个访问的节点的上一个节点,也就是将p赋值给pre指针。if(p->lclild==null){p -> lchild = pre;p -> ltag = 1;}if(pre->rclild==null && pre!= null ){pre -> rchild = p;pre -> rtag = 1;}将当前节点设置为前pre = p;}}}

2:修改createInthread()函数,因为createtthread()中{ pre->rchild = null; }这个步骤在后序中是不能直接使用的了,前边通过先序和中序的证明,也能够大致理解,如下证明后序线索二叉树:

void createInthread(ThreadTree T)
{	ThreadTree pre = null;if(T!=null){	PostThread(T,pre);if(pre - > rtag == 1){pre->rchild = null;}}
}
解释:关于{ pre->rchild = null; } 这里我们加了 if(pre - > rtag == 1)判断!!!!

问:为什么后序不能呢?

​ 第一步:我们从执行的角度分析:当结束PostThread()函数执行后,pre指针是指向最后一个节点的,这里是无可置疑的,既然pre是指向最后一个遍历的节点所以最后一个节点的后边是空节点,因此 p 也就一定指向null。

​ 第二步:我们分析后序遍历:后序遍历是先遍历两个子树,再遍历根节点,如果最后一个节点有右子树的情况下,这个节点能成为最后一个被遍历的节点?这里很容易理解是可以的,无论有没有右子树后序遍历时我都是最后一个,所以我们需要通过最后一个节点的右子树被线索化的标注rtag来进行判断是否根节点右子树为空。

​ 第三步:当右子树为空时,pre->rtag 是等于1的,此时我们将pre指向的最后一个节点设置为空,将他线索化

pre的改进:

​ 我们发现,当我们遍历二叉树的时候pre一直是一个引用的存在,引用的意思可以理解为实参的别名,和实参实际是一个变量,所以这里pre做形参和实参表示相同含义,所以可以直接将pre声明为全局变量并初始化赋值为null。

2.1.2 遍历线索二叉树

​ 这一部分王道讲的很好,我只对中序进行讲解:

遍历中序线索二叉树
两个概念:
第一个概念:访问中序线索二叉树的中序序列下的第一个节点:

            ThreadNode *Firstnode(ThreadNode *p)   {	while(p->ltag == 0) p=p->lchild;  #return p;}
解释:p->ltag == 0,表示p的左子树非空,所以树p中访问的第一个节点是树p中最左的节点,树p中最左的节点的特征就是p的左子树的左子树的左子树…中第一个出现p->ltag==1的节点,在众多嵌套左子树中第一个没有左子树的节点。
第二个概念:求中序线索二叉树中节点P在中序序列下的后继:
            ThreadNode *Nextnode(ThreadNode *p){if(p->rtag==0) return Firstnode(p->plchild);else return p->rchild;}
解释:求当前节点的p的后继节点;

​ 当他右子树不空的时候就找他右子树中最左的节点,也就是 他右子树的左子树的左子树的左子树…n层嵌套左子树中第一个左子树为空的左子树,刚好Firstnode()函数就是在做这个操作。

​ 当他右子树空的时候,rchild就是代表指向后继的线索。

遍历给定根节点的中序线索二叉树按照中序线索遍历二叉树:
            void Inorder(ThreadNode *T){for(ThreadNode *p = Firstode(t);p!=null;p=Nextnode(p))	visit(p);}
解释:我们知道一颗树的根节点的时候遍历树的中序

​ 就是先找到这个树的第一个被访问的节点然后,然后对第一个访问到的节点求该节点后继的过程,以及求该节点后继的后继的过程,从而就可以用for循环加上上边的两个概念实现。

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

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

相关文章

【代码+详解】算法题 : 最大公约数

❗❗❗必看: 下列题我全部都使用 Java 语言写的,并且均可以提交成功,获得Accepted 结果的. 如果代码和详解看了之后,对答案有任何疑问,都可以在评论区提出来,我都会一个一个回答. ❗❗❗感谢大家的支持,如果喜欢我的博客,关注 点赞 收藏 评论一波,非常感谢!!! 文章目录 题目&…

思维导图——幕布

一、前言 幕布是一款专注于简化和组织信息的大纲笔记应用,它旨在帮助用户高效地整理知识点、优化工作流程以及规划个人生活。 二、软件特点 幕布工具的核心优势在于其能够快速将用户的输入转换成清晰的思维导图,便于视觉化地理解和记忆信息。 幕布还具…

分集增益Diversity Gain与复用增益Multiplexing Gain

文章目录 概念DoF(Degrees of Freedom)复用增益(Multiplexing Gain)自由度(Degrees of Freedom, DoF)两者的关系实际应用关系总结具体关系例子结论 近场MIMO的分集与复用与远场MIMO有何不同 概念 在通信领…

HttpClient cookie爬虫记录

记录一次java语言使用httpclient爬取网站接口数据的经历 需要用到的依赖&#xff1a; httpclient和httpcore是封装了http请求的工具类 jsoup可以将返回的网页html找到你需要的xml节点&#xff0c;很方便 <dependency><groupId>org.apache.httpcomponents</gr…

通过DirectML和ONNXRuntime运行Phi-3模型

更多精彩内容&#xff0c;欢迎关注我的公众号“ONE生产力”&#xff01; 上篇我们讲到通过Intel Core Ultra系列处理器内置的NPU加速运行Phi-3模型&#xff0c;有朋友评论说他没有Intel处理器是否有什么办法加速Phi-3模型。通常&#xff0c;使用GPU特别是NVIDA的GPU加速AI模型…

windows上安装MongoDB,springboot整合MongoDB

上一篇文章已经通过在Ubuntu上安装MongoDB详细介绍了MongoDB的各种命令用法。 Ubuntu上安装、使用MongoDB详细教程https://blog.csdn.net/heyl163_/article/details/133781878 这篇文章介绍一下在windows上安装MongoDB&#xff0c;并通过在springboot项目中使用MongoDB记录用户…

SpaceX: 太空火箭自主精准着陆

本文是根据Lars Blackmore在16年的一篇公开论文翻译而来&#xff0c;虽然有些早而且是科普文章&#xff0c;但是可以初见一些SpaceX火箭着陆的细节&#xff0c;后面我会对spaceX landing control 技术主管MIT博士期间研究火箭控制算法的论文进行讲解&#xff0c;敬请期待。 Lar…

【php实战项目训练】——thinkPhP的登录与退出功能的实现,让登录退出畅通无阻

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

C/C++ 进阶(5)二叉平衡搜索树(AVL树)

个人主页&#xff1a;仍有未知等待探索-CSDN博客 专题分栏&#xff1a;C 目录 一、概念 二、平衡因子 三、操作 插入 旋转 左单旋 右单旋 左右双旋 右左双旋 一、概念 二叉平衡搜索树又称AVL树&#xff0c;是一种特殊的二叉搜索树。一般的二叉搜索树在遇到数据有序时&…

SOLIDWORKS修改零件时出现错误怎么办?

我们在使用SOLIDWOKRS进行零件建模过程中往往避免不了修改&#xff0c;但在修改后又常常会出现零件报错的情况&#xff0c;设计树中会出现一堆的错误和警告&#xff0c;我们如何快速处理这些问题呢&#xff1f; 我们都知道SOLIDWOKRS零件通常包含两大类的对象&#xff0c;分别…

Docker 入门版

目录 1. 关于Docker 2. Dockr run命令中常见参数解读 3. Docker常见命令 4. Docker 数据卷 5. Docker本地目录挂载 6. 自定义镜像 Dockerfile 语法 自定义镜像模板 Demo 7. Docker网络 1. 关于Docker 在docker里面下载东西&#xff0c;就是相当于绿色面安装板&#x…

python之生成器表达式

背景 生成器表达式&#xff0c;整个表达式都是另一个函数的唯一入参&#xff0c;则不需要带括号&#xff1b;若他只是其中一个参数&#xff0c;则需要圆括号包裹。 演示

响应式流和reactor框架进阶

响应式流和reactor框架进阶 响应式流创建、转换、处理 本文档主要介绍在响应式编程中如何从流中获取数据并处理。 前提条件 假设您已经能掌握Java基础、Maven使用、Lamda表达式、响应式编程等基础。 如何获取流中数据 &#x1f30f; 说明 1、不要试图从流中获取数据出来&a…

MMUNet:形态学特征增强网络在结肠癌病理图像分割中的应用

MMUNet: Morphological feature enhancement network for colon cancer segmentation in pathological images. 发表在&#xff1a;Biomedical Signal Processing and Control2024--影响因子&#xff1a;3.137 南华大学的论文 论文地址&#xff1a;main.pdf (sciencedirecta…

地理信息科学中的大数据挑战

在信息化爆炸的时代&#xff0c;地理信息科学&#xff08;GIScience&#xff09;正经历着前所未有的变革&#xff0c;其中&#xff0c;地理空间大数据的涌现为科学研究与应用带来了前所未有的机遇与挑战。作为地理信息与遥感领域的探索者&#xff0c;本文旨在深入剖析地理空间大…

找不到steam_api64.dll,无法继续执行的原因及解决方法

电脑已经成为我们生活中不可或缺的一部分。然而&#xff0c;在使用电脑的过程中&#xff0c;我们经常会遇到一些常见的问题&#xff0c;其中之一就是找不到某个特定的动态链接库文件&#xff0c;比如steamapi64.dll。这个问题可能会导致某些应用程序无法正常运行&#xff0c;给…

音视频开发—音频相关概念:数模转换、PCM数据与WAV文件详解

文章目录 前言1.模拟数字转换&#xff08;ADC&#xff09;1.1ADC的关键步骤&#xff1a; 2.数字模拟转换&#xff08;DAC&#xff09;2.1DAC 的基本流程包括&#xff1a; 3.PCM数据3.1PCM 数据的关键要素包括&#xff1a; 4.WAV文件4.1 WAV的构成4.2WAV文件的标准块结构4.3WAV的…

kettle从入门到精通 第六十五课 ETL之kettle 执行动态SQL语句,轻松实现全量增量数据同步

本次课程的逻辑是同步t1表数据到t2表&#xff0c;t1和t2表的表机构相同&#xff0c;都有id&#xff0c;name,createtime三个字段。 CREATE TABLE t1 (id bigint NOT NULL AUTO_INCREMENT,name varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,cr…

View->Bitmap缩放到自定义ViewGroup的任意区域(Matrix方式绘制Bitmap)

Bitmap缩放和平移 加载一张Bitmap可能为宽高相同的正方形&#xff0c;也可能为宽高不同的矩形缩放方向可以为中心缩放&#xff0c;左上角缩放&#xff0c;右上角缩放&#xff0c;左下角缩放&#xff0c;右下角缩放Bitmap中心缩放&#xff0c;包含了缩放和平移两个操作&#xf…

数据整理操作及众所周知【数据分析】

各位大佬好 &#xff0c;这里是阿川的博客&#xff0c;祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 Python 初阶 Python–语言基础与由来介绍 Python–…