二叉树的那些事

一篇关于二叉树的笔记。

  • 广义表生成二叉树。
  • 二叉树前、中、后序遍历递归实现。
  • 二叉树前、中、后序遍历非递归实现。
  • 二叉树层次遍历
  • 二叉排序树(二叉搜索树)生成
  • 中序线索二叉树声生成、遍历。

 

//
//  main.cpp
//  二叉树前中后缀遍历之递归和非递归、层次遍历、中序线索二叉树建立、遍历
//
//  Created by scnulpc on 2018/10/16.
//  Copyright © 2018年 scnulpc. All rights reserved.
//

#include <iostream>
#include <stack>
#include <queue>
using namespace std;
struct treeNode
{
    char value;
    int ltag;
    int rtag;
    treeNode* left;
    treeNode* right;
    treeNode(char a):value(a),ltag(0),rtag(0),left(NULL),right(NULL){}
};
struct node
{
    int value;
    node *left,*right;
    node(int a):value(a),left(NULL),right(NULL){};
};
//广义表生成二叉树-非递归
treeNode* createTreeByList(char end)
{
    char ch;
    treeNode* root=NULL,* pre = NULL,*temp;
    stack<treeNode*> *s = new stack<treeNode*>();
    cin>>ch;
    int flag=2;
    while (true)
    {
        if (ch==end) break;
        switch (ch) {
            case '(':flag=0;s->push(pre);break;
            case ',':flag=1;break;
            case ')':flag=2;s->pop();break;
            default:
                if (flag==0)//'('
                { temp=s->top(); temp->left=new treeNode(ch);pre=temp->left;}
                else if(flag==1)//','
                {temp=s->top();temp->right=new treeNode(ch);pre=temp->right;}
                else if (flag==2)//')'
                {
                    if (root==NULL) {root=new treeNode(ch);pre=root;}
                }
                break;
        }
        cin>>ch;
    }
    return root;
}

//前序遍历-递归
void preOrder(treeNode*p)
{
    if (p==NULL) return;
    cout<<p->value<<" ";
    preOrder(p->left);
    preOrder(p->right);
}
//前序遍历-非递归
void preOrderND(treeNode*p)
{
    stack<treeNode*> s;
    s.push(p);
    treeNode* temp;
    while (!s.empty())
    {
        temp=s.top();
        s.pop();
        cout<<temp->value<<" ";
        if (temp->right!=NULL) s.push(temp->right);
        if (temp->left!=NULL) s.push(temp->left);
    }
    cout<<endl;
}
//中序遍历-递归
void midOeder(treeNode* p)
{
    if (p==NULL) return;
    midOeder(p->left);
    cout<<p->value<<" ";
    midOeder(p->right);
}
//中序遍历-非递归
//对于每个结点,先将最左子孙(如果存在的话),然后再次最左子孙,再次之
void midOrderND(treeNode*p)
{
    if (p==NULL) return;
    stack<treeNode*> s;
    treeNode* current = p;
    
    while ((!s.empty())||current!=NULL)
    {
        if (current!=NULL) {
            s.push(current);
            current=current->left;
        }
        else
        {
            current=s.top();
            s.pop();
            cout<<current->value<<" ";
            current=current->right;
        }
    }
    cout<<endl;
    
}
//后缀遍历-递归
void sufixOrder(treeNode* p)
{
    if (p==NULL) return;
    sufixOrder(p->left);
    sufixOrder(p->right);
    cout<<p->value<<" ";
}
//后缀遍历-非递归
//对于一个结点,先把它的左子树输出,回到它自己,再把它的右子树输出,再回到它自己,这时可以把它自己输出了
void sufixOrderND(treeNode* p)
{
    stack<treeNode*> s;
    int flag=0;         //flag:0 表示从左子树中返回。 flag:1 表示从右子树中返回
    //int move=1;         //move:1 一棵子树还没生成。 move:0 已经生成一颗子树,说明可以直接出栈回退
    treeNode* current=p;
    while (!s.empty()||current!=NULL)
    {
        if (current!=NULL) {
            s.push(current);
            current=current->left;
            flag=0;
        }
        else
        {
            if (flag)//从右子树中返回
            {
                current=s.top();s.pop();
                cout<<current->value<<" ";  //访问根结点
                
                // 从根结点返回判断current结点是父结点的左孩子还是右孩子
                if (s.empty()) break;
                treeNode* temp = s.top();
                if (current==temp->left) flag=0;
                else if (current==temp->right) flag=1;
                current=NULL;
                
            }
            else    //从左子树中返回
            {
                current=s.top();
                current=current->right;
                flag=1;
                
            }
        }
    }
    cout<<endl;
}
void LayerPrint(treeNode* p)
{
    queue<treeNode*> q;
    q.push(p);
    treeNode* current;
    while (!q.empty())
    {
        current=q.front();
        q.pop();
        cout<<current->value<<" ";
        if (current->left!=NULL) q.push(current->left);
        if (current->right!=NULL) q.push(current->right);
    }
    cout<<endl;
}
void Insert(node*& p,int value) //在以p为根节点的线索二叉树中插入一个数value
{
    if (p==NULL) {p=new node(value);return;}
    if(p->value==value) return ;
    if (value<p->value) Insert(p->left, value);
    if (value>p->value) Insert(p->right, value);
}
node* createSearchBinaryTree(int a[],int length)
{
    node* root =NULL;
    for (int i=0; i<length; i++) {
        Insert(root, a[i]);
    }
    return root;
}
void print(node *p)
{
    if (p==NULL) return;
    print(p->left);
    cout<<p->value<<" ";
    print(p->right);
}

