二叉树的那些事

一篇关于二叉树的笔记。

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

 

//
//  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;
}

 

AI音乐YuE被看作是“开源音乐生成领域的DeepSeek”,旨在为音乐创作提供一个开放、强大且可自由定制的基础平台。它可以从歌词和音乐描述出发,生成包含专业人声和伴奏的完整歌曲,时长最长可达 5 分钟。它降低了音乐创作的门槛。 核心功能亮点 YuE的能力主要围绕长篇幅、高质量的歌曲生成,其核心功能总结如下: 功能类别 具体能力与支持范围 创作时长 可生成长达 5分钟 的完整歌曲,这是开源模型中少有的长篇幅生成能力。 音轨构成 能同时生成人声(主唱)和背景伴奏,实现真正的“歌曲”级创作。 多语言支持 支持英语、中文(含普通话和粤语)、日语、韩语等多种语言的歌词输入。 音乐风格 覆盖流行、金属、爵士、嘻哈、摇滚等多种流派。 风格控制 支持通过文本提示词,对音乐流派、乐器、情绪氛围、人声音色等进行细粒度控制。 情感匹配 能够分析歌词的情感基调,并生成与之匹配的音乐风格和旋律。 音频提示 支持使用已有的音频片段作为提示,来引导生成音乐的风格 YuE强大的生成能力源于其创新的技术架构。 模型架构:YuE采用了独特的双LLaMA语言模型架构。这个架构包含两个关键模型: Stage-1 模型 (7B参数):负责生成歌曲的宏观结构,包括歌词与旋律的总体对齐。 Stage-2 模型 (1B参数):基于Stage-1的粗线条,精细地生成丰富的音乐细节和完整伴奏。 创新技术: 双轨下一token预测 (Dual-NTP):这项技术让人声和伴奏在生成时保持同步与协调,解决了音乐生成中常出现的“音轨脱节”问题。 结构化渐进生成 (Structural Progressive Generation):它像写文章先列大纲一样,先生成歌曲的整体框架(主歌、副歌),再填充细节,确保了长篇幅音乐的结构连贯性。 语义增强音频分词器:这个模块能将歌词的语义与音乐信号深度绑定,帮助AI精准地匹配歌词的情感色彩
内容概要:本文围绕水下机器人双机械手系统的动态建模与控制仿真展开研究,基于Matlab平台构建了系统的运动学与动力学模型,实现了对双机械手耦合运动行为的精确建模,并设计了相应的控制策略进行仿真验证。研究涵盖系统参数初始化、参考轨迹设定、控制算法实现及模型调试优化等关键环节,重点解决了多自由度系统间的动态耦合、运动协调性与控制稳定性等问题,通过仿真结果验证了所建模型的准确性与控制策略的有效性,为复杂水下作业任务中机械手的高精度操控提供了理论依据与技术支撑。; 适合人群:具备一定自动化、机器人学或控制理论基础,从相关领域科研与工程开发的研究生、科研人员及工程师,尤其适合熟悉Matlab/Simulink仿真环境并关注水下机器人系统建模与控制的技术人员。; 使用场景及目标:①用于水下机器人双机械手系统的教学演示与科研建模;②支撑复杂机电系统动力学建模与先进控制算法开发;③为水下作业、远程操控、智能机器人等领域提供高保真仿真验证平台,目标是提升系统在复杂工况下的控制精度、响应速度与鲁棒性。; 阅读建议:建议读者结合提供的Matlab代码进行实践操作,重点关注参数配置文件与主仿真流程的衔接,调试过程中应逐步调整系统参数与控制增益以观察系统响应变化,深入理解动态建模中的耦合效应与控制策略的设计逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值