二叉树 1.0 -- 创建二叉树、遍历二叉树、二叉树常见问题求解

二叉树的遍历问题 二叉树:递归遍历、非递归遍历、树的宽度问题 阅读详情

树的结构主要是为了查找,这个主要是为了搜索,树的结构关注的不是增删查改

树

广义上面的树的结构我们不知道树的一个节点是有几个子节点的,所以这个时候我们需要定义的一种结构就是,一个节点的孩子是可以动态的增加的,这个时候我们就可以把一个一个的节点放置在vector中,这个时候某一个节点的孩子节点是可以动态的增加的
还有一种结构就是,我们可以把一个节点中定义两个节点指针,一个指向的是当前节点的兄弟,一个指向的是当前节点的第一个孩子节点,那么它的其他的孩子节点就由第一个孩子节点去标记了

struct TreeNode
{
    int _data;
    TreeNode* _firstchild;
    TreeNode* _nextSibling;
}

树的应用:文件管理

树的存储结构

在树的存储结构中主要介绍三种存储结构:双亲表示法,孩子表示法,孩子兄弟表示法

双亲表示法

除了我们的根节点之外,我们其他噶所有的节点都是有双亲的,我们在定义树的存储结构的时候可以在每个节点中附设一个指示器,用来标识当前节点的双亲节点,然后我们可以在一个数组中开辟连续的空间用来存储我们树的结构。

template<class T>
struct TreeNode
{
    T _data;
    int _parent;    //数组中的下标
}
template<class T>
class Tree
{
    typedef TreeNode<T> Node;

private:
    Node _nodes[10];     
    int _root,_n;   //用来标记根的位置和树的节点的个数
}

上面的存储结构中,因为我们的根节点是没有双亲的,我们这里可以不妨设双亲节点的标记双亲的那个参数的大小为-1.

这个时候就存在了一个问题就是,我们只能够通过一个节点找到它的双亲,但是不能双亲找到孩子节点,这里要考虑把每个节点中在加上一个标识位,用来标识孩子的位置,比如设计成下面的这种形式的

template<class T>
struct TreeNode
{
    T _data;
    int _parent;    //数组中的下标
    int _fiestchild;    //我们成这个域为长子域
}

如果我们的使用场景中还特别的关注一个节点和他兄弟之间的关系,我们还可以在节点域里面加上leftsib和rightsib等,就是根据我们的需求设计我们的节点结构就可以了。

下面还留了其他的一些思考的内容

还需要思考的另外的一个问题就是,每当我们增加一个节点的时候如何找到知道他们双亲节点呢,就是比如说我们知道一个节点的值是5,然后同时还有另外一个节点的值也是5,然后我们的第一个5这个节点有一个孩子是1,那么当我们的这个1添加进去的时候我们如何判断这个节点的父亲到底是第一个5呢,还是第二个5呢

还有就是删除一个节点的时候,我们需要判断的就是,此时我们是需要遍历的,我们想要删除一个节点的孩子节点,这个时候我们是需要遍历的,然后找到这个节点的父亲是不是我们想要删除的那一个,这个时候在进行删除,那么这种遍历是不是很麻烦呢

还有就是其他的一些问题的时候,如果我们是需要遍历的话,我想要一个遍历方式是层序的遍历是不是也会很麻烦呢,这个时候会伴随着大量的遍历

孩子表示法

在讲孩子表示法之前,我们先讲一个与孩子表示法类似的方法,就是多重链表表示法,就是我们的节点的数据结构中,有一个数据域,然后剩下的是指向孩子节点的指针,类似于下图的表示

image

但是上面的存储结构还是存在问题的,就是我们的指针域指向孩子的那些空间,因为孩子不确定,可能会造成空间的浪费,于是我们又出现了下面的一种存储结构。

我们可以在节点结构中加上一个孩子个数,有几个孩子我们这类就开辟出几个孩子指针节点,但是这种方式也是存在一些问题的,就是我们的维护的代价太大了,所以我们有了下面的一种方式,既能节省存储的空间,还能很好的维护,这就是孩子表示法,我们可以在设计节点的时候,包含两部分内存,一个是数据域,还有一个是指向孩子的链表指针,就是下图的方式进行存储

