个人学习-STL:Set前置-tree

参考资料:

[1]程杰.大话数据结构[M].

[2][美]Robert Sedgewic,Jevin Wayne. 算法Algorithms[M].谢路云译

1.基本脉络:

树实际是链表的衍生结构,从链表到二叉树,到二叉搜索树,到平衡二叉树(AVL),进行一个总结;

2.树的一些基本概念:

1)树实际是n个节点的有限集。n = 0 时称为空树;任何一个非空树,有且仅有一个根节点(root); n > 0 时,其余节点又可分为m个 _不相交_的有限集,每个集合都可看作一个树,即根的子树(subtree)
2)节点所拥有的子树称为子树的度(Degree)。度为0的节点称为叶节点(leaf)或者终端节点;
3)节点衍生出子树的根节点,称为子节点(child),同一根节点下子树节点为兄弟节点(slibing);

3.二叉树:

3.1二叉树的基本构造:

二叉树是最多存在两个子树的树形结构,每个节点单独看都是一个二叉树;
几种特殊的二叉树:
1)斜树:仅有左子树或者右子树的二叉树,实际就是一个线性表;
2)满二叉树:所有节点的度都是2,且所有的叶子节点都在一层上,称为满树
3)完全二叉树:概念定义比较难理解的一种二叉树,简单这样理解[1,2,3,4,5,6,7,8];这样的序列容器,把它以层序优先进行二叉树,它就可以构成一个完全二叉树,类似于广度优先的遍历;(详情见按层遍历二叉树)

个人学习-STL:Set前置-tree
3.2 简单二叉树的存储:
  typedef struct BinTree
  {
      int element;
      struct BinTree * ltree;
      struct BinTree * rtree;
  };
3.3二叉树构造和遍历:
前序,中序,后序

实际就是节点,左子叶,右子树之间的顺序;
前序:
若二叉树为空,则空操作返回,否则先访问节点,再先序访问左树,结束后先序访问右树;上图的先序结果为1,2,4,8,9,5,10,3,6,7;(节点在左右子树前被访问)
先遍历节点,再遍历左子树,再遍历右子树

  void pre_search_BinTree(struct BinTree * tree)
  {
      if (tree == NULL)
      {
          return;
      }
      preintf("%d", tree ->element);
      pre_search_BinTree(tree -> ltree);
      pre_search_BinTree(tree -> rtree);

  }

中序:
若二叉树为空,则空操作返回,否则先中序遍历左树,再访问元素,再中序遍历右树

  void on_search_BinTree(struct BinTree * tree)
  {
      if (tree == NULL)
      {
          return;
      }
      pre_search_BinTree(tree -> ltree);
      preintf("%d", tree ->element);
      pre_search_BinTree(tree -> rtree);
  }

后序:
二叉树为空,则空操作返回,否则先后序遍历左树,再后序遍历右树,再访问元素;

void pos_search_BinTree(struct BinTree * tree)
{
    if (tree == NULL)
    {
        return;
    }
    pre_search_BinTree(tree -> ltree);
    pre_search_BinTree(tree -> rtree);
    preintf("%d", tree ->element);
}
深度遍历和广度遍历(层序遍历)

深度遍历-先序:先序遍历的非递归版,实际就是一个简单的深度遍历,以访问最深的路径为目的;(在图的部分会被广泛使用)

  // 直接用了STL里的stcak,note:设计上把弹出栈顶元素拆成里top()和pop()两个函数,具体原因需要研究一下