//一般完全二叉树 生成 中序线索二叉树
treeNode*  first(treeNode* p)//找到以结点p为根节点的子树在中序下的第一个结点
{
    if (p==NULL) return p;
    while (p->ltag==0) {
        p=p->left;
    }
    return p;
}
treeNode* last(treeNode* p)//找到以结点p为根节点的树在中序下的最后一个结点
{
    if (p==NULL) return NULL;
    while (p->rtag==0) {
        p=p->right;
    }
    return p;
}
void createMidThreadBinaryTree(treeNode* p,treeNode* &pre) //线索化以p为根的子树  pre: p的在中序遍历下的前驱
{
    if(p==NULL)return;
    createMidThreadBinaryTree(p->left, pre);
    if (p->left==NULL&&p->ltag==0) {p->left=pre;p->ltag=1;}     //线索化p的前驱
    if(pre!=NULL&&pre->right==NULL){pre->right=p;pre->rtag=1;}  //线索化前驱pre的后继
    pre=p;
    createMidThreadBinaryTree(p->right, pre);
}
void createMidThreadBinaryTree(treeNode* p)
{
    treeNode* t = NULL;
    createMidThreadBinaryTree(p, t);
    if (p==NULL) return;
    treeNode* temp = p;     //别忘了最后一个结点的后驱置空
    while (temp->right!=NULL) {
        temp=temp->right;
    }
    temp->rtag=1;
    
}
//遍历中序线索二叉树

treeNode* Next(treeNode* p)//找到结点P的后驱
{
    if (p==NULL) return NULL;
    if (p->rtag==1) return p->right;
    else return first(p->right);
    
}
void printMidThreadBinaryTree(treeNode* p)
{
    treeNode* one = first(p);
    if (one==NULL) return;
    cout<<one->value<<" ";
    treeNode* next = Next(one);
    while (next!=NULL) {
        cout<<next->value<<" ";
        next = Next(next);
    }
    cout<<endl;
    
}
//A(B(C(D,E)),F(G,H))#
int main(int argc, const char * argv[])
{
    treeNode* head = NULL;
    cout<<"输入广义表,以#结束"<<endl;
    head=createTreeByList('#');
    cout<<"前序遍历"<<endl;
    preOrder(head);
    cout<<endl;
    preOrderND(head);
    cout<<"中序遍历"<<endl;
    midOeder(head);
    cout<<endl;
    midOrderND(head);
    cout<<"后缀遍历"<<endl;
    sufixOrder(head);
    cout<<endl;
    sufixOrderND(head);
    cout<<"层次遍历"<<endl;
    LayerPrint(head);
    cout<<"生成二叉搜索树"<<endl;
    int a[] = {2,3,7,8,9,5,1,4,0,13,7,8,9,23};
    node * root = createSearchBinaryTree(a,14);
    print(root);
    cout<<endl;
    
    cout<<"生成中序线索二叉树"<<endl;
    createMidThreadBinaryTree(head);
    cout<<"遍历中序线索二叉树"<<endl;
    printMidThreadBinaryTree(head);
    return 0;
}

 