image

这里二叉树的结构的设计如下

//指针节点
template<class T>
struct PointNode
{
    int _child;  //标记孩子的下标
    TreeNode* _next;    //指向下一个孩子
}
//孩子节点
template<class T>
struct TreeNode
{
    T _data;
    PointNode<T>* _firstchild;
}
template<class T>
class Tree
{
    TreeNode<T> _nodes[10];
    int _root,_n;
}

其实为了解决多重链表表示法造成的空间浪费的问题,我们还可以利用STL中的vector,我们指向节点的指针域可以不用放置一个一个的链表,我们这里可以直接放置一个vector,我们可以直接把孩子节点放在vector中。就是类似于下面的存储结构

tempalte<class T>
struct TreeNode
{
    T _data;
    vector<TreeNode<T>> _child;
}

孩子兄弟表示法

孩子兄弟表示法的方法是我认为比较巧妙的一种方法,就是我们的每个节点它如果有都会有唯一一个长子,每个节点如果有,他都会有唯一一个右孩子,于是我们设计出下面的存储结构

template<class T>
struct TreeNode
{
    T _data;
    TreeNode* _fistchild;
    TreeNode* _rightchild;
}

image

二叉树的结构

上面的广义上的树不是我们学习的重点,我们学习的重点的是二叉树,包括现实中的使用最多的也是二叉树,以及一些成熟的数据结构也是用二叉树的一些包装。

二叉树的结构

  • 我们可以把一个数组看成是一个二叉树,这个在以后的堆里面会有很好的运用,虽然数组在实际物理上面是连续存储着的,但是我们在访问一些数据,以及对数据的一些操作的时候,是按照树的结构进行处理的,比如下面的一种情况,首先看一个图

image

上图中,实际在内存中存储数据的时候,是按照数组的方式存储的,但是我们对数据访问操作的时候是按照树的结构去访问的,比如要访问一个节点的子节点,而当前节点的下标是n,那么它的左孩子节点的下标就是n * 2+1,右孩子节点就是n * 2+2,同样的,一个的父亲节点的下标是(n-1)/2

左孩子 n * 2 + 1
右孩子 n * 2 + 2
父亲节 (n - 1)/2

分析:如果我们的数据很集中,比如满二叉树或者是完全二叉树的时候可以使用上面的结构,但是如果我们的数据不是连续的,甚至是中间有很多空闲的位置的时候,就不建议使用数组这样的结构,这回造成空间的很大的浪费。

  • 常用的一种结构是一个节点有两个指向孩子的指针。
    这种结构叫做二叉链
template<class T>
struct TreeNode
{
    T _data;
    TreeNode<T>* _left;
    TreeNode<T>* _right;
}
  • 还有一种结构是有一个指向父亲的节点,有两个指向孩子的节点
    这种结构是三叉链

template<class T>
struct TreeNode
{
    T _data;
    TreeNode<T>* _father;
    TreeNode<T>* _left;
    TreeNode<T>* _right;
}
创建一个树

传入一个数组,然后使用前序(其他顺序),构建一棵树,传参的时候,需要传入的时候是数组,数组大小还有一个就是非法值
从数组里面一个一个取数据,然后构建到树里面直到,遇到非法值或者是遇到了结尾的时候,这个时候偶就让当前节点的根为NULL

创建一个树,在构造函数中需要调用的函数是creatTree,然后参数是数组,数组大小,非法值,数组下标,返回值是node*

把这个创建树的代码背下来

{1,2,3,0,0,4,0,0,5,6}
这里我们的非法值是0,首先看下面的代码

#include<iostream>
using namespace std;

//  {}

template<class T>
struct TreeNode
{
    T _data;
    TreeNode<T>* _left;
    TreeNode<T>* _right;

    TreeNode(T data)
        :_data(data)
        , _left(NULL)
        , _right(NULL)
    {}
};

template<class T>
class BinaryTree
{
    typedef TreeNode<T> Node;
public:
    BinaryTree()
        :_root(NULL)
    {}