void DFS(struct BinTree* tree)
{
    // 节点栈,利用先进后出的特性来处理
    if(tree == nullptr)
        return;
    stack<bintree*> node_stack;
    // &#x6839;&#x8282;&#x70B9;&#x5165;&#x6808;
    node_stack.push(tree);
    while (!node_stack.empty())
    {
        // &#x8BBF;&#x95EE;&#x5143;&#x7D20;;
        BinTree* top_elem = node_stack.top();
        node_stack.pop(); // &#x79FB;&#x9664;;
        // &#x5148;&#x8FDB;&#x540E;&#x51FA;&#xFF0C;&#x60F3;&#x5148;&#x8BBF;&#x95EE;&#x5DE6;&#x5B50;&#x6811;&#x7684;&#x8BDD;&#xFF0C;&#x53F3;&#x8FB9;&#x5148;&#x5165;&#x6808;
        if(top_elem ->rtree)
        {
            node_stack.push(top_elem -> rtree);
        }
        if(top_elem -> ltree)
        {
            node_stack.push(top_elem -> ltree);
        }
        // &#x9700;&#x8981;delete&#x4E00;&#x4E0B;&#xFF0C;&#x53EF;&#x80FD;&#x4F1A;&#x5185;&#x5B58;&#x6CC4;&#x6F0F;-->&#x5F85;&#x9A8C;&#x8BC1;;
        delete top_elem;
    }
</bintree*>

广度优先遍历(BFS):
按照每一层的顺序对二叉树进行遍历,root->层1 -> 层2 -> 层3 ;如上文,如果把一个容器里的数据,按层序展开,得到的就是一个完全二叉树

  /* &#x961F;&#x5217;&#x5B9E;&#x73B0;&#xFF0C;&#x5148;&#x8FDB;&#x5148;&#x51FA;;
    tree-    A
           /   \
          B     C
         / \   / \
        D   E  F  G
      queue: 1. push(A)     A
             2. front_pop:A&#xFF0C; pushback:BC    BC
             3. front_pop:B,  pushback:DE    CDE
             4. front_pop:C,  pushback:GF    DE
             5. frint_pop .....

*/
  void BFS(struct BinTree * tree)
{
    if(tree == nullptr)
    {
        return;
    }
    queue<bintree *> node_queue;
    // &#x6839;&#x8282;&#x70B9;&#x5165;&#x961F;&#x5217;;
    node_queue.push(tree);
    while (!node_queue.empty())
    {
        BinTree * node = node_queue.front();
        node_queue.pop(); // &#x5C3E;&#x8FDB;&#x5934;&#x51FA;FIFO;
        if(node -> ltree)
        {
            node_queue.push(node ->ltree);
        }
        if(node -> rtree)
        {
            node_queue.push(node -> rtree);
        }
    }
}
</bintree>
3.4基础二叉树的缺点:

1.当节点n的数量比较多的时候,子叶上会有大量空指针;
2.找不到前驱点,需要找到某个节点元素的前驱点,需要再去遍历;
由于这两个缺点,需要把原始二叉树进行改进,引出了线索二叉树;

4.线索二叉树:

鉴于上述的两个原因,在结构设计上,添加进了一个思路:
将节点中的空指针,指向本节点的前驱点和后继点,就可以实现二叉树的线索化,把此时如果只考虑前驱和后继,不考虑节点间的亲缘关系的话,此时数据类型就是一个双向链表。
常用的线索化思路:中序遍历,将空的rtree ptr指向后继点,ltree ptr指向前驱点;(枚举后较为便捷的做法其他case更为复杂);
此时,节点需要两个标识位,来分辨指针表示的是实际的子树,还是前驱后继关系;

typedef char TelemType;
typedef enum{Link, Thread} PointerFlag;
typedef struct BiThrNode
{
    TelemType elem;
    struct BiThrNode * ltree;
    struct BiThrNode * rtree;
    PointerFlag lflag;
    PointerFlag rflag;
};

// &#x904D;&#x5386;&#x7EBF;&#x7D22;&#x5316;
// &#x9700;&#x8981;&#x4E00;&#x4E2A;&#x91CF;&#xFF0C;&#x5B9A;&#x4E49;&#x524D;&#x4E00;&#x4E2A;&#x8BBF;&#x95EE;&#x7684;&#x8282;&#x70B9;;
BiThrNode* pre;
void InThreading(struct BiThrNode * tree)
{
    if (tree == NULL)
    {
        return;
    }
    InThreading(tree -> ltree);
    if(!tree ->ltree)
    {
        tree -> lflag = Thread;
        tree -> ltree = pre;

    }
    if(!pre -> rtree)
    {
        pre ->rflag = Thread;
        pre ->rtree = tree;
    }
    pre = tree;
    InThreading(tree -> rtree);
}

Original: https://www.cnblogs.com/Albert-lihai/p/16579215.html
Author: Albert_禄遥
Title: 个人学习-STL:Set前置-tree

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/577714/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • K8s-二进制安装

    K8S-二进制安装使用 1.IP总规划 服务类型 ip地址 组件 k8s-master01 etcd集群节点1 192.168.80.20 kube-apiserver、kube-…

    Linux 2023年6月13日
    097
  • CentOS通过Xshell连接密码错误

    环境:CentOS6.7虚拟机,Xshell7 问题说明:通过Xshell7进行远程登录时,一直提示密码错误。 问题分析排查过程: 1、开始以为是密码错了,经过SVN版本检查等未发…

    Linux 2023年5月28日
    0109
  • k8s 常用命令

    查看所有 pod 列表, -n 后跟namespace,查看指定的命名空间 查看 RC 和service 列表,-o wide 查看详细信息 显示 Node 的详细信息 显示 Po…

    Linux 2023年5月27日
    0118
  • Markdown 常用语法精讲

    标题 (# 跟标题名称一定要留空格) 一级标题 二级标题 三级标题 四级标题 五级标题 六级标题 缩进 (使用) 这是缩进四个空格文本 (源码: 这是缩进四个空格文本) 强调/加粗…

    Linux 2023年6月7日
    0130
  • 那些技术实战中的架构设计方法

    上个月我写的一篇文章《关于技术能力的思考和总结》引起了大家的关注,好多读者的评论”以写代想、以想促真、以讲验真”,大家的感受很深刻,基于上次的文章,这篇文章…

    Linux 2023年6月8日
    087
  • KVM虚拟化

    1. 虚拟化介绍 2. 为什么要使用虚拟化技术 3. KVM介绍 4. KVM部署 4.1.开启CPU的虚拟化功能,添加一块新的硬盘用来存储kvm的数据 4.2. 安装kvm 4….

    Linux 2023年6月13日
    0122
  • 【Example】C++ 标准库智能指针 unique_ptr 与 shared_ptr

    【概念直接搬运Docs】C 样式编程的一个主要 bug 类型是内存泄漏。 泄漏通常是由于为分配的内存的调用失败引起的 delete new 。 现代 C++ 强调”资源…

    Linux 2023年6月13日
    0134
  • Redis下载及安装(windows版)

    下载地址1、Github下载地址:https://github.com/MicrosoftArchive/redis/releases2、百度网盘下载地址 https://pan….

    Linux 2023年5月28日
    088
  • [转帖]shell学习之shell执行方式及排错

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Linux 2023年5月28日
    093
  • C++ 之处理模板化基类的成员名称

    问题描述 假设有下面这么一段简单的代码,其中定义了两个类模板,一个基类 Animal,一个派生类 Dog: #include #include using namespace st…

    Linux 2023年6月7日
    0100
  • Map&Promise

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> &lt…

    Linux 2023年6月13日
    0110
  • Python eval()函数

    The eval() takes three parameters: expression – this string as parsed and evaluated …

    Linux 2023年6月8日
    099
  • cdn缓存顺序优先级

    posted @2022-09-26 17:28 爱折腾的大臭臭 阅读(10 ) 评论() 编辑 Original: https://www.cnblogs.com/linuxsh…

    Linux 2023年6月6日
    0113
  • 一位美国教授的科研诀窍:每周工作100小时(转)

    今天看到了,Xinyu Zhang 的一篇文章,深受启发,转载一下。 OSU计算机系一位教授到北大讲座,学生提问:您组里发了那么多牛paper,有什么诀窍? 教授回答:我们组里,从…

    Linux 2023年6月14日
    0106
  • QNAP container station安装 redis

    打开container station,即docker,安装Redis 选择最新的即可 命令处请务必在尾部添加语句: –requirepass “yourpasswor…

    Linux 2023年5月28日
    078
  • Redis 缓存穿透、雪崩、击穿以及相关解决方案

    缓存流程: 缓存穿透: 什么是缓存穿透:是指 redis 和数据库都没有这个数据,大量请求该数据造成数据库挂掉,该请求一般是非正常用户 解决方案: 布隆过滤器:将数据库中所有的查询…

    Linux 2023年5月28日
    081
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球