数据结构与算法分析(c++版) #12 二叉树
2015-09-28 20:08
453 查看
二叉树
二叉树的定义与特性:
参考百度的二叉树定义:百度二叉树二叉树类型:
(1)完全二叉树——若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。(2)满二叉树——除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。
(3)平衡二叉树——平衡二叉树又被称为AVL树(区别于AVL算法),它是一棵二叉排序树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
二叉树的一些定理:
(1)在非空二叉树中,第i层的结点总数不超过2^(i-1)个, i>=1;(2)深度为h的二叉树最多有2^h - 1个结点(h>=1),最少有h个结点;
(3)具有n个结点的完全二叉树的深度为log(n+1)
;
(4)非空满二叉树的叶结点数等于其分支结点数加1;
(5)一棵非空二叉树空子树的数目等于其结点数目加1。
对于二叉树的操作,有些是关于结点的(如指向子结点或获取值),另一些则是关于整棵树的(如初始化)。这说明在c++中必须分别实现二叉树与结点的类。这里提供了一种二叉树结点类的定义。基本适合各种不同的二叉树类型。
下面是一棵二叉树结点的ADT,称为BinNode。
template <class Elem> class BinNode { public: // 返回该结点的值 virtual Elem& val() = 0; // 设置该结点的值 virtual void setVal(const Elem&) = 0; // 返回左子节点 virtual BinNode* left() const = 0; // 设置左子结点 virtual void setLeft(BinNode*) = 0; // 返回右子节点 virtual BinNode* right() const = 0; // 设置右子节点 virtual void setRight(BinNode*) = 0; // 判断该结点是否是叶节点 virtual bool isLeaf() = 0; };
使用指针实现二叉树
根据定义,每一个结点都有两个子结点,不论有一个为空还是二者都为空。通常,二叉树的结点都包含一个数据区,数据区所需空间大小根据需要而定。最常见的结点实现方法包含一个数据区和两个指向子结点的指针。下面给出了名为BinNodePtr的BinNod抽象类的简单实现。
template <class Elem> class BinNodePtr : public BinNode<Elem> { private: Elem element; // 二叉树指针结点存放的数据 BinNodePtr* leftChildNode; BinNodePtr* rightChildNode; public: // 两个构造函数 BinNodePtr() { leftChildNode = rightChildNode = nullptr; } BinNodePtr(Elem elemval, BinNodePtr* left = nullptr, BinNodePtr* right = nullptr) { element = elemval; leftChildNode = left; rightChildNode = right; } ~BinNodePtr() {} // 返回该结点的值 Elem& val() { return element; } // 设置该结点的值 void setVal(const Elem& elem) { element = elem; } // 返回左子节点 BinNode<Elem>* left() const { return leftChildNode; } // 设置左子结点 void setLeft(BinNode<Elem>* node) { leftChildNode = (BinNodePtr*)node; } // 返回右子节点 BinNode<Elem>* right() const { return rightChildNode; } // 设置右子节点 void setRight(BinNode<Elem>* node) { rightChildNode = (BinNodePtr*)node; } // 判断该结点是否是叶节点,通过判断左右子结点是否为空 bool isLeaf() { return (leftChildNode == nullptr) && (rightChildNode = nullptr); } };在利用指针实现的二叉树中,叶结点与分支节点是否使用相同的类定义十分重要。今后有一些应用只需要用叶结点存储数据,还有一些应用需求分支节点与叶指点存储不同类型的数据。根据定义,只有分支节点有非空子结点。因此,分别定义分支结点与叶节点将节省存储空间。
相关文章推荐
- 堆的基本实现
- 重学数据结构-树
- 数据结构和算法学习(3)-简单排序
- 数据结构_二叉索引树_模板
- 数据结构和算法学习(2)-时间复杂度
- 数据结构和算法学习(1)-概述
- Scala2.11.7学习笔记(四)常用数据结构
- 94 数据结构和方向感言
- 数据结构实验的目的、要求和评分标准
- java中Map数据结构详解
- C数据结构学习历程(1) 顺序表
- 图的三种数据结构
- 第9章 数据结构
- 中国大学MOOC-陈越、何钦铭-数据结构 一元多项式的乘法与加法运算
- 数据结构的地位
- 数据结构的基本概念和术语
- 数据结构研究的内容即定义
- 数据结构之关于栈的“先进后出”的理…
- 【数据结构导论】线性表
- 数据结构 带头结点的单链表 操作大全 最全的链表操作(c++实现)