内容概要:本文系统研究了全桥LLC谐振变换器的脉冲频率调制(PFM)控制策略,深入剖析其拓扑结构与工作原理,涵盖全桥逆变电路、谐振回路(Lr、Cr、Lm)、变压器及整流滤波电路的功能与协同机制。文章详细分析了变换器在不同开关频率下的三种工作模式(fs > fr、fs = fr、fm < fs < fr),阐明了其在感性区域实现原边零电压开通(ZVS)和副边零电流关断(ZCS)的软开关特性。重点阐述了PFM控制通过调节开关频率来改变谐振阻抗,从而稳定输出电压的基本原理,并论证了其在高效率(尤其轻载时)、低电磁干扰(EMI)和宽输入输出范围方面的显著优势。研究构建了基于Matlab/Simulink的完整仿真模型,对系统的稳态性能、动态响应(负载突变)和效率进行了全面仿真验证,结果证实PFM控制能有效实现输出电压的精确稳定,具备优良的动态响应能力和全负载范围内的高效率。最后,文章总结了PFM策略的有效性,并展望了结合自抗扰控制(ADRC)等先进算法优化控制性能及开展硬件实验验证的未来发展方向。; 适合人群:具备电力电子、自动控制或相关领域基础知识的研究生、科研人员及从高性能电源设计的工程技术人员。; 使用场景及目标:①深入理解LLC谐振变换器的拓扑结构、工作模式划分及其软开关物理机制;②掌握PFM控制策略的设计思想、参数整定方法及其在提升电源转换效率与降低EMI中的核心应用;③为开发高效率、高可靠性的开关电源(如通信电源、服务器电源)提供理论依据、仿真建模指导与性能优化的技术参考。; 阅读建议:在阅读时应紧密结合文中给出的仿真模型框图与关键波形,重点精读工作模式分析与PFM控制原理部分,建议动手复现仿真以深刻体会频率调节对增益和效率的影响规律,并特别关注轻载效率表现,同时思考未来展望中提及的先进控制算法融合方向,以激发创新研究思路。
内容概要:本文系统介绍了基于Matlab的多架无人机编队控制与轨迹规划技术实现方案,聚焦于一致性分布式控制、多领航者架构、编队跟随控制及轨迹跟踪等核心算法的建模与仿真。通过Matlab代码实现了多无人机系统的编队形成、保持与动态调整,并融合RRT、人工势场法、粒子群优化(PSO)、Q-learning等智能算法,完成复杂环境下的路径规划与避障任务。文档还深入探讨了滑模控制、反步法、模型预测控制(MPC)等多种先进控制策略在无人机协同中的应用,展现了系统在动态干扰和不确定环境下的鲁棒性与自适应能力。配套提供的完整Matlab代码涵盖多种编队模式与控制算法对比案例,支持二次开发与性能验证。; 适合人群:具备自动控制理论基础和Matlab编程能力的科研人员、研究生及从无人机系统开发的工程技术人员,尤其适用于研究多智能体协同控制、分布式编队与自主路径规划方向的专业人士。; 使用场景及目标:① 实现多无人机在复杂动态环境中的高效协同飞行与稳定编队;② 解决队形切换、轨迹实时优化与动态障碍物规避等关键问题;③ 为学术研究、毕业设计或实际工程项目提供可复现的算法框架与仿真平台支持; 其他说明:文中所有Matlab仿真代码可通过指定百度网盘链接下载,建议结合仿真运行深入理解算法细节,并根据具体应用场景进行参数调优与算法拓展。
内容概要:本文研究基于动态非合作博弈的大规模电动汽车实时优化调度决策方法,通过构建博弈论模型刻画电动汽车用户间的竞争行为,利用Matlab实现算法仿真与求解。研究将复杂的充电调度问题建模为动态非合作博弈形式,分析各电动汽车作为理性个体在电网负荷、电价及用户偏好等多重约束下的最优充放电策略,实现去中心化、分布式的实时调度优化。结合动态博弈理论与电力系统运行特性,文章深入探讨了纳什均衡的存在性、唯一性及迭代求解的收敛性,并通过仿真实验验证该方法在平抑电网负荷峰值、降低用户用电成本、提升可再生能源消纳能力以及增强电网运行稳定性方面的综合效益。; 适合人群:具备博弈论、优化理论、电力系统基础及相关数学建模能力,从智能电网、电动汽车调度、能源互联网、车网互动(V2G)等方向研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①应用于大规模电动汽车接入背景下的实时需求响应与分布式调度系统设计;②为电力公司制定动态电价机制、激励策略及负荷管理政策提供理论依据与技术支持;③促进车网互动技术的实际落地,推动新型电力系统中用户侧资源的高效协同与优化利用; 阅读建议:读者应结合提供的Matlab代码深入理解模型构建与算法实现细节,重点关注博弈模型的效用函数设计、约束条件处理、均衡求解过程及仿真参数设置,建议使用真实或模拟数据进行复现与拓展实验,以全面掌握其应用逻辑与优化潜力。
内容概要:本文系统研究了基于卡尔曼滤波的混合预编码技术在多用户毫米波大规模MIMO通信系统中的应用,旨在通过引入卡尔曼滤波算法优化信道估计与预编码矩阵的动态更新,提升系统的频谱效率、能量效率及信号传输可靠性。研究构建了完整的系统模型,涵盖毫米波信道建模、混合预编码架构设计、模拟与数字波束成形联合优化,并提供了详细的Matlab代码实现,覆盖仿真全流程,包括信道参数生成、预编码方案对比、性能指标计算等,具有较强的可复现性与工程参考价值。研究成果适用于未来高带宽、低延迟的无线通信系统设计与优化。; 适合人群:具备通信工程、电子信息、信号与信息处理等专业背景,熟悉MIMO系统原理、毫米波通信技术及阵列信号处理基础,并掌握Matlab编程技能的研究生、科研人员或相关领域工程师。; 使用场景及目标:①开展毫米波大规模MIMO系统中混合预编码算法的研究与性能评估;②复现先进预编码方案并进行对比实验;③支撑学术论文撰写、科研项目开发及通信系统原型仿真验证;④深入理解卡尔曼滤波在动态信道估计与自适应波束成形中的集成应用。; 阅读建议:建议读者结合文中Matlab代码逐模块运行与调试,重点分析卡尔曼滤波在信道状态信息(CSI)预测与反馈机制中的实现逻辑,关注算法在不同用户数、天线规模和信噪比条件下的性能变化,同时参考配套网盘资源获取完整代码包与仿真数据,以深化对系统级设计与算法优化的理解。
内容概要:本文系统介绍了时序数据的特点及其在物联网监控场景下的存储与处理挑战,并以TimescaleDB为核心解决方案进行深入讲解。文章从时序数据的定义出发,分析其高写入吞吐、大规模存储、固定查询模式和数据保留等核心挑战,对比多种时序数据库方案后突出TimescaleDB基于PostgreSQL的优势。重点内容包括超表(Hypertable)的自动时间分区机制、连续聚合提升查询性能、数据压缩节省存储空间以及自动化数据保留策略。文中还提供了完整的物联网监控平台实战设计,涵盖表结构搭建、索引优化、常用查询模式、数据摄入优化及日常运维监控方法,帮助读者构建高效稳定的时序数据系统。; 适合人群:具备一定数据库基础,从物联网、监控系统或大数据平台开发的1-3年经验研发人员或系统架构师。; 使用场景及目标:① 构建高性能物联网传感器数据采集与分析系统;② 优化现有PostgreSQL时序数据表的写入、查询与存储效率;③ 实现自动化的数据聚合、压缩与生命周期管理;④ 支撑PB级时序数据的长期稳定运行。; 阅读建议:此资源以实际案例驱动,强调工程实践与性能调优,建议读者结合本地环境动手部署TimescaleDB,逐步实现文中的超表创建、连续聚合、压缩与保留策略配置,并通过执行计划验证优化效果,深入理解其背后机制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值