    BinaryTree(const T* arr,const T& inval,const size_t& n)
    {
        size_t index = 0;
        _root = _CreatTree(arr,n,index,inval);
    }

private:
    Node* _CreatTree(const T* arr,const size_t& n,size_t& index,const T& inval)
    {
        Node* root = NULL; 
        if (arr[index] != inval && index < n)
        {
            root = new Node(arr[index]);
            root->_left = _CreatTree(arr,n,++index,inval);
            root->_right = _CreatTree(arr,n,++index,inval);
        }
        return root;
    }

private:
    Node* _root;


};

void TestTree()
{
    int arr[] = {1,2,3,0,0,4,0,0,5,6};
    BinaryTree<int> tree(arr,0,10);
}

下面是对上面代码的一个分析,首先应该注意的一个就是,我们需要在构造函数里面调用一个_CreatTree()的函数来进行树的创建,因为在 创建树的时候,需要递归的调用,所以这里不能直接一直调用构造函数,这显然是不合理的

创建树的函数 – _CreatTree()

接下来主要需要讲述的就是创建树的函数,首先是函数的返回值,因为我们需要递归的调用,在调用的过程中的一个大的思路就是,首先,让根节点等于函数的返回值,到函数的内部创建一个root的节点指针,然后是如果数组中的数据符合要求就开辟一个节点的空间,然后就是root指向它,接着是是root的左和右分别的调用_CreatTree()函数,最后返回root。通过这样的操作之后,就可以首先是_root指向一个节点,接下来是递归的使当前节点的左右孩子节点调用,就可以使左右孩子节点也指向相应的操作

==把上面的创建树的代码,包括下面的一些代码,其实可以考虑背下来,因为这些代码是最最基础的东西了,在理解的基础之上背下来,这些是以后深入学习的一个基础,不光光是要背,更加重要的是理解其中的一些==

参数index

参数index为什么使用的是引用呢,这里如果我们不使用引用的话,就会出现一些问题,首先还是看上面的我们给出的例子

    int arr[] = {1,2,3,0,0,4,0,0,5,6};

首先第一层递归里面的时候,我们的index是0,然后创建一个节点,把1放置进去了,然后进入到下一层递归,这个时候index是1,然后把数据’2’放置进去了,大家记住这层递归里面的index是1,然后进入到第三层递归的时候,index是2,这个时候把数据‘3’放置进去了,接着往下走的时候,index是3,这个时候数据是0,这是个非法值,于是再次递归,这个时候index是4,也是一个非法值,这个时候,关于数据3这一层的递归函数已经结束了,所以返回上一层递归,上一层递归的时候,index是1,就是又回到了数据2的那一层递归调用了,这个时候++index后,又变成了3,所以节点数据2的右孩子又是3,所以这里是错误,这个是我们应该注意的一个问题。

二叉树的遍历

前序遍历,中序遍历,后序遍历,层序遍历

看到一个二叉树的时候,想象成三个部分,根节点,左子树,右子树

前序:根左右
中序:左根右
后序:左右根
层序:一层一层

关于遍历的思想特别的重要

==一定要深刻的理解各种遍历的思想,因为下面的好多问题其实都是遍历思想的变形==

二叉树的遍历的这一点的知识很重要,因为后面的很多的内容,很多的题目,很多的求解的方法都是使用了遍历的思想的

前序遍历

==思想==

根左右:访问一个节点的时候先访问数据,然后访问左孩子,然后访问右孩子

public:
void PrevOrder()
    {
        _PrevOrder(_root);
    }
private:
void _PrevOrder(Node* root)
    {
        if (root != NULL)
        {
            cout << root->_data << " ";
            _PrevOrder(root->_left);
            _PrevOrder(root->_right);
        }
    }

前序遍历和后面的很多的遍历包括其他的问题是需要有两个部分组成的,为什么一个设置成公有的,一个设置成私有的呢,因为我们的遍历的时候是需要访问 _ root的,但是我们肯定不能在外面用户使用的时候直接让他们调用前序遍历的时候,将_root,作为参数传递进去,这显然是实现不了的,所以这里需要在写一个私有的函数,让公有的函数去调用这个私有的函数,然后让这个私有的函数去实现遍历的功能。

