出去面试、被问到计算机数据结构和算法的问题,尴了个尬,听不懂,虽说自己是前端开发,平时算法的问题还是考虑的少点了,自己总结吧~多沉淀点~
- 什么是树?
树是一种数据结构,它是由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)
以下是生成是二叉排序树结构:
后边还有时间再继续更新总结吧~给自己个小心心,慢慢积累~加油加油!!!!