非计算机专业出身对数据结构中的左子树、右子树的理解~

2,037 阅读5分钟

出去面试、被问到计算机数据结构和算法的问题,尴了个尬,听不懂,虽说自己是前端开发,平时算法的问题还是考虑的少点了,自己总结吧~多沉淀点~

  1. 什么是树?

树是一种数据结构,它是由n(n>=1)个有限结点组成一个具有层次关系的集合。附上图片:


树具有的特点有:

(1)每个结点有零个或多个子结点

(2)没有父节点的结点称为根节点

(3)每一个非根结点有且只有一个父节点

(4)除了根结点外,每个子结点可以分为多个不相交的子树。

2、什么是二叉树?

二叉树是每个结点最多有两个子树的树结构。它有五种基本形态:二叉树可以是空集;根可以有空的左子树或右子树;或者左、右子树皆为空。


二叉树的性质

  • 二叉树第i层的结点数目最多为:2i-1(i>=1)
  • 深度为k的二叉树至多有2k-1个结点(k>=1)
  • 包含n个结点的二叉树的高度至少为(log2n)+1

3、满二叉树、完全二叉树、二叉树查找树

  • 满二叉树

     定义:高度为h,并且由2h-1个结点组成的二叉树,称为满二叉树


  • 完全二叉树

定义:一棵二叉树中,只有最下面两层结点的度可以小于2,并且最下层的叶结点集中在靠左的若干位置上,这样的二叉树称为完全二叉树。

特点:叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部。显然,一棵满二叉树必定是一棵完全二叉树,而完全二叉树未必是满二叉树。


  • 二叉树查找树

       定义:二叉查找树又被称为二叉搜索树。设x为二叉查找树中的一个结点,x结点包含关键字key,结点x的key值计为key[x]。如果y是x的左子树中的一个结点,则key[y]<=key[x];如果y是x的右子树的一个结点,则key[y]>=key[x]


在二叉查找树种:

(1)若任意结点的左子树不空,则左子树上所有结点的值均小于它的根结点的值。

(2)任意结点的右子树不空,则右子树上所有结点的值均大于它的根结点的值。

(3)任意结点的左、右子树也分别为二叉查找树。

(4)没有键值相等的结点。

4、二叉树遍历

意思是从树的根节点出发,按照某种次序依次访问二叉树中所有的结点,使得每个结点被访问仅且一次。

分三种方式遍历:

先(根)序遍历:根左右
中(根)序遍历:左根右
后(根)序遍历:左右根

(function () {    // 顺序存储结构的遍历    var tree = [1, 2, 3, 4, 5, , 6, , , 7];
    console.log('preOrder:');    void function preOrderTraverse(x, visit) {        visit(tree[x]);        if (tree[2 * x + 1]) preOrderTraverse(2 * x + 1, visit);           if (tree[2 * x + 2]) preOrderTraverse(2 * x + 2, visit);       }(0, function (value) {           console.log(value);       }); //1、2、4、5、7、3、6          console.log('inOrder:');       void function inOrderTraverse(x, visit) {           if (tree[2 * x + 1]) inOrderTraverse(2 * x + 1, visit);           visit(tree[x]);           if (tree[2 * x + 2]) inOrderTraverse(2 * x + 2, visit);       }(0, function (value) {           console.log(value);       });//4、2、7、5、1、3、6          console.log('postOrder:');       void function postOrderTraverse(x, visit) {           if (tree[2 * x + 1]) postOrderTraverse(2 * x + 1, visit);           if (tree[2 * x + 2]) postOrderTraverse(2 * x + 2, visit);           visit(tree[x]);       }(0, function (value) {           console.log(value);       });   }());//4、7、5、2、6、3、1

以上是对二叉树的三种遍历(递归方法实现的)

用视图的形式 显示更清楚些:如下图所示:

                                       

先序遍历:ABCDEFGHK

中序遍历:BDCAEHGKF

后序遍历:DCBHKGFEA

(后续:中间也是一个计算机专业的同事帮我点了一下,睡个午觉也是忽然明白的\(^o^)/~)

二叉树还有很多操作,创建、查找、最大值、最小值的问题网上也是有很多,在这里,我就只贴出来二叉排序树的方法吧~

function BinaryTree (arr) {    if (Object.prototype.toString.call(arr).slice(8, -1) !== 'Array') {        throw new TypeError('只接受一个数组作为参数')    }    this.root = null; //根节点    this.arr = arr || []; //接受传入的参数-数组            //初始化每个树节点    var TreeNode = function (key) {        this.key = key; //当前节点的值        this.left = null; //左子树        this.right = null; //右子树    }        //构建二叉树    this.init = function () {        if (!this.arr) {            console.warn('请选择一个数组参数');        }        for (var i = 0, len = this.arr.length; i < len; i++) {            this.insert(this.arr[i])        }    }
    //插入节点    this.insert = function (key) {        var newNode = new TreeNode(key) //当前需要插入的节点        if (this.root === null) { //根节点不存在值时, 插入节点到根节点            this.root = newNode;        }else{            this.insertNode(this.root, newNode)        }    }    this.insertNode = function (rootNode, newNode) {        if (rootNode.key > newNode.key) { // 当前节点的key小于父节点时, 当前节点应该插入左子树            if (rootNode.left === null) { //如果左子树不存在节点时, 把当前节点放进去                rootNode.left = newNode;                return;            }            this.insertNode(rootNode.left, newNode) //左子树存在节点, 再次递归与该左节点进行比较        }else{ // 当前节点的key大于或等于父节点时, 当前节点应该插入右子树            if (rootNode.right === null) { //如果右子树不存在节点时, 把当前节点放进去                rootNode.right = newNode;                return;            }            this.insertNode(rootNode.right, newNode) //右子树存在节点, 再次递归与该右节点进行比较        }    }}       var arr = [8, 13,3,7,19,21,15];var tree = new BinaryTree(arr);tree.init();console.log(100,tree)

以下是生成是二叉排序树结构:



后边还有时间再继续更新总结吧~给自己个小心心,慢慢积累~加油加油!!!!