关于函数的实现部分就是按照拿到一个节点的时候首先要做的就是如果当前节点不是NULL的话,就访问数据,如果是NULL的,就结束么,我上面写代码的时候,我把递归调用那里放置在了if判断的外面了,这是错误的,因为放置在if判断的外面的话,当前节点已经是NULL了,我们是无法访问它的左右节点的。

中序遍历

==思想==

左根右:访问一个节点的时候,首先访问它的左孩子,然后访问数据,然后在访问访问右孩子

public:
void InOrder()
    {
        _InOrder(_root);
        cout << endl;
    }
private:
void _InOrder(Node* root)
    {
        if (root != NULL)
        {
            _InOrder(root->_left);
            cout << root->_data << " ";
            _InOrder(root->_right);
        }
    }

没什么好解释的了,结合着前序遍历就可以理解中序遍历,然后就可以理解后序遍历了

后序遍历

==思想==

左右根:访问一个节点的时候,首先访问它的左孩子,然后在访问访问右孩子,然后访问数据

public:
void EndOrder()
    {
        _EndOrder(_root);
        cout << endl;
    }
private:
void _EndOrder(Node* root)
    {
        if (root != NULL)
        {
            _EndOrder(root->_left);
            _EndOrder(root->_right);
            cout << root->_data << " ";
        }
    }

层序遍历

==思想==
一层一层的遍历
层序遍历的代码中我们使用一个队列,首先我们把根节点放置在队列中去,这个时候队列里面至少有一个节点了 ,接下来要做的就是每次从队列中拿取一个数据,然后把这个节点的数据打印出来,接着就是判断这个节点的左右两个孩子是否为NULL,如果不是的就把左右两个节点指针放置在队列中去。

public:
void LevelOrder()
    {
        queue<Node*> que;
        if (_root)
        {
            que.push(_root);
        }
        while (!que.empty())
        {
            Node* cur = que.front();
            que.pop();
            cout << cur->_data << " ";
            if (cur->_left)
            {
                que.push(cur->_left);
            }
            if (cur->_right)
            {
                que.push(cur->_right);
            }
        }
    }

二叉树的各种求解

二叉树的各种求解中都基本上使用了二叉树遍历的一些思想

需要用到递归的思想:就是我想要求当前节点的某个解,我需要求解它的左右子树的某个解

求树的所有节点的个数

==思想==
我需要求解以当前节点为根的节点的个数,我需要求解当前节点的子节点的个数
返回条件就是,如果当前节点为NULL的话,就直接返回0,如果当前节点不是NULL,就返回当前节点的孩子节点的个数+1,这个1表示的就是当前节点的值。
这个求解的过程可以理解为一个后序遍历的思想,就是我想要给当前节点的所有节点的个数,我首先应该求解的是当前节点的子节点的个数,然后才能给当前节点的个数加上+1。

代码很重要,背下来,在这个代码的基础之上,思考其他的一些内容

int NodeNum()
    {
        return _NodeNum(_root);
    }
private:
int _NodeNum(Node* root)
    {
        if (root == NULL)
        {
            return 0;
        }
        return _NodeNum(root->_left) + _NodeNum(root->_right) + 1;
    }

求树的叶子节点的个数

==思想==
这个时候其实思想还是使用了后序遍历的思想,就是我想要求解当前节点的叶子节点的个数,我需要求解的是当前节点的孩子节点的叶子节点的个数

public:
int LeafNum()
    {
        return _LeafNum(_root);
    }
private:
int _LeafNum(Node* root)
    {
        if (root == NULL)
        {
            return 0;
        }

        if ((root->_left == NULL) && (root->_right == NULL))
        {
            return 1;
        }
        return _LeafNum(root->_left) + _LeafNum(root->_right);
    }

这个内容我们需要和上面的求解节点的个数做一个详细的比较,我们都应该以当前节点为一个判断的依据。这个时候我们很容易纠结的一个问题就是,是不是需要单独的判断左右呢,单独的判断左右的时候,又如何进行相加呢,这个时候就容易除了问题了。看我们上面的代码就很好的解决了这个问题,如果当前节点是NULL,,当前节点很可能就是从上面的父节点传递过来的,所以很好的避免了我们需要单独分开判断的问题了。这个思想当中我们需要注意的问题就是我们的返回条件是两种的,一种就是返回0,一种是返回1。

