二叉树结构的建立与遍历

2023-11-20

实验项目:

1编写建立二叉树的二叉链表存储结构(左右链表示)的程序,并以适当的形式显示和保存二叉树;

2.完成二叉树的7种遍历操作

3.给定一个二叉树, 编写算法完成下列应用:

1)判断其是否为完全二叉树;

2)求二叉树中任意两个结点的公共祖先。

输入示例(空子树以'#'表示):

ab##c##

 

#include <stdio.h>
#include <stdlib.h>
#define MAX_LEN 50
/*二叉树的二叉链表结构*/
typedef struct node
{
    struct node *lchild;
    struct node *rchild;
    char data;
}BTREE;
/*栈的数组实现*/
typedef struct
{
    int top;
    BTREE *a[MAX_LEN]; //结构体数组,每个元素均为一个结点
}Stack;
/*队列的数组实现*/
typedef struct
{
    BTREE *a[MAX_LEN]; //结构体数组,每个元素均为一个结点
    int front;
    int rear;
}Queue;
/*为栈分配空间*/
Stack *Createstack()
{
    Stack *p;
    p = (Stack *)malloc(sizeof(Stack));
    p->top = -1;
    return p;
}
/*为队列分配空间*/
Queue *Createqueue()
{
    Queue *p;
    p = (Queue *)malloc(sizeof(Queue));
    p->front = 0;
    p->rear = 0;
    return p;
}
/*菜单*/
int Menu()
{
    int x;
    printf("\n\n");
    printf("1.先序遍历(递归)\n");
    printf("2.先序遍历(非递归)\n");
    printf("3.中序遍历(递归)\n");
    printf("4.中序遍历(非递归)\n");
    printf("5.后序遍历(递归)\n");
    printf("6.后序遍历(非递归)\n");
    printf("7.层序遍历\n");
    printf("8.判断其是否为完全二叉树\n");
    printf("9.求二叉树中任意两个结点的公共祖先\n");
    printf("10.退出\n\n");
    printf("请选择你要执行的操作:\n");
    scanf("%d",&x);
    return x;
}
/*先序遍历建立二叉树*/
void CreateBT(BTREE **T)
{
    char ch;
    scanf(" %c",&ch);
    if(ch=='#')
        *T = NULL;
    else
    {
        *T = (BTREE *)malloc(sizeof(BTREE));
        if(*T==NULL)
        {
            printf("No enough memory!\n");
            exit(0);
        }
        (*T)->data = ch;
        CreateBT(&((*T)->lchild));   //构造左子树
        CreateBT(&((*T)->rchild));   //构造右子树
    }
}
/*压栈*/
void Push(Stack *s,BTREE *p)
{
    s->top++;
    s->a[s->top] = p;
}
/*出栈*/
BTREE *Pop(Stack *s)
{
    BTREE *p;
    if (s->top == -1)
    {
    printf("栈空!\n");
    return NULL;
    }
    p = s->a[s->top];
    s->top--;
    return p;
}
/*栈顶*/
BTREE *Top(Stack *s)
{
    BTREE *p;
    if (s->top == -1)
    {
    printf("栈空!\n");
    return NULL;
    }
    p = s->a[s->top];
    return p;
}
/*输出结点数据*/
void Printdata(char ch)
{
    printf("%c  ",ch);
}
/*先序遍历二叉树递归算法*/
void Preorder(BTREE *T)
{
    if(T == NULL)
    {
        return;
    }
    Printdata(T->data);
    Preorder(T->lchild);
    Preorder(T->rchild);
}
/*中序遍历二叉树的递归算法*/
void Inorder(BTREE *T)
{
    if(T != NULL)
    {
        Inorder(T->lchild);
        Printdata(T->data);
        Inorder(T->rchild);
    }
}
/*后序遍历二叉树的递归算法*/
void Postorder(BTREE *T)
{
    if(T != NULL)
    {
        Postorder(T->lchild);
        Postorder(T->rchild);
        Printdata(T->data);
    }
}
/*先序遍历二叉树的非递归算法,栈顶保存当前结点的左子树*/
void NPreorder(BTREE *T)
{
     Stack *s;
     s = Createstack(); //创建一个栈
     while(T!=NULL||s->top!=-1)
     {
         while(T!=NULL)   //直到最左
         {
             Printdata(T->data);
             Push(s,T);
             T=T->lchild;
         }
         if(s->top!=-1)
         {
             T=Pop(s);
             T=T->rchild;
         }
     }
}
/*中序遍历二叉树的非递归算法*/
void NInorder(BTREE *T)
{
     Stack *s;
     s = Createstack(); //创建一个栈
     while(T!=NULL||s->top!=-1)
     {
         while(T!=NULL)
         {
             Push(s,T);
             T=T->lchild;
         }
         if(s->top!=-1)
         {
             T=Pop(s);
             Printdata(T->data); //输出位置不同,其余与先序非递归遍历一致
             T=T->rchild;
         }
     }
}
/*后序遍历的非递归算法,不设标志,设一变量*/
void NPostorder(BTREE *T)
{
    BTREE *p,*pr;
    Stack *s;
    s = Createstack(); //创建一个栈
    p = T;
    while(p!=NULL||s->top!=-1)
    {
        while(p!=NULL)
        {
            Push(s,p);
            pr = p->rchild;
            p = p->lchild;
            if(p==NULL)    //直到最底层,即后序遍历第一个
            p = pr;
        }
        p = Pop(s);
        Printdata(p->data);
        if(s->top!=-1&&Top(s)->lchild==p)
            p=Top(s)->rchild;  //遍历右子树
        else
            p=NULL;
    }
}
/*层序遍历,队列实现*/
void Levelorder(BTREE *T)
{
    Queue *p;
    p = Createqueue();  //创建一个队列
    if(T==NULL)
        return;
    p->rear++;   //二叉树非空,根指针入队
    p->a[p->rear]=T;
    while(p->front !=p->rear)  //循环直到队列不为空
    {
        p->front++;
        T=p->a[p->front];
        Printdata(T->data);
        if(T->lchild!=NULL) //若结点存在左孩子,将左孩子入队
        {
            p->rear++;
            p->a[p->rear]=T->lchild;
        }
        if(T->rchild!=NULL) //若结点存在右孩子,将右孩子入队
        {
            p->rear++;
            p->a[p->rear]=T->rchild;
        }
    }
}
/*判断二叉树是否为完全二叉树,采用层序遍历的方式*/
int CompleteTree(BTREE *T)
{
    Queue *p;
    p = Createqueue(); //创建队列
    if(T==NULL)
        return 0;
    p->rear++; //二叉树非空,根指针入队
    p->a[p->rear]=T;
    while(p->front !=p->rear)   //循环直到队列不空
    {
        if(T->lchild!=NULL&&T->rchild!=NULL) //若结点左右孩子都不为空,结点出队,左右孩子进队
        {
            p->front++;
            T=p->a[p->front];
            if(T->lchild!=NULL)
            {p->rear++;
            p->a[p->rear]=T->lchild;}
            if(T->rchild!=NULL)
            {p->rear++;
            p->a[p->rear]=T->rchild;}
        }
        if(T->lchild==NULL&&T->rchild!=NULL) //如果只有右子树没有左子树,不是
            return 0;
        if((T->lchild!=NULL&&T->rchild==NULL)||(T->lchild==NULL&&T->rchild==NULL))
            //左孩子不空右孩子空,或者左右都空,则该结点之后的所有结点必定是叶子结点
        {
            p->front++;
            while(p->front !=p->rear)
            {
                T=p->a[p->front];
                if(T->lchild==NULL&&T->rchild==NULL)
                    p->front++;
                else
                    return 0;
            }
            return 1;
        }
    }
    return 1;
}
/*先序递归遍历,寻找数据对应的结点*/
BTREE *Getnode(BTREE *m,char c)
{
    BTREE *ret=NULL;
    if(m == NULL)
        return NULL;
    if(m->data==c)
        return m;
    else
    {
        ret =Getnode(m->lchild,c);
        if(ret!=NULL)
        {
            if(ret->data==c) //进入下一层递归前判断,若返回地址是要找的地址,则不用向下进行
            return ret;
        }
        ret =Getnode(m->rchild,c);
    }
    return ret;
}
/*先序递归遍历,寻找结点对应的数据*/
char Getdata(BTREE *r,BTREE *T)
{
    if(T == NULL)
        return ' ';
    if(T==r)
        return T->data;
    Getdata(r,T->lchild);
    Getdata(r,T->rchild);
}
/*递归寻找两个结点的公共祖先*/
BTREE *Commonancestor(BTREE *T,BTREE *p,BTREE *q)
{
    BTREE *left=T,*right=T;
    if(T==NULL||p==NULL||q==NULL)
        return NULL;
    if(p==T||q==T)
        return T;
    left=Commonancestor(T->lchild,p,q);
    right=Commonancestor(T->rchild,p,q);
    if(left!=NULL&&right!=NULL) //如果左右子树都能找到,那么当前的结点就是最近公共祖先
        return T;
    if(left==NULL)  //左子树没有,返回右子树查找结构
        return right;
    else   //否则返回左子树查找结果
        return left;
}

