JavaScript数据结构和算法之二叉树详解


Posted in Javascript onFebruary 11, 2015

二叉树的概念

二叉树(Binary Tree)是n(n>=0)个结点的有限集合,该集合或者为空集(空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树的二叉树组成。

JavaScript数据结构和算法之二叉树详解

二叉树的特点

每个结点最多有两棵子树,所以二叉树中不存在度大于2的结点。二叉树中每一个节点都是一个对象,每一个数据节点都有三个指针,分别是指向父母、左孩子和右孩子的指针。每一个节点都是通过指针相互连接的。相连指针的关系都是父子关系。

二叉树节点的定义

二叉树节点定义如下:

struct BinaryTreeNode

{

    int m_nValue;

    BinaryTreeNode* m_pLeft;

    BinaryTreeNode* m_pRight;

};

二叉树的五种基本形态

空二叉树
只有一个根结点
根结点只有左子树
根结点只有右子树
根结点既有左子树又有右子树

JavaScript数据结构和算法之二叉树详解

拥有三个结点的普通树只有两种情况:两层或者三层。但由于二叉树要区分左右,所以就会演变成如下的五种形态:

JavaScript数据结构和算法之二叉树详解

特殊二叉树

斜树

如上面倒数第一副图的第2、3小图所示。

满二叉树

在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树。如下图所示:

JavaScript数据结构和算法之二叉树详解

完全二叉树

完全二叉树是指最后一层左边是满的,右边可能满也可能不满,然后其余层都是满的。一个深度为k,节点个数为 2^k - 1 的二叉树为满二叉树(完全二叉树)。就是一棵树,深度为k,并且没有空位。

完全二叉树的特点有:

叶子结点只能出现在最下两层。

最下层的叶子一定集中在左部连续位置。

倒数第二层,若有叶子结点,一定都在右部连续位置。

如果结点度为1,则该结点只有左孩子。

同样结点树的二叉树,完全二叉树的深度最小。

JavaScript数据结构和算法之二叉树详解

注意:满二叉树一定是完全二叉树,但完全二叉树不一定是满二叉树。

算法如下:

bool is_complete(tree *root)  

{  

    queue q;  

    tree *ptr;  

    // 进行广度优先遍历(层次遍历),并把NULL节点也放入队列  

    q.push(root);  

    while ((ptr = q.pop()) != NULL)  

    {  

        q.push(ptr->left);  

        q.push(ptr->right);  

    } 
    // 判断是否还有未被访问到的节点  

    while (!q.is_empty())  

    {  

        ptr = q.pop(); 
        // 有未访问到的的非NULL节点,则树存在空洞,为非完全二叉树  

        if (NULL != ptr)  

        {  

            return false;  

        }  

    } 
    return true;  

} 

二叉树的性质

二叉树的性质一:在二叉树的第i层上至多有2^(i-1)个结点(i>=1)

二叉树的性质二:深度为k的二叉树至多有2^k-1个结点(k>=1)

二叉树的顺序存储结构

二叉树的顺序存储结构就是用一维数组存储二叉树中的各个结点,并且结点的存储位置能体现结点之间的逻辑关系。

JavaScript数据结构和算法之二叉树详解

二叉链表

既然顺序存储方式的适用性不强,那么我们就要考虑链式存储结构啦。二叉树的存储按照国际惯例来说一般也是采用链式存储结构的。

二叉树每个结点最多有两个孩子,所以为它设计一个数据域和两个指针域是比较自然的想法,我们称这样的链表叫做二叉链表。

JavaScript数据结构和算法之二叉树详解

二叉树的遍历

二叉树的遍历(traversing binary tree)是指从根结点出发,按照某种次序依次访问二叉树中所有结点,使得每个结点被访问一次且仅被访问一次。

二叉树的遍历有三种方式,如下:

(1)前序遍历(DLR),首先访问根结点,然后遍历左子树,最后遍历右子树。简记根-左-右。

(2)中序遍历(LDR),首先遍历左子树,然后访问根结点,最后遍历右子树。简记左-根-右。

(3)后序遍历(LRD),首先遍历左子树,然后遍历右子树,最后访问根结点。简记左-右-根。

前序遍历:

若二叉树为空,则空操作返回,否则先访问根结点,然后前序遍历左子树,再前序遍历右子树。

遍历的顺序为:A B D H I E J C F K G

//先序遍历

function preOrder(node){

    if(!node == null){

        putstr(node.show()+ " ");

        preOrder(node.left);

        preOrder(node.right);

    }

}

中序遍历:

若树为空,则空操作返回,否则从根结点开始(注意并不是先访问根结点),中序遍历根结点的左子树,然后是访问根结点,最后中序遍历右子树。

JavaScript数据结构和算法之二叉树详解

遍历的顺序为:H D I B E J A F K C G

//使用递归方式实现中序遍历

function inOrder(node){

    if(!(node == null)){

        inOrder(node.left);//先访问左子树

        putstr(node.show()+ " ");//再访问根节点

        inOrder(node.right);//最后访问右子树

    }

}

后序遍历:

若树为空,则空操作返回,否则从左到右先叶子后结点的方式遍历访问左右子树,最后访问根结点。

JavaScript数据结构和算法之二叉树详解

遍历的顺序为:H I D J E B K F G C A

//后序遍历

function postOrder(node){

    if(!node == null){

        postOrder(node.left);

        postOrder(node.right);

        putStr(node.show()+ " ");

    }

}

实现二叉查找树

二叉查找树(BST)由节点组成,所以我们定义一个Node节点对象如下:

function Node(data,left,right){

    this.data = data;

    this.left = left;//保存left节点链接

    this.right = right;

    this.show = show;

}


function show(){

    return this.data;//显示保存在节点中的数据

}

查找最大和最小值

查找BST上的最小值和最大值非常简单,因为较小的值总是在左子节点上,在BST上查找最小值,只需遍历左子树,直到找到最后一个节点

查找最小值

function getMin(){

    var current = this.root;

    while(!(current.left == null)){

        current = current.left;

    }

    return current.data;

}

该方法沿着BST的左子树挨个遍历,直到遍历到BST最左的节点,该节点被定义为:
current.left = null;

这时,当前节点上保存的值就是最小值

查找最大值

在BST上查找最大值只需要遍历右子树,直到找到最后一个节点,该节点上保存的值就是最大值。

function getMax(){

    var current = this.root;

    while(!(current.right == null)){

        current = current.right;

    }

    return current.data;

}
Javascript 相关文章推荐
jQuery bind事件使用详解
May 05 Javascript
js将控件隐藏的方法及display属性介绍
Jul 04 Javascript
jQuery修改CSS伪元素属性的方法
Jul 30 Javascript
AngularJS的一些基本样式初窥
Jul 27 Javascript
Javascript实现图片轮播效果(一)让图片跳动起来
Feb 17 Javascript
jqGrid 学习笔记整理——进阶篇(一 )
Apr 17 Javascript
用js制作淘宝放大镜效果
Oct 28 Javascript
解决微信二次分享不显示摘要和图片的问题
Aug 18 Javascript
vue地区选择组件教程详解
May 04 Javascript
JS实现获取毫秒值及转换成年月日时分秒的方法
Aug 15 Javascript
node.js的Express服务器基本使用教程
Jan 09 Javascript
vue3.0中使用postcss-pxtorem的具体方法
Nov 20 Javascript
JavaScript中的函数模式详解
Feb 11 #Javascript
Javascript核心读书有感之表达式和运算符
Feb 11 #Javascript
JavaScript数据结构和算法之图和图算法
Feb 11 #Javascript
Javascript核心读书有感之类型、值和变量
Feb 11 #Javascript
JavaScript中的继承方式详解
Feb 11 #Javascript
JavaScript中原型和原型链详解
Feb 11 #Javascript
Node.js中的缓冲与流模块详细介绍
Feb 11 #Javascript
You might like
Terran历史背景
2020/03/14 星际争霸
php不使用copy()函数复制文件的方法
2015/03/13 PHP
javaScript 简单验证代码(用户名,密码,邮箱)
2009/09/28 Javascript
Javascript技巧之不要用for in语句对数组进行遍历
2010/10/20 Javascript
表单JS弹出填写提示效果代码
2011/04/16 Javascript
JS+CSS实现带关闭按钮DIV弹出窗口的方法
2015/02/27 Javascript
基于jquery实现可定制的web在线富文本编辑器附源码下载
2015/11/17 Javascript
基于JavaScript代码实现pc与手机之间的跳转
2015/12/23 Javascript
用js实现放大镜的效果的简单实例
2016/05/23 Javascript
浅谈jQuery animate easing的具体使用方法(推荐)
2016/06/17 Javascript
深入理解Commonjs规范及Node模块实现
2017/05/17 Javascript
基于AngularJS实现的工资计算器实例
2017/06/16 Javascript
解决JS内存泄露之js对象和dom对象互相引用问题
2017/06/25 Javascript
详解基于Angular4+ server render(服务端渲染)开发教程
2017/08/28 Javascript
基于dataset的使用和图片延时加载的实现方法
2017/12/11 Javascript
php中and 和 &&出坑指南
2018/07/13 Javascript
微信小程序实现留言功能
2018/10/31 Javascript
24行JavaScript代码实现Redux的方法实例
2019/11/17 Javascript
vue使用swiper实现中间大两边小的轮播图效果
2019/11/24 Javascript
jQuery使用hide()、toggle()函数实现相机品牌展示隐藏功能
2021/01/29 jQuery
Python写的一个简单DNS服务器实例
2014/06/04 Python
python面向对象多线程爬虫爬取搜狐页面的实例代码
2018/05/31 Python
python接口自动化如何封装获取常量的类
2019/12/24 Python
使用PyTorch将文件夹下的图片分为训练集和验证集实例
2020/01/08 Python
Python sorted对list和dict排序
2020/06/09 Python
使用Python实现NBA球员数据查询小程序功能
2020/11/09 Python
浅谈h5自定义audio(问题及解决)
2016/08/19 HTML / CSS
英国户外装备商店:Ultimate Outdoors
2019/05/07 全球购物
澳大利亚一站式数码相机商店:CameraPro
2020/03/09 全球购物
报关报检委托书
2014/04/08 职场文书
《月亮湾》教学反思
2014/04/14 职场文书
大型活动组织方案
2014/05/10 职场文书
中班上学期个人总结
2015/02/12 职场文书
python 爬取豆瓣网页的示例
2021/04/13 Python
MySQL令人大跌眼镜的隐式转换
2021/08/23 MySQL
python模块与C和C++动态库相互调用实现过程示例
2021/11/02 Python