求第K层的个数

==思想==
我们想要求第k层节点的个数,需要求解的是第k-1层节点的个数

public:
int LevelNodeNum(int k)
    {
        return _LevelNodeNum(_root,k);
    }
int _LevelNodeNum(Node* root,int k)
    {
        if (root == NULL)
            return 0;
        if ((k == 1) && (NULL != root) )
            return 1;
        else
        {
            return _LevelNodeNum(root->_left, k - 1) + _LevelNodeNum(root->_right, k - 1);
        }
    }

上面的方式是一种很巧妙的方法,但是我们还是应该理解其中的道理,这个问题和上面的问题一样,我们还是需要考虑子问题还有几十需要考虑的是返回值,这里的返回值也是有两种返回条件,一种是返回0的时候,还有一种是返回1的状态。

上面的问题让我直接想可能还有点困难,但是让我结合着代码理解的话,问题是不大的

求二叉树的高度(深度)

==思想==
这里还是子问题,如果我们想要求解当前节点的深度,首先需要求解的是当前节点的子节点的高度,然后+1,加的这个1就是当前的一个节点。但是这里返回的时候我哦们需要放回的应该是左右子树最大的那一个,但是如果用三目运算符,或者是使用如下的方式的话,


if(_High(root->_left) > _High(root->_right))
{
    return _High(root->_left);
}

就可能造成了两次的调用了递归函数。所以这里我们采用的是首先用一个数据保存起来的方式。

int High()
    {
        return _High(_root);
    }
private:
int _High(Node* root)
    {
        if (root == NULL)
        {
            return 0;
        }
        int l = _High(root->_left);
        int r = _High(root->_right);

        if (l > r)
            return l + 1;
        else
            return r + 1;
    }

查找某一个节点

==思想==
这个问题和其他的问题有点出入的,我们需要从中间的某一个位置返回一个节点指针,但是这里返回就是一个问题,所以我们应该注意到这个问题

private:
Node* Find(T data)
    {
        return _Find(_root,data);
    }
Node* _Find(Node* root,T data)
    {
        if (NULL == root)
        {
            return NULL;
        }
        else
        {
            if (root->_data == data)
            {
                return root;
            }
            Node* ret = _Find(root->_left,data);
            if (ret)
            {
                return ret;
            }
            ret = _Find(root->_right,data);
            if(ret)
            return ret;
            return NULL;
        }
    }

上面的代码背下来,这是学习其他东西和解决问题的一些基础,一开始学习人家的代码就是要后来更好的运用

C语言实现二叉树的各种遍历及求解深度 C语言实现二叉树的各种遍历及求解深度 一、介绍 二叉树是一种重要的数据结构,在很多方面都有重要的应用,此文主要记录了二叉树的基础知识,包括二叉树的建立、前中后序遍历方式、层次遍历方式、求解二叉树的深度、求解二叉树的节点总数、求解二叉树每层的节点数目等。 二、实现思路 主要借助栈和队列方式实现二叉树的非递归访问等操作,二叉树的建立采用递归方式。层次遍历时, 阅读详情

相关推荐

数据结构—遍历、创建二叉树

1.遍历二叉树算法描述 遍历二叉树( traversing binary tree)是指按某条搜索路径巡访树中每个结点,使得每个结点均被访问一次,而且仅被访问一次。访问的含义很广,可以是对结点做各种处理,包括输出结点的信息,对结点进行运算和修改等。 遍历二叉树是二叉树最基本的操作,也是二叉树其他各种操作的基础,遍历的实质是对二又树进行线性化的过程,即遍历的结果是将非线性结构的树中结点排成一个线...

小虾米编程 1461

二叉树的解决方法

