树的孩子兄弟链存储表示创建、遍历等算法

news2025/7/7 14:45:26

【实验目的】

1. 掌握树的孩子兄弟链存储表示。

2. 掌握树的创建、遍历等算法。

【问题描述】

树的创建及其操作。

【基本要求】

1. 创建树的孩子兄弟链式存储表示。假设以二元组(F,C)的形式输入一颗树的诸边,其中F表示双亲结点标识,C表示孩子结点标识,且在输入的二元组序列中,C是按层次序列顺序出现的。F=’^’时C为根结点标识,若C也为’^’,则表示输入结束。例如,如下所示树的输入序列为;

          

 

2. 按树状打印树。例如:假设树上每个结点所含数据元素为单个字母,左下图树印为右下形状。

                                                                        

3. 统计树的叶子结点个数;

4. 计算树的高度;

5. 给出树的先根遍历序列、后根遍历序列和层次遍历序列;

6. 输出树中从根结点到所有叶子结点的路径。

【测试数据】

       自行设定

  • 需求分析:包含题目要求,程序功能,运行方式,测试数据等

题目要求用孩子兄弟链表结构表示树,并按照特定的输入方法去创建树,并将树打印。需要创建结构体CSNode,将数据类型定义为char,在主函数中设置输入,在运行时输入相应的字符,创建孩子兄弟树。

typedef struct CSNode{
    char data;
    struct CSNode *firstchild,*nextsibling;
}CSNode,*CSTree;

 同时先预设队列和相关实现队列操作的函数与结构体,用于实现统计树的叶子结点个数和输出树中从根结点到所有叶子结点的路径。

typedef struct {
    CSTree  *base;  // 动态分配存储空间
    int  front;    // 头指针,若队列不空,指向队列头元素
    int  rear;     // 尾指针,若队列不空,指向队列尾元素的下一个位置
} SqQueue; 

按特定形状打印树:即是按先根遍历去打印树,同时运用递归的方法来打印孩子兄弟,打印孩子时深度加一,打印兄弟时深度不变,所以用一个数字n表示深度,用for循环结合n打印制表符来表示树的深度。

if(T){
        for(int i = 0;i<n;i++){
            cout<<"\t";//按深度打印制表符
        }
        cout<<T->data;//打印数据
        cout<<endl;//换行打印孩子
        printTree(T->firstchild,n+1);//递归打印孩子,深度加1
        printTree(T->nextsibling,n);//递归打印兄弟
    }

二、概要设计:包含抽象数据类型定义,程序模块等

第一个模块定义CSNode结构体,创建孩子兄弟链表,相应的指针。

    char data;

通过struct CSNode *firstchild,*nextsibling;可知CSNode是一个递归的结构体。

定义创建孩子兄弟树,和孩子兄弟树结点的函数。

CSTree GetTreeNode(char ch){//创建结点
    CSTree CST = new CSNode;
    CST->data = ch;
    CST->firstchild = NULL;
    CST->nextsibling = NULL;
    return CST;
}

创建树,P = GetTreeNode(ch)创建结点,指针入队,fa == ^表示没有父结点,即创建结点为根结点,取队列头元素(指针值),查询双亲结点,不存在孩子结点时链接第一个孩子结点,否则链接兄弟结点。

定义顺序队列SqQueue相应的内容,数据,左右孩子指针,头尾指针,创建需要用到的函数,InitQueue构造一个空队列Q;EmptyQueue判断队列是否空;GetHead返回队列Q的队头元素,不修改队头指针;EnQueue插入元素e为Q的新的队尾元素;DeQueue若队列不空,则删除Q的队头元素,否则退出程序报错。相应的需要用到的基本算法,再用这些算法去实现题目所要求的遍历算法和统计结点,路径。

bool EmptyQueue(SqQueue Q){
    //判断队列是否空
    return Q.front == Q.rear;
}

int  QueueLength (SqQueue Q) {
    //返回Q的元素个数,即队列的长度
    return (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;
}

CSTree GetHead(SqQueue Q) {
    //返回队列Q的队头元素,不修改队头指针
    if ( Q.front != Q.rear )
        return Q.base[Q.front];
    else
        return 0;
}

void EnQueue(SqQueue&Q,CSTree e) {
    // 插入元素e为Q的新的队尾元素
    if((Q.rear+1) %MAXQSIZE ==Q.front){
        cout<<"队列满";
        exit(0); //队列满
    }
    Q.base[Q.rear] = e;
    Q.rear = (Q.rear+1) % MAXQSIZE;
}

void DeQueue (SqQueue&Q) {
    //若队列不空,则删除Q的队头元素,
    //否则退出程序报错
    if (Q.front==Q.rear)  exit(0);
    Q.front = (Q.front+1) % MAXQSIZE;
}

第二个模块用来定义相应的算法, CountLeaf(CSTree T)用于统计树的叶子结点个数,TreeDepth(CSTree T)用于计算树的高度,PreOrderTraverse(CSTree T)先根遍历树,InOrderTraverse(CSTree T)后根遍历树,LevelOrderTraverse(CSTree T)层次遍历树,AllPath(CSTree T,SqQueue Q)用于输出根结点到叶子结点的路径。

       第三个模块是主函数模块,用来实现进入算法和输出函数返回值,输出正确的题目和所要求的结果。同时用于初始化孩子兄弟树与队列,按顺序调用的算法函数和endl,让最后运行程序时简洁美观。

int main()
{
    CSTree CST;SqQueue Q;
    CreatTree(CST);InitQueue(Q);
    printTree(CST,0);
    cout<<"树的叶子个数为:"<<CountLeaf(CST)<<endl;
    cout<<"树的高度为:"<<TreeDepth(CST)<<endl;
    cout<<"树的先根遍历为:";PreOrderTraverse(CST);cout<<endl;
    cout<<"树的后根遍历为:";InOrderTraverse(CST);cout<<endl;
    cout<<"树的层次遍历为:";LevelOrderTraverse(CST);cout<<endl;
    cout<<"树从根结点到所有叶子结点的路径:"<<endl;AllPath(CST,Q);
    return 0;
}
详细设计:抽象数据类型以及程序模块的具体实现,算法设计思想
统计树的叶子结点个数:设置静态的int static num做计数数据,当没有没有孩子即为叶子结点,计数+1,否则即是按递归遍历孩子兄弟,最后返回n,即是叶子结点个数。
int CountLeaf(CSTree T){//统计树的叶子结点个数
    int static num=0;
    if(T){
        if(!T->firstchild)//没有孩子即为叶子结点,计数+1
          num++;
        CountLeaf(T->firstchild);//遍历孩子
        CountLeaf(T->nextsibling);//遍历兄弟
    }
    return num;
}
计算树的高度:空树时返回0,树高度为0。定义h1,h2分别表示孩子、兄弟的高度,并递归计算,返回两者中较大值,即为树的高度。
int TreeDepth(CSTree T){//计算树的高度
    if(T == NULL) return 0;//空树时返回0
    else{
        int h1 = TreeDepth(T->firstchild);//孩子高度
        int h2 = TreeDepth(T->nextsibling);//兄弟高度
        return (h1+1>h2)?(h1+1):h2;//返回大的值
    }
}
给出树的先根遍历序列、后根遍历序列:先根遍历与后根遍历较为简单,只需要根据遍历的定义按顺序输出孩子兄弟,即输出了相应的序列。
void PreOrderTraverse(CSTree T) {//先根遍历
    if(T) {
        cout<<T->data<<" ";
        PreOrderTraverse(T->firstchild);
        PreOrderTraverse(T->nextsibling);
    }
}

void InOrderTraverse(CSTree T) {//后根遍历
    if(T) {
        InOrderTraverse(T->firstchild);
        cout<<T->data<<" ";
        InOrderTraverse(T->nextsibling);
    }
}
输出树的层次序列:需要用到队列辅助输出层次序列,队列创建并初始化后,先让根结点入队,队列非空时,根据队列长度输出结点并出队,指向下一个孩子结点,在p非空时继续遍历入队,让p指向兄弟结点,循环上述方法直到树遍历完成。
void LevelOrderTraverse(CSTree T){//层次遍历
    SqQueue Q;
    InitQueue(Q);//队列初始化
    if(T==NULL) return;
    CSTree p = T;
    EnQueue(Q,p);//根结点入队
        while (!EmptyQueue(Q)) {
            int width = QueueLength(Q);//队列长度
            for(int i = 0;i<width;i++){
                p = GetHead(Q);
                cout<<p->data<<" ";//输出结点
                DeQueue(Q);//出队
                p = p->firstchild;//指向下一个孩子结点
                while (p) {//p非空时继续遍历
                    EnQueue(Q,p);//入队
                    p = p->nextsibling;//指向兄弟结点
                }
            }
        }
}

输出树中从根结点到所有叶子结点的路径:同样是要用队列辅助输出,但队列要定义在主函数中,因为要用到递归,队列定义在主函数中保证路径输出正确。根结点入队,当没有孩子时输出路径,否则指向孩子,递归孩子,循环入队直到该路径输出。一条路径输出之后指向根结点兄弟,重复上面的方法,直到所有路径输出完成。

void AllPath(CSTree T,SqQueue Q){//输出根结点到叶子结点的路径
    if(T){
        EnQueue(Q,T);//根结点入队
        if(!T->firstchild){//没有孩子时输出路径
            for(;QueueLength(Q)>1;DeQueue(Q)){
                cout<<GetHead(Q)->data<<" ";
            }
            cout<<GetHead(Q)->data<<endl;
        }else {
            T = T->firstchild;//否则指向孩子
            while (T) {
                AllPath(T,Q);//递归孩子,即递归该路径
                T = T->nextsibling;//指向兄弟
            }
        }
    }
}

四、调试分析:包括算法的时间复杂度和空间复杂度分析等

       树的先根遍历序列、后根遍历用到了递归,时间复杂度均为O(n),辅助空间即树的深度,所以空间复杂度也为O(n)。

按树状打印孩子兄弟树同理,但因为需要按深度打印制表符,所以时间复杂度为O(n2),空间复杂度为O(n)。

       树的层次遍历,因为需要用到队列,出队和入队,同时需要递归遍历孩子兄弟,辅助空间较多,同时用到队列空间和树CSNode空间,空间复杂度为O(n2),时间复杂度为O(n)。

       统计叶子结点个数的算法较为简单,只使用了递归遍历,对含n个结点的二叉树,时间复杂度均为O(n),辅助空间即树的深度,所以空间复杂度也为O(n)。

输出根结点到所有叶子结点的路径中,要用到队列,输出队列中的内容,加上需要递归子树,所以时间复杂度为O(n2),空间复杂度也为空间复杂度为O(n2)。

在层次遍历孩子兄弟树时,没有正确的递归孩子兄弟,递归了传入算法的树,让其入队,相当于重复入队其首结点并输出,导致层次序列一直输出首结点直到队列满,后来发现是需要在递归函数的参数中传入队头的子树,才能正确递归孩子兄弟,这样才正确入队和出队,完成输出层次遍历树的目的。

统计叶子结点时定义n为全局变量,封装性不够好,在递归时最好定义静态static的数据,这样保证了数据的封装性也保证了输出能够正确,同时不破坏程序的模块化。

输出根结点到所有叶子结点的路径时,错误的对形参采用了取地址的符号&,导致递归的封装性被破坏,取到队列的未知地址,整个函数的输出完全错误,后来经过仔细检查后发现不能取地址,而是直接对队列进行调整入队,这样才能输出正确的路径。

五、测试结果:提供试验结果和数据,测试所有操作结果的正确性


测试数据1:

可见所有数据正确

测试数据2:

可见所有数据正确:

头文件及源程序

 

#include <iostream>
#include <stack>

using namespace std;

#define MAXQSIZE  100  //最大队列长度

typedef struct CSNode{
    char data;
    struct CSNode *firstchild,*nextsibling;
}CSNode,*CSTree;

typedef struct {
    CSTree  *base;  // 动态分配存储空间
    int  front;    // 头指针,若队列不空,指向队列头元素
    int  rear;     // 尾指针,若队列不空,指向队列尾元素的下一个位置
} SqQueue;

void InitQueue (SqQueue &Q) {
    // 构造一个空队列Q
    Q.base = new CSTree[MAXQSIZE];
    if(!Q.base) exit(0);             // 存储分配失败
    Q.front = Q.rear = 0;
}

bool EmptyQueue(SqQueue Q){
    //判断队列是否空
    return Q.front == Q.rear;
}

int  QueueLength (SqQueue Q) {
    //返回Q的元素个数,即队列的长度
    return (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;
}

CSTree GetHead(SqQueue Q) {
    //返回队列Q的队头元素,不修改队头指针
    if ( Q.front != Q.rear )
        return Q.base[Q.front];
    else
        return 0;
}

void EnQueue(SqQueue&Q,CSTree e) {
    // 插入元素e为Q的新的队尾元素
    if((Q.rear+1) %MAXQSIZE ==Q.front){
        cout<<"队列满";
        exit(0); //队列满
    }
    Q.base[Q.rear] = e;
    Q.rear = (Q.rear+1) % MAXQSIZE;
}

void DeQueue (SqQueue&Q) {
    //若队列不空,则删除Q的队头元素,
    //否则退出程序报错
    if (Q.front==Q.rear)  exit(0);
    Q.front = (Q.front+1) % MAXQSIZE;
}

CSTree GetTreeNode(char ch){//创建结点
    CSTree CST = new CSNode;
    CST->data = ch;
    CST->firstchild = NULL;
    CST->nextsibling = NULL;
    return CST;
}

void CreatTree(CSTree &T){//创建树
    CSTree P,s,r;
    T = NULL;
    SqQueue Q;InitQueue(Q);//队列创建及初始化
    char fa,ch;
    for(cin>>fa,cin>>ch;ch!='^';cin>>fa,cin>>ch){
        P = GetTreeNode(ch);//创建结点
        EnQueue(Q,P);//指针入队
        if(fa == '^') T=P;//fa == ^表示没有父结点,即创建结点为根结点
        else{//不为根结点时
            s = GetHead(Q);//取队列头元素(指针值)
            while (s->data != fa){//查询双亲结点
                DeQueue(Q);s = GetHead(Q);
            }
            if(!(s->firstchild)){
                s->firstchild = P;//链接第一个孩子结点
                r = P;//r指向尾端
            }else{
                r->nextsibling = P;//链接兄弟结点
                r = P;//r指向尾端
            }
        }
    }
}

void printTree(CSTree T,int n){//打印树,n表示深度
    if(T){
        for(int i = 0;i<n;i++){
            cout<<"\t";//按深度打印制表符
        }
        cout<<T->data;//打印数据
        cout<<endl;//换行打印孩子
        printTree(T->firstchild,n+1);//递归打印孩子,深度加1
        printTree(T->nextsibling,n);//递归打印兄弟
    }
}

int CountLeaf(CSTree T){//统计树的叶子结点个数
    int static num=0;
    if(T){
        if(!T->firstchild)//没有孩子即为叶子结点,计数+1
          num++;
        CountLeaf(T->firstchild);//遍历孩子
        CountLeaf(T->nextsibling);//遍历兄弟
    }
    return num;
}

int TreeDepth(CSTree T){//计算树的高度
    if(T == NULL) return 0;//空树时返回0
    else{
        int h1 = TreeDepth(T->firstchild);//孩子高度
        int h2 = TreeDepth(T->nextsibling);//兄弟高度
        return (h1+1>h2)?(h1+1):h2;//返回大的值
    }
}

void PreOrderTraverse(CSTree T) {//先根遍历
    if(T) {
        cout<<T->data<<" ";
        PreOrderTraverse(T->firstchild);
        PreOrderTraverse(T->nextsibling);
    }
}

void InOrderTraverse(CSTree T) {//后根遍历
    if(T) {
        InOrderTraverse(T->firstchild);
        cout<<T->data<<" ";
        InOrderTraverse(T->nextsibling);
    }
}

void LevelOrderTraverse(CSTree T){//层次遍历
    SqQueue Q;
    InitQueue(Q);//队列初始化
    if(T==NULL) return;
    CSTree p = T;
    EnQueue(Q,p);//根结点入队
        while (!EmptyQueue(Q)) {
            int width = QueueLength(Q);//队列长度
            for(int i = 0;i<width;i++){
                p = GetHead(Q);
                cout<<p->data<<" ";//输出结点
                DeQueue(Q);//出队
                p = p->firstchild;//指向下一个孩子结点
                while (p) {//p非空时继续遍历
                    EnQueue(Q,p);//入队
                    p = p->nextsibling;//指向兄弟结点
                }
            }
        }
}

void AllPath(CSTree T,SqQueue Q){//输出根结点到叶子结点的路径
    if(T){
        EnQueue(Q,T);//根结点入队
        if(!T->firstchild){//没有孩子时输出路径
            for(;QueueLength(Q)>1;DeQueue(Q)){
                cout<<GetHead(Q)->data<<" ";
            }
            cout<<GetHead(Q)->data<<endl;
        }else {
            T = T->firstchild;//否则指向孩子
            while (T) {
                AllPath(T,Q);//递归孩子,即递归该路径
                T = T->nextsibling;//指向兄弟
            }
        }
    }
}

int main()
{
    CSTree CST;SqQueue Q;
    CreatTree(CST);InitQueue(Q);
    printTree(CST,0);
    cout<<"树的叶子个数为:"<<CountLeaf(CST)<<endl;
    cout<<"树的高度为:"<<TreeDepth(CST)<<endl;
    cout<<"树的先根遍历为:";PreOrderTraverse(CST);cout<<endl;
    cout<<"树的后根遍历为:";InOrderTraverse(CST);cout<<endl;
    cout<<"树的层次遍历为:";LevelOrderTraverse(CST);cout<<endl;
    cout<<"树从根结点到所有叶子结点的路径:"<<endl;AllPath(CST,Q);
    return 0;
}

仅供参考,求点赞收藏~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python的opencv操作记录(九)——图像清晰度计算

文章目录图像清晰度计算的一般思路图像梯度图像梯度绝对值与梯度角度基于梯度的方式计算梯度算子1——Sobel算子计算梯度算子2——Laplacian算子梯度统计评分平均梯度梯度总和Demo图像清晰度计算的一般思路 定义图像清晰度是一个比较定制化&#xff0c;或者说比较偏业务属性的…

MySql面试

0. InnoDB与MyISAM的区别 1&#xff09;InnoDB支持事务&#xff0c;MyISAM不支持&#xff0c;对于InnoDB每一条SQL语言都默认封装成事务&#xff0c;自动提 交&#xff0c;这样会影响速度&#xff0c;所以最好把多条SQL语言放在begin和commit之间&#xff0c;组成一个事务&…

【Vue3+TS】Axios拦截器封装及跨域 [cors] 解决方案

【Vue3TS】Axios拦截器封装及跨域 [cors] 解决方案简述封装过程文件路径拦截器封装 —— Interceptor.tsAPI请求管理前端跨域的解决方案后端跨域的解决方案效果结语简述 我的项目采用 Vue3TypeScriptViteElement Plus 的组合&#xff0c;这个组合也是Vue版本退出3.x后官方推荐版…

记一次服务宕机、优化全流程(以后也可以装X了)

视频地址&#xff1a; https://www.bilibili.com/video/BV1924y1y7jN 221115上午10点的时候客户反应进入小程序慢&#xff0c;打开监控发现服务pv已经超过了历史之最&#xff08;印象中最高的是100w&#xff09;&#xff0c;这次到了400w。原因是因为推广了一个发红包的活动。 …

Java练习题第二十七期:幸运的袋子

作者&#xff1a;有只小猪飞走啦 博客地址&#xff1a;文章目录前言一&#xff0c;题目二&#xff0c;解析三&#xff0c;代码前言 本博客是小博主在做Java算法题的过程中一些觉得可以分享的题目&#xff0c;希望对你们有帮助&#xff0c;如果哪里写错了或者有更好的解法&…

详解Unity中的Nav Mesh新特性|导航寻路系统 (一)

前言 之前我们讲解过Unity的Nav Mesh系统&#xff0c;其中提到过这个新版的Nav Mesh&#xff0c;它解决现有Nav Mesh的几个缺陷&#xff0c;比如无法动态烘焙&#xff0c;无法按照Agent的半径和高度适当的判断可行路径。现在新版Nav Mesh可以彻底解决这个问题&#xff01;某种…

实验送样、数据分析样品、组名命名规范

俗话说巧妇难为无米之炊&#xff0c;而样品就是“米”&#xff0c;没有样品&#xff0c;就无法开展实验&#xff0c;无法获得数据&#xff0c;无法毕业&#xff0c;无法发文章。鉴于样品的重要性&#xff0c;非常有必要对样品进行详细且规范的记录&#xff0c;方便他人也方便自…

Java 线上机器 CPU 100 的一次排查过程

文章目录1. 问题发生2. 数据库连接关闭问题排查3. 问题的进一步排查4. 解决方法1. 问题发生 日常敲代码突然收到生产环境异常告警&#xff0c;线上有一台机器 CPU 使用率飙升到 100 触发扩容&#xff0c;工作群里一下子鸡飞狗跳。 出现问题&#xff0c;首先当然是查看监控和日…

在群晖NAS上搭建导航页_通过Web Station搭建

一、业务需求 1.1、需求说明 我们在使用群晖NAS的过程中&#xff0c;随着时间的推移会安装各种各样的软件内容和管理工具&#xff0c;而这些内容又都是一些网页界面&#xff08;特别是一些在Docker中搭建的工具&#xff09;时间久了我们也记不住那么多工具的Web界面地址&#…

激活Windows时出现错误代码0xC004C003怎么办?

Windows是我们最常见的电脑操作系统&#xff0c;那么如果我们在尝试激活Windows时出现错误代码0xC004C003&#xff0c;应该如何解决&#xff1f; 什么是Windows激活错误0xC004C003&#xff0c;出现该错误的原因是什么&#xff1f; Windows操作系统为了抑制盗版软件&#xff0c…

3D建模就业前景如何?加班多吗?值不值得入行

加班其实都还好&#x1f914;&#xff0c;因为这个岗位是按照项目进度考核&#xff08;算钱&#xff09;的&#xff0c;老手做一个模型要5,6个小时&#xff0c;新手可能需要10个小时&#xff0c;新人刚入行&#xff0c;做东西效率跟不上&#x1f630;需要加班来弥补是肯定有的事…

SpringMVC-整合详解

SpringMVC-整合详解 MVC 什么是MVC? 它是一种开发模式&#xff0c;它是模型视图控制器的简称。所有的web应用都是基于MVC开发的 M: 模型层&#xff0c;它是模型视图控制器的简称。所有的web应用都是基于MVC开发 V: 视图层,html、javascript、vue等都是视图层&#xff0c;用…

高校实验室设备管理系统设计与实现-计算机毕业设计源码+LW文档

数据库代码&#xff1a; /* Navicat MySQL Data Transfer Source Server : mysql5 Source Server Version : 50562 Source Host : localhost:3306 Source Database : ssmgxsyssbglxthsg3511cg ​ Target Server Type : MYSQL Target Server Versio…

Linux磁盘分区和管理

文章目录一 添加硬盘&#xff0c;创建Linux分区1.首先准备一块新的硬盘2.检查系统是否识别了硬盘3.对磁盘进行分区3-1 创建MBR磁盘分区3-2 创建文件系统3-3 挂载文件系统二 创建交换空间2-1 创建分区2-2 设置分区类型2-3 格式化交换空间2-4 激活交换空间三 删除磁盘的分区3-1 备…

【GPU】Nvidia CUDA 编程高级教程——利用蒙特卡罗法求解近似值(CUDA-Aware MPI)

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

11.24直播预告 | AIGC,看热闹不如看门道

如果把AI比作既富含能源&#xff0c;又无限神秘的海域&#xff0c;那么AIGC这条近半年内流经学术界和创投圈的支流&#xff0c;也无疑既带来了无数机遇&#xff0c;又蕴藏未知风险。 几天前&#xff0c;将门-TechBeat社区的专题&#xff08;《AIGC的八大前沿创新》&#xff09;…

Allegro基本规则设置指导书

Allegro基本规则设置指导书 下面介绍基本规则设置指导书之Analysis Modes 点击set-up-constrains-Modes 调出Analysis Modes,这个是所有DRC的总开关 下面介绍常用的一些开关设置 Design Options (Soldermask) 从上往下 阻焊到阻焊的间距 阻焊到pad和走线间距 阻焊到shape…

leecode #加一#二进制求和

题目描述&#xff1a; 给定一个由 整数 组成的 非空 数组所表示的非负整数&#xff0c;在该数的基础上加一。 最高位数字存放在数组的首位&#xff0c; 数组中每个元素只存储单个数字。 你可以假设除了整数 0 之外&#xff0c;这个整数不会以零开头。 分析&#xff1a;对数…

简单版的采用前后端分离模式实现SpingBoot新增查询功能

目录 后端代码编写 前端代码编写 首页展示&#xff1a; 新增&#xff1a; 开发工具&#xff1a;IDEA、HbuilderX 技术点&#xff1a;后端&#xff1a;SpringBoot&#xff0c;前端&#xff1a;ElementUIvue,采用前后端分离模式实现。 后端代码编写 目录&#xff1a; 代码…

多线程高并发笔记

一、基础知识 1. 线程打断的三种方法 interrupt() 打断某个线程&#xff08;其实只是设置一个标志位&#xff09;isInterrupted() 查询某线程是否被打断过&#xff08;查询是否设置了标志位&#xff09;static interrupted() 查询当前线程是否被打断过&#xff0c;并重置打断…