int main()
{
    BTREE *T,*p,*q,*r;
    char ch,a,b,c;
    int flag;
    printf("请以先序遍历的方式输入二叉树(空子树以'#'表示):\n");
    CreateBT(&T);
    while(1)
    {
        getchar();
        ch = Menu();
        switch(ch)
        {
            case 1:Preorder(T);
            break;
            case 2:NPreorder(T);
            break;
            case 3:Inorder(T);
            break;
            case 4:NInorder(T);
            break;
            case 5:Postorder(T);
            break;
            case 6:NPostorder(T);
            break;
            case 7:Levelorder(T);
            break;
            case 8:flag = CompleteTree(T);
            if(flag)
                printf("该二叉树是完全二叉树!\n");
            else
                printf("该二叉树不是完全二叉树!\n");
            break;
            case 9:
            printf("请输入第一个结点的数据:\n");
            scanf(" %c",&a);
            printf("请输入第二个结点的数据:\n");
            scanf(" %c",&b);
            p=Getnode(T,a);   //找到数据对应的结点
            q=Getnode(T,b);
            r=Commonancestor(T,p,q);
            printf("最近公共祖先是:%c\n",r->data);
            break;
            case 10:exit(0);
            default:printf("请输入正确序号!\n");
        }
    }
    return 0;
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

二叉树结构的建立与遍历 的相关文章

  • 《Linux From Scratch》第三部分:构建LFS系统 第六章:安装基本的系统软件- 6.29. Coreutils-8.23...

    Coreutils 软件包包含用于显示和设置基本系统特性的工具 大概编译时间 2 5 SBU 需要磁盘空间 193 MB 6 29 1 安装 Coreutils POSIX 要求 Coreutils 中的程序即使在多字节语言环境也能正确识别
  • python 历险记(五)— python 中的模块

    目录 前言 基础 模块化程序设计 模块化有哪些好处 什么是 python 中的模块 引入模块有几种方式 模块的查找顺序 模块中包含执行语句的情况 用 dir 函数来窥探模块 python 的内置模块有哪些 结语 参考文档 系列文章列表 前言
  • 算法--将数组分成和相等的多个子数组,求子数组的最大个数

    作者 陈太汉 一个整数数组 长度为n 将其分为m份 使各份的和相等 求m的最大值 比如 3 2 4 3 6 可以分成 3 2 4 3 6 m 1 3 6 2 4 3 m 2 3 3 2 4 6 m 3 所以m的最大值为3 算法 原理的思想是
  • 直线检测方法—LSD论文翻译

    附原文链接 LSD a Line Segment Detector 摘 要 LSD是一个线段检测器 能够在线性时间内得到亚像素级精度的检测结果 它无需调试参数就可以适用于任何数字图像上 并且能够自我控制错误数量的检测 平均来说 一个图像中允
  • 一文弄懂循环链表、双向链表、静态链表

    循环链表 双向链表 静态链表 三遍定律 理解了单链表本文的理解易如反掌 单链表请点击这里 理解了单链表本文的理解易如反掌 单链表请点击这里 理解了单链表本文的理解易如反掌 单链表请点击这里 1 循环链表 将单链表中终端结点的指针端由空指针改
  • 4399 C++笔试题

    1 写出一个函数 取到链表中倒数第二个节点 双链表 node getSec List mylist return mylist m tail gt m prev m prev为链表前指针 单链表 node getSec List mylis
  • Qt——用于表格QTableView的模型

    如果想使用表格来呈现数据 Qt提供了一个方便的部件QTableWidget 但是直接用它实现一些功能可能比较困难 这里将介绍一种强大 灵活的方式来操作表格 一 模型 视图架构 在这个架构中 模型用于存储数据 视图用于呈现数据 除此之外 还有
  • 链表和线性表的优缺点

    链表和线性表的优缺点 作为我们最先接触的两个数据结构 链表和线性表的优缺点都较为明显 并且二者互相补足 文章目录 链表和线性表的优缺点 线性表 线性表的组成 线性表的缺点 线性表的优点 链表 链表的组成 链表的优点 链表的缺点 总结 线性表
  • 微软2013暑假实习生笔试题

    自己mark一下 以作后备 下面提交原文链接 原文博客 部分题目答案不确定 会持续更新 1 Which of the following calling convention s support s supportvariable leng
  • 常用的十种算法--马踏棋盘算法

    1 马踏棋盘算法介绍 马踏棋盘算法也被称为骑士周游问题 将马随机放在国际象棋的 8 8 棋盘 Board 0 7 0 7 的某个方格中 马按走棋规则 马走日字 进行移动 要求每个方格只进入一次 走遍棋盘上全部 64 个方格 2 马踏棋盘算法
  • DNG格式解析

    Author Maddock Date 2015 04 22 转载请注明出处 http www cnblogs com adong7639 p 4446828 html DNG格式基本概念 DNG格式是在TIFF的基础上扩展出来的 要了解D
  • 手把手教你实现一个向量

    文章目录 什么是向量 向量提供哪些接口 实现 宏定义 定义类 成员变量 构造函数与析构函数 构造函数 析构函数 成员函数 size get r put r e expand insert r e remove lo hi remove r
  • Hash映射理解

    先说数组 数组优点之一 能通过索引很快定位到值 hashmap 就是利用了数组这个优点 对比 线性映射 定义一个数组 数组的元素是结构体 结构体包括 一对键 值 伪代码表示 a 0 struct Bill 5 a 1 struct KK 6
  • 链表面试题(一):反转链表的算法实现

    关于链表的考察 链表是面试里面经常涉及到的考点 因为链表的结构相比于Hashmap Hashtable Concurrenthashmap或者图等数据结构简单许多 对于后者更多面试的侧重点在于其底层实现 比如Hashmap中Entry
  • 堆栈01--用两个栈实现队列

    堆栈01 用两个栈实现队列 jz05 题目概述 解析 参考答案 注意事项 说明 题目概述 算法说明 用两个栈来实现一个队列 完成队列的Push和Pop操作 队列中的元素为int类型 测试用例 队列先进先出 输入 1 2 输出 1 2 解析
  • 如何防止过拟合和欠拟合

    过拟合和欠拟合是模型训练过程中经常出现的问题 两种情况正好相反 现将两者的定义及如何防止进行简要总结 1 过拟合 1 1 定义 是指模型对于训练数据拟合呈现过当的情况 反映到评估指标上就是模型在训练集上的表现很好 但是在测试集上的表现较差
  • 算法问题实战策略

    算法问题实战策略 基本信息作者 韩 具宗万 译者 崔盛一出版社 人民邮电出版社ISBN 9787115384621上架时间 2015 2 4出版日期 2015 年3月开本 16开页码 738版次 1 1 内容简介 算法问题实战策略 本书收录
  • CRC校验(二)

    CRC校验 二 参考 https blog csdn net liyuanbhu article details 7882789 https www cnblogs com esestt archive 2007 08 09 848856
  • 【试题】排列组合

    在写一个远程的代码 如果本地有M个显示器 远程有N个显示器 M lt N 依据分辨率 显示器刷新频率等要求 需要对远程的N个显示器进行最佳分辨率修改 之后 需要从N个远程显示器中选择M个 跟本地显示器进行一对一的匹配 即从 A N M N
  • Leetcode2661. 找出叠涂元素

    Every day a Leetcode 题目来源 2661 找出叠涂元素 解法1 哈希 题目很绕 理解题意后就很简单 由于矩阵 mat 中每一个元素都不同 并且都在数组 arr 中 所以首先我们用一个哈希表 hash 来存储 mat 中每

随机推荐

  • ALLEGRO等长时如何将PIN DELAY和VIA长度计算在内

    在PCB设计中 对于时序要求严格的线路 Via和IC pin delay的长度必须得到重视 通过下面的操作 可将Via和Pin delay加入到线路长度的计算中 1st 计算Pin delay 打开Constraint Manager 选择
  • c语言指针入门

    1 指针是什么 1 概念 指针是一种十分重要的数据类型 利用指针变量可以直接对内存中各种不同数据结构的数据进行 快速处理 2 指针与内存的关系 指针与内存有着密切的联系 为了正确理解指针的概念 必须弄清楚计算机系统中数 据存储和读取的方式
  • OSI与TCP/IP协议

    OSI七层模型 OSI7层模型分别是 物理层 数据链路层 网络层 传输层 会话层 表示层 应用层 数据的封装与解封装过程 OSI模型vsTCP IP模型 TCP IP协议族的组成 每层常见的协议 应用层的协议 HTTP协议 HTTPS协议
  • 【ML&DL】【skimming】Global Optimality in Neural Network Training

    补了一下2017年的CVPR Global Optimality in Neural Network Training 1 论文一览 痛点 深度学习取得了很大的成功 但是对其成功原因的数学解释却还是一个难点 很大一个原因是对深度网络的参数学
  • 读《洞穴奇案》——一个人是否应该为了避免偷窃面包而挨饿致死?

    之前在功利主义与法的精神一文中提到过正当防卫 在读了今天的内容后 我觉得有必要对正当防卫的内在精神做一个深入探讨 书中说到判断是否是正当防卫 需要去判断一个人在进行自我防卫的时候是否是故意的 我认为 对这个故意的解读 是判断正当防卫的关键
  • SM2加解密、签名验签

    导论 SM2是国家密码管理局于2010年12月17日发布的椭圆曲线公钥密码算法 在我们国家商用密码体系中被用来替换RSA算法 国产SM2算法 是基于ECC的 但二者在签名验签 加密解密过程中或许有些许区别 目前鄙人还不太清楚 后期有机会的话
  • linux:http服务器搭建及实验案例

    目录 准备工作 http服务器各个配置文件大概说明 实验1 访问不同ip获得不同网页 实验2 同一ip访问不同端口获得不同网页 准备工作 1 安装http服务 2 将 etc selinux config 文件下面的 SELINUX值改为
  • 设备虚拟化基础 - PCI

    目录 1 配置空间概念和作用 2 通过配置空间发现设备 3 Linux读取PCI配置空间接口 4 内核中具体读取配置空间实例 5 Virtion设备自定义空间 6 Linux读取Capabilities List代码解析 1 配置空间概念和
  • 【解决方案】“/usr/bin/nvcc“ is not able to compile a simple test program解决方案

    问题描述 CMake Error at usr share cmake 3 16 Modules CMakeTestCUDACompiler cmake 46 message The CUDA compiler usr bin nvcc i
  • 深入理解Android之AOP

    深入理解Android之AOP 格式更加精美的PDF版请到 http vdisk weibo com s z68f8l0xTgCLK 下载 一 闲谈AOP 大家都知道OOP 即ObjectOriented Programming 面向对象编
  • OpenGL 创建OpenGL上下文(OpenGL Context WGL)

    文章目录 OpenGL Context 窗口 Pixel Format 创建上下文 Create Context MakeCurrent 删除上下文 Delete Context 如何正确创建Context 创建一个假的Context 获取
  • 2023华为OD机试真题【双指针/优雅子数组】

    题目内容 如果一个数组中出现次数最多的元素出现大于等于K次 被称为K 优雅数组 k也可以被称为优雅阈值 例如 数组1 2 3 1 2 3 1 它是一个3 优雅数组 因为元素1出现次数大于等于3次 数组1 2 3 1 2就不是一个3 优雅数组
  • 蓝桥杯 填字母游戏(博弈论)

    小明经常玩 LOL 游戏上瘾 一次他想挑战K大师 不料K大师说 我们先来玩个空格填字母的游戏 要是你不能赢我 就再别玩LOL了 K大师在纸上画了一行n个格子 要小明和他交替往其中填入字母 并且 1 轮到某人填的时候 只能在某个空格中填入L或
  • 寻找3的幂

    目录 题目 题目接口 题目思路 第一点 第二点 第三点 代码实现 普通版本 提交 递归版本 提交 结语 题目 在ledcode刷题网站上 有这样一道题 寻找3的幂 题目接口 bool isPowerOfThree int n 题目思路 第一
  • 【HTML】HTML5的拖放你用了吗

    HTML HTML5的拖放你用了吗 引言 github HTML HTML5的拖放你用了吗 内容速递 看了本文您能了解到的知识 在 HTML5 中 拖放是标准的一部分 任何元素都能够拖放 拖放的操作 多用在拖拽排序列表 游戏拼图等 下文中出
  • 华为OD机试 - 贪吃蛇(Java)

    题目描述 贪吃蛇是一个经典游戏 蛇的身体由若干方格连接而成 身体随蛇头移动 蛇头触碰到食物时 蛇的长度会增加一格 蛇头和身体的任一方格或者游戏版图边界碰撞时 游戏结束 下面让我们来完成贪吃蛇游戏的模拟 给定一个N M的数组arr 代表N M
  • roslaunch error: ERROR: cannot launch node of type

    今天在因为github上有个之前的包更新了 重新git clone后出现了一个问题 ERROR cannot launch node of type crazyflie demo controller py can t locate nod
  • 【FPGA】通俗理解从VGA显示到HDMI显示

    注 大部分参考内容来自 征途Pro FPGA Verilog开发实战指南 基于Altera EP4CE10 2021 7 10 上 贴个下载地址 野火FPGA Altera EP4CE10征途开发板 核心板 野火产品资料下载中心 文档 hd
  • MySQL报错的解决Can‘t connect to local MySQL server through socket ‘/var/lib/mysql/mysql.sock‘

    使用数据库工具连接或还原数据库数据时 提示Can t connect to local MySQL server through socket var lib mysql mysql sock 处理方法 1 修改配置文件 vim etc m
  • 二叉树结构的建立与遍历

    实验项目 1 编写建立二叉树的二叉链表存储结构 左右链表示 的程序 并以适当的形式显示和保存二叉树 2 完成二叉树的7种遍历操作 3 给定一个二叉树 编写算法完成下列应用 1 判断其是否为完全二叉树 2 求二叉树中任意两个结点的公共祖先 输