二叉树的问题的解决办法主要采用递归的方法解决 主要有两种: 递归遍历 递归分治 90%的问题可以采用递归分治的办法解决。 1.递归遍历的方法 定义一个全局变量,将该变量作为一个结果参数传入一个定义的空返回值类型的辅助函数。 递归遍历的方法,是一种不断得递归深入遍历,亲力亲为。遍历的顺序很重要。 2.递归分治的方法 分治的办法通常可以不用定义辅助函数,或者定义一个有

hlang8160的博客 1107

Spring Boot整合Apache Hop 2.3.0实战:从零搭建数据管道(附完整代码)

本文详细介绍了如何在Spring Boot项目中整合Apache Hop 2.3.0,从零开始构建可嵌入的数据管道。内容涵盖环境初始化、依赖配置、管道设计,并通过完整代码示例演示了如何通过REST API触发执行,实现数据同步与ETL流程的自动化管理,为微服务架构提供灵活的数据集成方案。

web99的专栏 632

数据结构——二叉树遍历和常见问题

二叉树遍历 二叉树常见问题

weixin_57133901的博客 3645

OpenClaw:深度学习驱动的智能编程工具实战解析

智能编程工具通过深度学习技术革新传统开发流程,其核心在于代码语义理解与实时协作能力。这类工具采用AI代码补全、错误预测等技术,显著降低开发者认知负荷,尤其适用于复杂业务逻辑开发和遗留系统维护场景。以OpenClaw为例,其智能填充和上下文感知功能可提升40%编码效率,减少65%调试时间。关键技术实现包含自然语言处理、代码静态分析等,在金融科技、电商系统等领域具有广泛应用前景。热词提示:代码理解引擎、智能工作流整合展现了当前AI辅助开发的最新趋势。

chubaisheng8627的博客 320

ZYNQ USB按键读写操作详解:从裸机到Linux系统的完整实现

USB接口在现代嵌入式系统中扮演着至关重要的角色,而按键作为最基础的人机交互设备,其与USB的结合能够实现丰富的应用场景。这种实现不仅适用于简单的键盘应用,还可以扩展为游戏控制器、专业输入设备或工业控制面板,展现了ZYNQ在嵌入式USB应用中的强大灵活性。:USB控制器需要准确的时钟源,通常使用外部33MHz晶振,并在Vivado中正确配置。结合ZYNQ的PL(可编程逻辑)和PS(处理系统)优势,可以创建创新的USB按键应用。本文详细介绍了在ZYNQ平台上实现USB按键读写的完整方案,涵盖了从。

QQ_778132974的博客 378

二叉树遍历及其相关问题

二叉树的定义: * 在计算机科学中,二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。 * 二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。二叉树的第i层至多有2^{i-1}个结点;深度为k的二叉树至多有2^k-1个

SkinWhite的博客 928

【C语言笔记初级篇】第一章:C语言快速入门及注意事项

(1)第一个C语言程序 A:利用vs2010写C语言程序 1:按以下步骤新建工程 2:添加源文件,“.c”文件 B:第一个C语言代码 1:以下是基本的C语言程序 2:由于没有设置连接器,所以打印结果没有显示,按照如下步骤链接控制台 (2)数据类型 A:基本数据类型及占用字节 B:一些概念的梳理 概念一:关于计算机的单位 位(bit):计算机通过电路的开关和闭合处理信息,电路通...

快乐江湖的博客 3737

C语言:二叉树的遍历以及遇到的问题

二叉树的遍历以及注意点

myscratch的博客 3416

PX4实战(十):PX4导航模块(Navigator)详解

