二叉樹作爲一種子節點不超過兩個的樹形結構,在查詢檢索方面的性能還是不錯的。比如對於敏感詞信息的檢索上,無論是鏈表還是map,其性能都無法跟二叉樹相比較。
1 定義
1.1 幾個約定:
1.1.1 左節點的值<父節點的值<右節點的值
//定義節點對象
var Node=function(data,left,right){
this.data=data;
this.left=left;
this.right=right;
}
//二叉樹對象
var BST=function(){
this.root=null;
this.fnInsert=fnInsert;//插入
this.fnInorder=fnInorder;//遍歷
this.fnGetMin=fnGetMin;//獲取最小值
this.fnGetMax=fnGetMax;//獲取最大值
this.fnFind=fnFind;//檢索查詢
this.fnRemove=fnRemove;//刪除
}
2 幾個方法:
//插入節點
//插入節點
/**
* 1 從根節點開始執行插入操作
* 2 判斷當前值與 當前節點的大小-依次是左節點-右節點
* 3 如果比當前節點小,且左節點不存在,放置在左節點
* 4 如果比當前節點大,且右節點不存在,放置在右節點
* @param {Object} data
*/
var fnInsert=function(data){
var node=new Node(data,null,null);
if(this.root==null){
this.root=node;
}else{
var current=this.root;
var parent;
while(true){
parent=current;
if(data>parent.data){
if(parent.right==null){
parent.right=node;
break;
}
current=parent.right;
}else{
if(parent.left==null){
parent.left=node;
break;
}
current=parent.left;
}
}
}
}
var fnInorder =function(node){
if(node!=null){
console.log(node.data);
fnInorder(node.left);
fnInorder(node.right);
}
}
//查找最小值-最左側節點值
var fnGetMin=function(){
var current=this.root;
while(current.left!=null){
current=current.left;
}
return current.data;
}
//查找最大值-最右側節點值
var fnGetMax=function(){
var current=this.root;
while(current.right!=null){
current=current.right;
}
return current.data;
}
//查詢檢索--當前節點-左節點-右節點循環遍歷
var fnFind=function(data){
var current=this.root;
while(current!=null){
if(current.data==data){
return current;
}else if(current.data<data) {
current=current.right;
}else {
current=current.left;
}
}
return null;
}
//刪除節點
var fnRemove=function(data){
root=fnRemoveNode(this.root,data);
}
//刪除節點
/**
* 1 當前節點沒有子節點-直接刪除
* 2 當前節點只有一個子節點-當前節點的父節點指向其子節點
* 3 當前節點有兩個子節點
* 3.1 查詢當前節點右節點的最小值-或者當前節點左節點的最大值--至於爲什麼-看圖體會
* 3.2 將上一步查找到的節點放置於當前節點
* 3.3 移除3.1查找到的節點
* @param {Object} data
*/
var fnGetSmallest=function(node){
var current=node;
while(current.left!=null){
current=current.left;
}
return current;
}
//
var fnRemoveNode=function(node,data){
if(node==null){
return null;
}
if(node.data==data){
if(node.right==null&&node.left==null){
return null;
}
if(node.left==null){
return node.right;
}
if(node.right==null){
return node.left;
}
var temNode=fnGetSmallest(node.right);
node.data=temNode.data;
node.right=fnRemoveNode(node.right,temNode.data);
return node;
}else if(data<node.data){
node.left=fnRemoveNode(node.left,data);
return node;
}else{
node.right=fnRemoveNode(node.right,data);
return node;
}
}
測試:
var bst=new BST();
bst.fnInsert(23);
bst.fnInsert(46);
bst.fnInsert(15);
bst.fnInsert(37);
bst.fnInsert(3);
bst.fnInsert(99);
bst.fnInsert(21);
bst.fnInsert(22);
bst.fnInsert(17);
bst.fnInorder(bst.root);
console.log(bst);
var min=bst.fnGetMin();//獲取最小值
var max=bst.fnGetMax();//獲取最大值
console.log('min,max',min,max);
var cur3=bst.fnFind(3);
var cur13=bst.fnFind(13);
console.log(cur3);
console.log(cur13);
bst.fnRemove(15);//移除節點
bst.fnInorder(bst.root);
console.log(bst);
刪除前節點:
3 一個應用--統計文本單詞的數量;
3.1 修改Node,添加count屬性
//定義節點對象
var Node=function(data,left,right){
this.data=data;
this.count=1;
this.left=left;
this.right=right;
}
3.2 添加統計方法;
var fnUpdate=function(data){
var node=this.fnFind(data);
node.count++;
return node;
}
3.3 修改Bst
//二叉樹對象
var BST=function(){
this.root=null;
this.fnInsert=fnInsert;//插入
this.fnInorder=fnInorder;//遍歷
this.fnGetMin=fnGetMin;//獲取最小值
this.fnGetMax=fnGetMax;//獲取最大值
this.fnFind=fnFind;//檢索查詢
this.fnRemove=fnRemove;//刪除
this.fnUpdate=fnUpdate;//更新
}
3.4測試
var str='aa,bb,dd,cc,dd,ee,aa,bb,cc,dd,dd,aa,dd,dd,aa,ee,dd,ee';
var bst=new BST();
var strArr=str.split(',');
for(var i=0;i<strArr.length;i++){
var node=bst.fnFind(strArr[i]);
if(node==null){
bst.fnInsert(strArr[i]);
}else{
bst.fnUpdate(strArr[i]);
}
}
bst.fnInorder(bst.root);
結果: