数据结构树与二叉树的实现

news2024/12/26 22:39:32

目录

一、普通树的存储结构

1、双亲表示法

2.孩子表示法

二、二叉树

1.二叉树的顺序存储(必须是完全二叉树,否则很浪费空间)

1)结构体

2.二叉树的链式存储

1)结构体

2)操作

1.创建一颗二叉树

2.创建一个结点

3.二叉树的前序遍历

a.递归实现

b.非递归,使用栈

4.二叉树的中序遍历

a.递归实现

b.非递归实现

5.二叉树的后序遍历

a.递归实现

b.非递归实现

6.二叉树的层次遍历:使用队列

三、线索二叉树

1.先序线索化

2.中序线索化

3.后序线索化

4.拓展,中序线索二叉树中

1)找到以p为根,第一个为中序遍历的结点,其实就是最左边的叶节点

2)找到p的后继

3)能找到后继,就可以不使用递归来遍历了,能得到中序遍历结果

4)找到以p为根结点,最后一个被中序遍历的结点,也就是p最右边的叶子结点

5)找到p的前驱

6)逆序中序遍历

5.拓展,先序二叉树中

1)寻找后继

2)不能知道找到前驱,除非能直接找到父节点,然后再讨论

6.拓展,后续二叉树中

1)寻找前驱

2)找不到后继,除非能找到父节点,再讨论

四、二叉排序树

1.结构体

2.操作函数

1)创建一颗二叉排序树

2)创建一颗二叉排序结点

3)查找关键值所对应结点

a.递归

b.非递归

4)插入关键值

5)构造一颗二叉排序树,其实就是不断插入的过程


一、普通树的存储结构

1、双亲表示法

typedef  struct{
    ElemType data;
    int parent;
}PTNode;

typedef  struct{
    PTNode nodes[MAXSIZE];
    int n;  //结点数
}PTree;

2.孩子表示法

struct CTNode{
    int child; //孩子在数组中的下标
    CTNode *next;
};

typedef  struct {
    ElemType data;
    CTNode *firstChild;
}CTBox;

typedef  struct{
    CTBox nodes[MAXSIZE];
    int n,r;//结点数、根的下标
}CTree;

二、二叉树

1.二叉树的顺序存储(必须是完全二叉树,否则很浪费空间)

1)结构体

struct TreeNode{
    ElemType value;
    bool isEmpty;
};

TreeNode t[MAXSIZE]; //一般从下标为1开始存储,为了和下标对应起来,方便查找孩子

//顺序存储初始化将所有的isEmpty变为TRUE

//左孩子为2i 右孩子为2i+1  父节点为i/2

//i>n/2就是叶子结点

2.二叉树的链式存储

1)结构体

//二叉树的链式存储
typedef  struct BiTNode{
    ElemType data;
    BiTNode *lchild,*rchild;
}BiTNode,*BTree;

2)操作

1.创建一颗二叉树

BTree CreatBTree(ElemType rootdata)
{
    BiTNode *root = (BiTNode*)malloc(sizeof(BiTNode));
    root->data=rootdata;
    root->lchild=NULL;
    root->rchild=NULL;
    return  root;
}

2.创建一个结点

BiTNode *CreatBiTNode(ElemType data)
{
    BiTNode* NewNode = (BiTNode*)malloc(sizeof(BiTNode));
    NewNode->data=data;
    NewNode->lchild=NULL;
    NewNode->rchild=NULL;
    return  NewNode;
}

3.二叉树的前序遍历

a.递归实现
void PreOrder(BTree T)
{
    if(T!=NULL){
        visit(T);
        PreOrder(T->lchild);
        PreOrder(T->rchild);
    }
}
b.非递归,使用栈
//会使用栈
void PreOrder1(BTree T)
{
    SqStack s;
    InitStack(s);
    BTree p =T;
    while (p||!StackEmpty(s)) {
        if(p){
            visit(p);
            push(s,p);
            p=p->lchild;
        }
        else {
            pop(s,p);
            p=p->rchild;
        }
    }
}

4.二叉树的中序遍历

a.递归实现
void InOrder(BTree T)
{
    if(T!=NULL){
        InOrder(T->lchild);
        visit(T);
        InOrder(T->rchild);
    }
}
b.非递归实现
void InOrder1(BTree T)
{
    SqStack s;
    InitStack(s);
    BTree p = T;
    while (p||!StackEmpty(s)) {
        if(p){
            push(s,p);
            p=p->lchild;
        }
        else {
            pop(s,p);
            visit(p);
            p=p->rchild;
        }
    }
}

5.二叉树的后序遍历

a.递归实现
void PostOrder(BTree T)
{
    if(T!=NULL){
        PostOrder(T->lchild);
        PostOrder(T->rchild);
        visit(T);
    }
}
b.非递归实现
void PostOrder1(BTree T)
{
    SqStack s;
    InitStack(s);
    BTree p = T;
    BTree r=NULL;
    while (p||!StackEmpty(s)) {
        if(p){
            push(s,p);
            p=p->lchild;
        }
        else {
          GetTop(s,p);
          if(p->rchild!=r&&p->rchild)
              p=p->rchild;
          else {
              pop(s,p);
              visit(p);
              r=p;
              p=NULL;
          }
        }
    }
}

6.二叉树的层次遍历:使用队列


void LevelOrder(BTree T)
{
    LinkQueue Q;
    InitLinkQueue(Q);
    BTree p;
    EnLinkQueue(Q,T);
    while (!LinkQueueEmpty(Q)) {
        DeLinkQueue(Q,p);
        visit(p);
        if(p->lchild!=NULL)
            EnLinkQueue(Q,p->lchild);
        if(p->rchild!=NULL)
            EnLinkQueue(Q,p->rchild);
    }
}

三、线索二叉树

1.先序线索化

void PreThread(ThreadTree T, ThreadTree &pre)
{
    if(T!=NULL){
        if(T->lchild==NULL){
            T->lchild=pre;
            T->ltag=1;
        }
        if(pre!=NULL and pre->rchild==NULL){
            pre->rchild=T;
            pre->rtag=1;
        }
        pre=T;
        if(T->ltag==0)
            PreThread(T->lchild,pre);
        PreThread(T->rchild,pre);

    }
}

void CreatPreThread(ThreadTree T)
{
    ThreadTree pre= NULL;
    if(T!=NULL){
        PreThread(T,pre);
        pre->rchild=NULL;
        pre->rtag=1;
    }
}

2.中序线索化

void InThread(ThreadTree T,ThreadTree &pre)
{
    if(T!=NULL){
        InThread(T->lchild,pre);

        if(T->lchild==NULL){
            T->lchild=pre;
            T->ltag=1;
        }
        if(pre!=NULL and pre->rchild==NULL){
            pre->rchild=T;
            pre->rtag=1;
        }
        pre=T;

        InThread(T->rchild,pre);
    }

}

void CreatInThread(ThreadTree T)
{
    ThreadTree pre= NULL;
    if(T!=NULL){
        InThread(T,pre);
        pre->rchild=NULL;
        pre->rtag=1;
    }
}

3.后序线索化

void PostThread(ThreadTree T, ThreadTree &pre)
{
    if(T!=NULL){
    PostThread(T->lchild,pre);
    PostThread(T->rchild,pre);

        if(T->lchild==NULL){
            T->lchild=pre;
            T->ltag=1;
        }
        if(pre!=NULL and pre->rchild==NULL){
            pre->rchild=T;
            pre->rtag=1;
        }
        pre=T;
    }
}

void CreatPostThread(ThreadTree T)
{
    ThreadTree pre= NULL;
    if(T!=NULL){
        PostThread(T,pre);
        pre->rchild=NULL;
        pre->rtag=1;
    }
}

4.拓展,中序线索二叉树中

1)找到以p为根,第一个为中序遍历的结点,其实就是最左边的叶节点

ThreadNode *FirstNode(ThreadNode *p)
{
    //找到最左边叶节点
    while (p->ltag==0) {
        p=p->lchild;
    }
    return  p;
}

2)找到p的后继

ThreadNode *NextNode(ThreadNode *p)
{
    if(p->rtag==0)
        return FirstNode(p->rchild);
    else {
        return p->rchild;
    }
}

3)能找到后继,就可以不使用递归来遍历了,能得到中序遍历结果

void InOrder1(ThreadTree T)
{
    for(ThreadNode *p = FirstNode(T);p!=NULL;p=NextNode(p)){
        visit_Thread(p);
    }
}

4)找到以p为根结点,最后一个被中序遍历的结点,也就是p最右边的叶子结点

ThreadNode *LastNode(ThreadNode *p)
{
    while (p->rtag==0) {
        p=p->rchild;
    }
    return  p;
}

5)找到p的前驱

ThreadNode *preNode(ThreadNode *p){
    if (p->ltag==0) {
        return LastNode(p->lchild);
    }
    else {
        return p->lchild;
    }
}

6)逆序中序遍历

void RevInOrder(ThreadTree T)
{
    for(ThreadNode *p = LastNode(T);p!=NULL;p=preNode(p)){
        visit_Thread(p);
    }
}

5.拓展,先序二叉树中

1)寻找后继

ThreadNode *NextNode_pre(ThreadNode *p)
{
    if(p->rtag==0){
        if(p->lchild!=NULL)
            return p->lchild;
        if(p->rchild!=NULL)
            return p->rchild;
    }
    else {
        return p->rchild;
    }
}

2)不能知道找到前驱,除非能直接找到父节点,然后再讨论

6.拓展,后续二叉树中

1)寻找前驱

ThreadNode *preNode_post(ThreadNode *p)
{
    if(p->ltag==1){
        return p->lchild;
    }
    else {
        if(p->rchild!=NULL)
            return p->rchild;
        else {
            return p->lchild;
        }
    }
}

2)找不到后继,除非能找到父节点,再讨论

四、二叉排序树

1.结构体

typedef  struct BSTNode{
    ElemType data;
    BSTNode *lchild,*rchild;
}BSTNode,*BSTree;

2.操作函数

1)创建一颗二叉排序树

BSTree CreatBSTree(ElemType rootdata)
{
    BSTNode *NewNode = (BSTNode*)malloc(sizeof (BSTNode));
    NewNode->data=rootdata;
    NewNode->lchild=NULL;
    NewNode->rchild=NULL;
    return  NewNode;
}

2)创建一颗二叉排序结点

BSTNode *CreatBSTNode(ElemType data)
{
    BSTNode *NewNode = (BSTNode*)malloc(sizeof (BSTNode));
    NewNode->data=data;
    NewNode->lchild=NULL;
    NewNode->rchild=NULL;
    return  NewNode;
}

3)查找关键值所对应结点

a.递归
BSTNode *BSTSearch(BSTree bt, ElemTpye key)
{
    if(bt==NULL)
        return  NULL;
    if(bt->data==key)
        return bt;
    else if (bt->data>key) {
        return BSTSearch(bt->lchild,key);
    }
    else {
        return  BSTSearch(bt->rchild,key);
    }
}
b.非递归
BSTNode *BSTSearch(BSTree bt, ElemType key)
{
    while(bt!=NULL and key!=bt->data){
        if(key<bt->data)
            bt=bt->lchild;
        else {
            bt=bt->rchild;
        }
    }
    return bt;
}

4)插入关键值

bool BSTInsert(BSTree &bt, ElemType key)
{
    if(bt==NULL){
        BSTNode *Newnode = CreatBSTNode(key);
        bt=Newnode;
        return true;
    }
    if(bt->data==key){
        return false;
    }
    else if(bt->data>key){
        return BSTInsert(bt->lchild,key);
    }
    else {
        return BSTInsert(bt->rchild,key);
    }

}

5)构造一颗二叉排序树,其实就是不断插入的过程

void CreatBST(BSTree &bt, int key[], int n)//key[] 关键字数组,n 关键字数组长度
{
    bt = NULL;
    for (int i=0;i<n;i++) {
        BSTInsert(bt,key[i]);
    }
}

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

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

相关文章

kubernetes--数据存储

目录 一、数据存储引言&#xff1a; 二、基础存储卷&#xff1a; 1. emptyDir存储卷&#xff1a; 2. hostPath存储卷&#xff1a; 3. nfs共享存储卷&#xff1a; 3.1 配置nfs: 3.2 master节点编写yaml文件&#xff1a; 4. 总结&#xff1a; 三、PVC和PV&#xff1a; 1. PV 的…

vivado产生报告阅读分析6-时序报告2

1、复查时序路径详情 单击“ OK ”运行报告命令后 &#xff0c; 将打开一个新窗口。这样您即可复查其中内容。在其中可查看执行选定的每种类型 (min/max/min_max ) 的分析之后所报告的 N 条最差路径。 下图显示的“Report Timing ” &#xff08; 时序报告 &#xff09; 窗口…

【无标题】chapter6卷积

此例以说明全连接层处理图片的时候会遇到参数过多 模型过大的问题 参数比要研究的物体总数还多 卷积&#xff0c;特殊的全联接层 平移不变形&#xff0c;局部性 原本权重为二维&#xff08;输入和输出全联接&#xff0c;想想下表组合&#xff0c;就是个二维的矩阵&#xff09;…

pytorch 安装 2023年

pytorch网址&#xff1a;https://pytorch.org/get-started/locally/ conda install pytorch torchvision torchaudio pytorch-cuda11.8 -c pytorch -c nvidia我在自己电脑上用这个pip命令完全安装不了&#xff0c;只能用conda安装。复制上面提供的命令&#xff0c;在cmd中直接运…

腾讯云服务器新用户优惠政策,腾讯云新人服务器购买入口

腾讯云服务器新用户优惠政策是腾讯云为新用户提供的一种优惠&#xff0c;它可以帮助新用户以更低的价格购买腾讯云服务器&#xff0c;并且还提供一些额外的优惠。腾讯云服务器对于新用户有着非常优惠的政策。无论你是个人用户还是企业用户&#xff0c;只要你是第一次购买腾讯云…

flutter TabBar指示器

第一层tabView import package:jade/configs/PathConfig.dart; import package:jade/customWidget/MyCustomIndicator.dart; importpackage:jade/homePage/promotion/promotionPost/MyPromotionListMainDesc.dart; import package:jade/homePage/promotion/promotionPost/MyPr…

ProtocolBuffers(protobuf)详解

目录 前言特点语法定义关键字JSON与Protocol Buffers互相转换gRPC与Protocol Buffers的关系 前言 Protocol Buffers&#xff08;通常简称为protobuf&#xff09;是Google公司开发的一种数据描述语言&#xff0c;它能够将结构化数据序列化&#xff0c;可用于数据存储、通信协议…

交换排序详讲:冒泡排序+快速排序(多方法+思路+图解+代码)

文章目录 交换排序一.冒泡排序二.快速排序1.挖坑法2.Hoare法 交换排序 根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置将键值较大的记录向序列的尾部移动&#xff0c;键值较小的记录向序列的前部移动。 一.冒泡排序 /*** 冒泡排序* 时间复杂度 n^2* 空间复杂…

用Postman发送xml数据

启动Postman&#xff1a; 点击左上角的“New”&#xff0c;在弹出窗中选择HTTP&#xff1a; 选择POST方法&#xff1a; 点击Body&#xff1a; 选择raw&#xff1a; 在右侧的下拉列表中选择XML&#xff1a; 在下面的输入框中输入或者从其它地方拷贝XML文本&#xff1a;…

cookie机制

目录 为什么会有cookie?? cookie从哪里来的&#xff1f;&#xff1f; cookie到哪里去&#xff1f;&#xff1f; cookie有啥用&#xff1f;&#xff1f; session HttpServletRequest类中的相关方法 简单的实现cookie登录功能 实现登录页面 实现servlet逻辑 实现生成主…

uni-app 蓝牙打印, CPCL指令集使用

先上代码: GitHub - byc233518/uniapp-bluetooth-printer-demo: 使用uniApp 连接蓝牙打印机 Demo, CPCL 指令简单实用示例 (内含 芝珂,佳博,精臣 多个厂家指令集使用文档) 文件结构: ├── App.vue ├── CPCL 指令手册.pdf // 指令集参考手册 ├── LICENSE ├── R…

【JAVA-排列组合】一个套路速解排列组合题

说明 在初遇排列组合题目时&#xff0c;总让人摸不着头脑&#xff0c;但是做多了题目后&#xff0c;发现几乎能用同一个模板做完所有这种类型的题目&#xff0c;大大提高了解题效率。本文简要介绍这种方法。 题目列表 所有题目均从leetcode查找&#xff0c;便于在线验证 46.…

Mindomo Desktop for Mac(免费思维导图软件)下载

Mindomo Desktop for Mac是一款免费的思维导图软件&#xff0c;适用于Mac电脑用户。它可以帮助你轻松创建、编辑和共享思维导图&#xff0c;让你的思维更加清晰、有条理。 首先&#xff0c;Mindomo Desktop for Mac具有直观易用的界面。它采用了Mac独特的用户界面设计&#xf…

2023年首届天府杯数学建模国际大赛问题A思路详解与参考代码:大地测量数据中异常现象的特征和识别

地球变形观测是固体潮汐曲线分析和地震前体研究的重要手段&#xff0c;也是地球观测技术的重要组成部分。基于各种精密科学仪器的变形观测点主要集中在洞穴、地下井等易的自然灾害&#xff08;雷暴、强降雨、降雪等&#xff09;&#xff0c;人工维护、人工爆破等外部条件&#…

浅谈安科瑞无线测温产品在巴西某工厂的应用

摘 要&#xff1a;高压开关设备是变电站和配电站中保证电力系统安全运行的重要设备之一,因此,开关柜的稳定运行对于整个电力系统有非常重要的意义。设备老化、长期高负荷运行都可能使设备局部温度过高而发生火灾&#xff0c;因此,对变电站内的敏感设备进行温度检测变得尤为重要…

chrome 浏览器个别字体模糊不清

特别是在虚拟机里&#xff0c;有些字体看不清&#xff0c;但是有些就可以&#xff0c;设置办法&#xff1a; chrome://settings/fonts 这里明显可以看到有些字体就是模糊的状态&#xff1a; 把这种模糊的字体换掉即可解决一部分问题。 另外&#xff0c;经过观察&#xff0c;…

Unity开发之C#基础-集合(字典)(Dictionary)

前言 Hello 兄弟们 一转眼俩月又过去了&#xff08;失踪人口回归&#xff09; 不出意外的是出意外了 失踪了两个月 有点对不起我这为数不多的粉丝们 实不相瞒忙的焦头烂额 也没心情写博客 实在对不住各位 好了长话短说 今天这篇文章是讲解c#当中的新的一种集合的表现&#xff…

​软考-高级-系统架构设计师教程(清华第2版)【第10章 软件架构的演化和维护(P345~382)-思维导图】​

软考-高级-系统架构设计师教程&#xff08;清华第2版&#xff09;【第10章 软件架构的演化和维护&#xff08;P345~382&#xff09;-思维导图】 课本里章节里所有蓝色字体的思维导图

idea运行项目之后一直卡在Writing classes… 解决方案

最近遇到idea里直接运行一个Spring boot项目后&#xff0c;idea一直慢悠悠的parsing java&#xff0c;然后就writing classes&#xff0c;然后就一直卡着不动了&#xff0c;运气好10几分钟能把项目启动起来。 多年的摸鱼经验告诉我&#xff0c;事出反常必有妖&#xff0c;赶紧…

python趣味编程-5分钟实现一个测验应用程序(含源码、步骤讲解)

Python测验是用 Python 编程语言编写的,这个关于 Python 编程的简单测验是一个简单的项目,用于测试一个人在给定主题考试中的知识能力。 Python 中的 Quiz项目仅包含用户端。用户必须先登录或注册才能开始Python 测验。 此外,还规定了解决问题的时间。用户应在时间结束前解…