javascript数据结构(七)树

1、树的定义

首先给出树的相关定义:树(tree)是包含n(n>0)个结点的有穷集,其中: 
1)每个元素称为结点(node); 
2)有一个特定的结点被称为根结点或树根(root); 
3)除根结点之外的其余数据元素被分为m(m≥0)个互不相交的集合T1,T2,……Tm-1,其中每一个集合Ti(1<=i<=m)本身也是一棵树,被称作原树的子树。 
树也可以这样定义:树是由根结点和若干颗子树构成的。树是由一个集合以及在该集合上定义的一种关系构成的。集合中的元素称为树的结点,所定义的关系称为父子关系。父子关系在树的结点之间建立了一个层次结构。在这种层次结构中有一个结点具有特殊的地位,这个结点称为该树的根结点,或称为树根。

2、树的相关术语

节点的度:一个节点含有的子树的个数称为该节点的度; 
叶节点或终端节点:度为0的节点称为叶节点; 
非终端节点或分支节点:度不为0的节点; 
双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点; 
孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点; 
兄弟节点:具有相同父节点的节点互称为兄弟节点; 
树的度:一棵树中,最大的节点的度称为树的度; 
节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推; 
树的高度或深度:树中节点的最大层次; 
堂兄弟节点:双亲在同一层的节点互为堂兄弟; 
节点的祖先:从根到该节点所经分支上的所有节点; 
子孙:以某节点为根的子树中任一节点都称为该节点的子孙。 
森林:由m(m>=0)棵互不相交的树的集合称为森林;

下面给出常见的树的概念,大部分内容可参考严蔚敏版《数据结构》:

3、二叉树

二叉树是数据结构中一种重要的数据结构,也是树表家族最为基础的结构。 
二叉树的定义:二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。二叉树的第i层至多有2i-1个结点;深度为k的二叉树至多有2k-1个结点;对任何一棵二叉树T,如果其终端结点数为n0,度为2的结点数为n2,则n0=n2+1。 
这里写图片描述

4、满二叉树

一棵深度为k且有2k-1(2的k次幂减1)个结点的二叉树称为满二叉树。 
这里写图片描述

5、完全二叉树

深度为k的,有n个结点的二叉树,当且仅当其每一个结点都与深度为k的满二叉树中编号从1至n的结点一一对应时,称之为完全二叉树。 
这里写图片描述

6、二叉排序树

二叉查找树定义:又称为是二叉排序树(Binary Sort Tree)或二叉搜索树。二叉排序树或者是一棵空树,或者是具有下列性质的二叉树: 
1) 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 
2) 若它的右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值; 
3) 它的左、右子树也分别为二叉排序树。 
这里写图片描述

7、平衡二叉树

平衡二叉树(Balanced Binary Tree)又被称为AVL树。它或者是一棵空树,或者是具有下列性质的二叉树:它的左子树和右子树都是平衡二叉树,且左子树和右子树的深度之差的绝对值不超过1。(注:平衡二叉树应该是一棵二叉排序树) 
这里写图片描述

二叉排序树的实现

 function BinarySearchTree() {
	var Node = function(key) {
		this.key = key;
		this.left = null;
		this.right = null;
	};
	var  root = null;
	this.insert = function(key) { 
		var  newNode  = new Node(key) ;

		if (root === null) {
			root = newNode;
		} else {
			insertNode(root,newNode);
		}
	};
	var insertNode = function(node, newNode){
		if (newNode.key < node.key) {
			if (node.left === null) {
				node.left = newNode;
			} else {
				insertNode(node.left, newNode);
			}
		} else {
			if (node.right === null) {
				node.right = newNode; 
			} else {
				insertNode(node.right, newNode);
			}
		}
	};

	// 中序遍历
	this.inOrderTraverse = function(callback) {
		inOrderTraverseNode(root, callback);
	};
	var inOrderTraverseNode = function(node, callback) {
		if (node != null) {
			inOrderTraverseNode(node.left, callback);
			callback(node.key);
			inOrderTraverseNode(node.right, callback);
		}
	};
	
	
	// 先序遍历
	this.preOrderTraverse = function(callback) {
		preOrderTraverseNode(node, callback);
	};
	var preOrderTraverseNode = function(node, callback) {
		if (node != null) {
			callback(node.key);
			preOrderTraverseNode(node.left, callback);
			preOrderTraverseNode(node.right, callback);
		}
	};
	// 后序遍历
	this.postOrderTraverse = function(callback) {
		postOrderTraverseNode(root, callback);
	};
	var postOrderTraverseNode = function(node, callback) {
		if (node != null) {
			postOrderTraverseNode(node.left, callback);
			postOrderTraverseNode(node.right, callback);
			callback(node.value);
		}
	};
	function printNode(value) {
		console.log(value);
	}
	this.min = function(node) {
		return minNode(root);
	};
	var minNode = function(node) {
		if(node) {
			while(node && node.left !== null) {
				node = node.left;
			}
			return node.key;
		}
		return null;
	};
	this.max = function() {
		return maxNode(root);
	};

	var maxNode = function(node) {
		if(node) {
			while(node && node.right !== null) {
				node = node.right;
			}
			return node.key;
		}
		return null;
	};

	this.search = function(key) {
		return searchNode(root, key);
	};

	var searchNode = function(node, key) {
		if(node === null) {
			return false;
		}
		if(key < node.key) {
			return searchNode(node.left, key);
		}  else if(key > node.key) {
			return searchNode(node.right, key);
		} else {
			return true;
		}
	};
	this.remove = function(key) {
		root =  removeNode(root, key);
	};

	var removeNode = function(node, key){
		if(node === null) {
			return false;
		}
		if(key < node.key) {
			node.left = removeNode(node, key);
			return  node;
		} else if(key > node.key) {
			node.right = removeNode(node, key);
			return node;
		} else {
			// 第一种情况叶节点
			if(node.left === null && node.right === null) {
				node = null;
				return node;
			}
			// 只有一个子节点的节点
			if(node.left === null) {
				node = node.right;
				return node;
			} else if (node.right === null) {
				node = node.left;
				return node;
			}
			// 有两个子节点的节点
			var aux = findMinNode(node.right);
			node.key = aux.key;
			node.right = removeNode(node.right, aux.key);
			return node;
		}
	};
	var findMinNode = function(node) {
		while(node && node.left !== null){ 
		node = node.left;
		}
		return node;
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值