本文将对 PX4 固件 v1.14.3 版本中的 Navigator(导航)模块进行详尽的技术剖析。作为飞行控制栈中的高层决策核心,Navigator 模块承担着将抽象的任务指令转化为具象的底层控制设定点的关键职责。本文基于对 src/modules/navigator 目录下源代码的深究研究与架构反推,详细阐述了该模块的文件组织结构、基于状态机的控制逻辑、uORB 异步通讯机制、核心任务模式(Mission)与返航模式(RTL)的实现细节,以及地理围栏(Geofence)与任务可行性检查(Feasibil

PX4-SLAM-PNC 669

大数据分析案例-基于随机森林模型对北京房价进行预测

自1998年我国取消了福利分房的政策后,房地产市场迅速开展蓬勃起来。同时,随着社会经济的快速开展,居民的经济条件越来越好,住房条件也在不断地提升。而住房是人民根本生活的保障,也是-一个家庭最重要的资产,从一定的层面.上反映了一个家庭整体的生活水王,多方面的因素使得房地产行业在短时间开展成为我国的支柱产业之一;成为了切实关乎人民生活和利益的重要产业。然而,随着房地产行业的开展,问题也慢慢突显出来,房价一直居高不下成为了一个大问题。 作为国家的支柱产业,房地产的稳定发展关乎国计民生。近几年,房

m0_64336780的博客 8827

二叉树的建立与遍历详解 菜鸟都能看懂的教程

树形结构要多利用递归来求解,递归的关键就是想清楚所有的基准情形,然后扩展到一般情况,写代码的时候最好把基准情况放在前面,把一般情况放在后面!定义二叉树结构体:typedef struct BinaryTreeNode { TelemType data; struct BinaryTreeNode *Left; struct BinaryTreeNode *Right; }N...

ac_blood的博客 4万+

SPD-Conv+YOLOv8:空间深度转换卷积赋能小目标检测,从原理到实战的科研级优化指南

从理解SPD-Conv“空间到深度+逐步卷积”的核心设计,到亲手将其嵌入YOLOv8并验证在小目标场景的表现,再到基于此探索属于自己的科研与工程方向——这个过程能让你深刻理解“小目标特征保留”在检测任务中的核心价值。现在就开始行动,相信你会在小目标检测的“细节捕捉”之路上,走出一条属于自己的技术路径。实验通常会证明:嵌入SPD-Conv后,YOLOv8在小目标AP上提升5-8个百分点,mAP50-95提升3-5个百分点,而推理速度仅下降5%以内,充分体现了其“保细节+提精度”的优势。

m0_64661770的博客 161

关于二叉树前中后序遍历的常见问题

尊敬的读者您好:笔者很高兴自己的文章能被阅读,但原创与编辑均不易,所以转载请必须注明本文出处并附上本文地址超链接以及博主博客地址:https://blog.csdn.net/vensmallzeng。若觉得本文对您有益处还请帮忙点个赞鼓励一下,笔者在此感谢每一位读者,如需联系笔者,请记下邮箱:zengzenghe@gmail.com,谢谢合作! 最近不论是笔试还是面试,都经常性...

Vensmallzeng的博客 4626

Open3D点云数据处理(六):点云、mesh可视化(Visualizer类)

本文介绍了Open3D中Visualizer类可视化几何对象的方法,给出了常用参数解释和代码示例。

孙悟空 3025

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

二叉树的基本操作精集(创建、遍历、求深度结点以及叶子结点个数)

对于二叉树的操作一般的我们使用递归的方法,因为在二叉树中每一个子树又是一颗二叉树。 这篇代码主要是演示了二叉树的以下操作 二叉树的创建 二叉树的三种遍历 求解二叉树的高度 求解指定层数的结点个数 求解二叉树的叶子结点个数 /********************************************************* - Copyright (C): 2016 - File

Zxn、Sirius荣耀之路 4267

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

二叉树的创建与遍历

C语言 数据结构实验四 二叉树的创建与遍历 【实验内容】 按扩展先序遍历序列输入二叉树中结点的值,(用‘#’表示空),构造一棵二叉树; 1、 以递归算法实现二叉树的先序、中序、后序遍历; 2、求·二叉树的深度和结点个数; 3、 实现二叉树的层次遍历(采用队列实现)。 typedef char TElemType; typedef struct BiTnode { TElemType data; //保存树结点的数据元素,比如字符A、B、C等 str

m0_51406138的博客 400

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

已知二叉树的中序遍历序列和后序遍历序列,求前序遍历序列

#include <bits/stdc++.h> using namespace std; char* in = (char *)malloc(sizeof(char)); char* post = (char *)malloc(sizeof(char)); struct node { char data; node *left, *right; }; node *create(int postL, int postR, int inL, int inR) { i.

qq_44850725的博客 7620

二叉树遍历和创建过程分析

二叉树的遍历分三种情况: 对这样一个二叉树来说 1.先序遍历 A -> B -> C 2.中序遍历 B -> A -> C 3.后序遍历 B -> C -> A 任何二叉树都可以看作这样的一个简单的模型,只是图内的节点对应的子树各不相同。其中A为根节点。 对这样的二叉树,我们可以把遍历整个二叉树看作一个主问题,而遍历时遍历每一个子节点对应的子树的过程看作一个子问题。比如我要遍历这颗二叉树。我们先从A出发,遍历到B,此时B为A的左子树的根节点.

m0_60777643的博客 640

二叉树的创建与销毁

一、根据先序遍历和中序遍历创建二叉树 1、根据中序遍历的结果能确定一棵树吗? 中序遍历:结果为:“12345”,这个“12345”能确定一棵树吗? 请思考,会有多少种形状。 2、如何才能确定一棵树? 结论:     通过中序遍历和先序遍历可以确定一个树 通过中序遍历和后续遍历可以确定一个树 通过先序遍历和后序遍历确定不了一个树。 单独先序遍历:能求解根,但不能求解左子

bbs375的博客 1万+

二叉树的操作:创建、遍历、求树的深度、叶子结点数

二叉树认识二叉树在计算机科学中,二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。在该图中,用’#’表示空节点,我们真正要创建的树为有ABCD字符。先序遍历的方式创建二叉树int creatBitree(struct Bitnode *(*T)) { char data; // data = getc

樊茂林的博客 3959

二叉树的创建与遍历的应用(C++代码实现)

多说无益,直接上代码 #include <iostream> using namespace std; typedef struct btree{ int data; btree *left,*right; }*pointer; void creatbtree(pointer&t){ int num;cin>>num; if(num==0) t=NULL; else{ t=new btree; .

执的博客 645

二叉树遍历的递归算法程序

二叉树的遍历是典型的递归算法。所谓树的遍历是指按某条搜索路径访问树中每个结点,使得每个结点均被访问一次,而且仅被访问一次。我的程序给出了二叉树的先序遍历,中序遍历,后序遍历和求二叉树的深度。程序如下:  #include  #include  #include  #define OK 1 #define ERROR 0 #define OVERFLOW -2 #define MAX(a,b) 

我的仓库 My Storehouse 4443

二叉树的遍历操作

一、操作要求 1.假设二叉树的结点值是字符,先根据输入一棵二叉树标明空子树的完整先根遍历序列或者根据输入一棵二叉树的先根遍历序列和中根遍历序列或者根据输入一棵二叉树的后根遍历序列和中根遍历序列,建立一棵以二叉链表表示的二叉树,并输出建立后的二叉树的先根、中根、后根遍历序列,观察其建立的二叉树是否正确; 2.复制上述建立的二叉树,并输出复制后的二叉树的后根遍历序列,观察其复制操作是否正确; 3.判断复制后形成的二叉树是否与原二叉树相等,如果相等,则报告“这两棵树是相等的,复制操作成功”,否则报告“这两棵

奈川直子 3454

二叉树的创建及遍历实验 matlab,【二叉树的建立和遍历实验报告】 二叉树的遍历实验心得...

[题目] 建立二叉树并求指定结点路径、深度、叶子个数和左右子树交换。[问题描述]要求能够按先序遍历次序输入二叉树 中结点的值来构造二叉树T;然后用递归和非递归算法实现二叉树T 的中序遍历;接着编写算法实现求二叉树T中指定结点的路径,即从键盘输入二叉树T 的任一结点,可以输出从根结点到该 结点所经历的结点;最后编写二叉树的三个应用算法(求二叉树的深度、求二叉树的叶子结点个数、将二叉树左右子树交换)。...

weixin_32746239的博客 1705

【数据结构】二叉树的构造与遍历练习

二叉树实验。时间:2020-5-27。

sailven的博客 2838
上一篇: 继承和多态 3.0 -- 菱形继承
下一篇: 二叉树 2.0 -- 非递归遍历
NeilZhy
博客等级 码龄11年 175粉丝 145原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值