数据结构:树tree和二叉树BinaryTree的实现与代码分析
来源:互联网 发布:哥白尼式革命 知乎 编辑:程序博客网 时间:2024/06/16 16:20
一些概念:
一棵树是一些结点的集合。这个集合可以是空集,若不是空集,则树由称作根(root)的结点r以及零个或多个非空的(子)树T1,T2...Ta组成,子树中每一个棵的根都被来自根r的一条有向的边(edge)所连接。
每一棵子树的根叫做根r的儿子(child),而r是每一棵子树的根的父亲(parent)。
没有儿子的结点成为叶(leaf)结点。
具有相同父亲的结点为兄弟(siblings)结点。
对于任意结点n,n的深度(depth)为从根到n的唯一路径的长。因此根的深度为0.
n的高度是从n到一片树叶的最长路径的长。因此所有的树叶的高度都是0.
一棵树的高等于它的根的高。
一棵树的深度等于它最深的树叶的深度。等于根的高度。
前序遍历:对结点的处理工作是在它的诸儿子结点被处理之前进行的。
后序遍历:对结点的处理工作是在它的诸儿子结点被处理之后进行的。
内部路径长(internal path length)一棵树所有结点的深度总和。
//普通的树结点template <typename Object>struct TreeNode {Object element;//结点的数据TreeNode* firstChild;//第一个儿子的指针TreeNode* nexSibling;//当前结点的兄弟结点的指针};
二叉树:每个结点最多有两个儿子的树。
每个二叉树,具有N个结点,N+1个NULL结点
//二叉树结点template<typename Object>struct BinaryNode {Object element;//结点的数据BinaryNode* left;//左结点BinaryNode* right;//右结点};
二叉查找树:对于树中的每个结点,它的左子树中所有项的值小于x中的项,而它的右子树中所有项的值大于x中的项。
// // Vector.h // HelloWorld // csdn blog:http://blog.csdn.net/u012175089 // Created by Fable on 17/1/7. // Copyright (c) 2017年 Fable. All rights reserved. // #ifndef __HelloWorld__Tree__ #define __HelloWorld__Tree__#include <iostream>namespace Fable{ //二叉查找树,对于Comparable,必须实现了><=的比较template<typename Comparable>class BinarySearchTree{public://构造函数BinarySearchTree(){}//复制构造函数BinarySearchTree(const BinarySearchTree& rhs){root = clone(rhs.root);}//析构函数~BinarySearchTree(){makeEmpty(root);}//复制赋值运算符const BinarySearchTree& operator=(const BinarySearchTree& rhs){if (this != &rhs){makeEmpty(root);//先清除root = clone(rhs.root);//再复制}return *this;}//查找最小的对象const Comparable& findMin()const{findMin(root);}//查找最大的对象const Comparable& findMax()const{findMax(root);}//是否包含了某个对象bool contains(const Comparable& x)const{return contains(x, root);}//树为空bool isEmpty()const{return root == nullptr;}//打印整棵树void printTree()const{printTree(root);}//清空树void makeEmpty(){makeEmpty(root);}//插入某个对象void insert(const Comparable& x){insert(x, root);}//移除某个对象void remove(const Comparable& x){remove(x, root);} private:struct BinaryNode {Comparable element;BinaryNode* left;BinaryNode* right;BinaryNode(const Comparable& theElement, BinaryNode* lt, BinaryNode* rt):element(theElement), left(lt), right(rt){}};BinaryNode* root;//根结点//插入对象,这里使用了引用void insert(const Comparable& x, BinaryNode*& t)const{if (!t){t = new BinaryNode(x, nullptr, nullptr);}else if (x < t->element){insert(x, t->left);//比根结点小,插入左边}else if (x > t->element){insert(x, t->right);//比根结点大,插入右边}else{//相同的}} void removeMin(BinaryNode*& x, BinaryNode*& t)const{if (!t){return nullptr;//找不到}if (t->left){return removeMin(t->left);//使用了递归的方式}else{//找到最小的结点了x->element = t->element;BinaryNode* oldNode = t;t = t->right;delete oldNode;//删除原来要删除的结点return t;}}//删除某个对象,这里必须要引用void remove(const Comparable& x, BinaryNode*& t)const{if (!t){return;//树为空}else if (x < t->element){remove(x, t->left);//比根结点小,去左边查找}else if (x > t->element){remove(x, t->right);//比根结点大,去右边查找}else if (!t->left && !t->right)//找到结点了,有两个叶子{removeMin(t, t->right);}else{BinaryNode* oldNode = t;t = (t->left) ? t->left : t->right;//走到这里,t最多只有一个叶子,将t指向这个叶子delete oldNode;//删除原来要删除的结点}}//左边子树的结点肯定比当前根小的,所以一直往左边寻找BinaryNode* findMin(BinaryNode* t)const{if (!t){return nullptr;//找不到}if (!t->left){return t;}return findMin(t->left);//使用了递归的方式}//右边子树的结点肯定比当前根大,所以一直往右边找BinaryNode* findMax(BinaryNode* t)const{if (t){while (t->right)//使用了循环的方式{t = t->right;}}return t;}//判断是否包含某个对象,因为要使用递归,所以还有一个public版本的bool contains(const Comparable& x, BinaryNode* t)const{if ( !t ){return false;//空结点了}else if (x < t->element){//根据二叉树的定义,比某个结点小的对象,肯定只能存在与这个结点的左边的子树return contains(x, t->left);}else if (x > t->element){//根据二叉树的定义,比某个结点大的对象,肯定只能存在与这个结点的右边的子树return contains(x, t->right);}else{//相等,就是找到啦。return true;}}//清空子树void makeEmpty(BinaryNode*& t){if (t){makeEmpty(t->left);//清空左边makeEmpty(t->right);//清空右边delete t;//释放自身}t = nullptr;//置为空}//打印子树,这里没有使用复杂的排位,纯属打印void printTree(BinaryNode* t)const{if (!t){return;}std::cout << t->element << std::endl;//输出自身的对象printTree(t->left);//打印左子树printTree(t->right);//打印右子树}BinaryNode* clone(BinaryNode* t)const{if (!t){return nullptr;}return new BinaryNode(t->element, clone(t->left), clone(t->right));}};}#endif二叉树的所有操作平均运算时间是O(logN)。
但是在极端的情况下,是有可能失衡的,例如经常插入和删除数据,按上面的算法来说,是会造成左子树的比右子树深。
当极度失衡,就变成一个单向链表了。
有些经过转变的树会考虑着方面的问题,会做调整。下一章再说了。
1 0
- 数据结构:树tree和二叉树BinaryTree的实现与代码分析
- 数据结构 二叉树(binarytree)的实现
- java数据结构与算法之树基本概念及二叉树(BinaryTree)的设计与实现
- java数据结构与算法之树基本概念及二叉树(BinaryTree)的设计与实现
- [BinaryTree] 二叉树类的实现
- 数据结构BinaryTree实例(二):二叉树的中序遍历(递归与非递归)
- 数据结构BinaryTree实例(三):二叉树的后序遍历(递归与非递归)
- 数据结构二叉树BinaryTree之性质+推导
- 数据结构二叉树BinaryTree之遍历
- BinaryTree(0).关于平衡二叉树的实现
- 数据结构BinaryTree实例(五):树的深度与广度
- 数据结构二叉树BinaryTree之java构建二叉树
- 二叉树 BinaryTree.h
- 二叉树类BinaryTree
- 数据结构BinaryTree实例(一):先序遍历二叉树(递归与非递归)
- BinaryTree:学习二叉树的Python库
- 数据结构与算法分析-二叉查找树的实现
- BinaryTree的构建和遍历,以及搜索删除(非完全二叉树,非平衡二叉树)
- Elasticsearch 5.1.1 Embedded Mode
- was mutated while being enumerated
- Flask框架的学习与实战(三):登陆管理
- Sql小白入门(三)管理数据库对象
- 常用的优秀开源项目
- 数据结构:树tree和二叉树BinaryTree的实现与代码分析
- Memcached 安装以及安装php扩展
- Linux 下启动memcache
- 如何解锁oracle 11g中的用户Scott
- 使用WireShark分析HTTP协议时几种常见的汉字编码及其解码方法小结
- 搭建Hadoop集群的过程中的坑
- redis命令(key)
- Android ConstraintLayout 约束布局
- DEDECMS安全警告:Safe Alert: Request Error step 2!