JS中的二叉搜尋樹
阿新 • • 發佈:2020-12-11
程式碼封裝:
//封裝二叉搜尋樹
function BinarySearchTree(){
//節點
function Node(key){
this.key = key;
this.left = null;
this.right = null;
}
//屬性
this.root = null;
//方法
//插入節點:給使用者呼叫的方法
BinarySearchTree.prototype.insert = function (key){
//1.根據key建立節點
var newNode = new Node(key);
//2.判斷根節點是否有值
if(this.root == null){
this.root = newNode;
}else{
this.insertNode (this.root,newNode)
}
}
//內部插入方法
BinarySearchTree.prototype.insertNode = function(node,newNode){
if(newNode.key < node.key){
//向左查詢
//如果左節點為空
if(node.left == null){
node. left = newNode;
}else{
//如果左節點不為空,遞迴查詢
this.insertNode(node.left,newNode);
}
}else{
//向右查詢
//如果右節點為空
if(node.right == null){
node.right = newNode;
}else{
this.insertNode(node.right,newNode);
}
}
}
//樹的遍歷
//1.先序遍歷
BinarySearchTree.prototype.preOrderTraversal = function(handler){
this.preOrderTraversalNode(this.root, handler);
}
BinarySearchTree.prototype.preOrderTraversalNode = function(node,handler){
if(node != null){
//1.處理經過的節點
handler(node.key);
//2.處理經過的節點的左子節點
this.preOrderTraversalNode(node.left,handler);
//3.處理經過的節點的右子節點
this.preOrderTraversalNode(node.right,handler);
}
}
//中序遍歷
BinarySearchTree.prototype.midOrderTraversal = function(handler){
this.midOrderTraversalNode(this.root, handler);
}
BinarySearchTree.prototype.midOrderTraversalNode = function(node,handler){
if(node != null){
//1.處理經過的節點的左子節點
this.midOrderTraversalNode(node.left,handler);
//2.處理經過的節點
handler(node.key);
//3.處理經過的節點的右子節點
this.midOrderTraversalNode(node.right,handler);
}
}
//後序遍歷
BinarySearchTree.prototype.postOrderTraversal = function(handler){
this.postOrderTraversalNode(this.root, handler);
}
BinarySearchTree.prototype.postOrderTraversalNode = function(node,handler){
if(node != null){
//1.處理經過的節點的左子節點
this.postOrderTraversalNode(node.left,handler);
//2.處理經過的節點的右子節點
this.postOrderTraversalNode(node.right,handler);
//3.處理經過的節點
handler(node.key);
}
}
//尋找最大值
BinarySearchTree.prototype.max = function(){
//1.獲取根節點
//2.依次向右不斷的查詢,直到節點為null
var node = this.root;
var key = null;
while(node !== null){
key = node.key;
node = node.right;
}
return key;
}
//尋找最小值
BinarySearchTree.prototype.min = function(){
var node = this.root;
var key = null;
//2.依次向右不斷的查詢,直到節點為null
while(node !== null){
key = node.key;
node = node.left;
}
return key;
}
BinarySearchTree.prototype.findMaxNode = function(node){
//1.獲取根節點
//2.依次向右不斷的查詢,直到節點為null
var parent = null;
var current = node;
while(1){
parent = current
current = current.right;
if(current.right === null){
break;
}
}
return [current,parent];
}
//搜尋某一個key
BinarySearchTree.prototype.search = function (key){
//1.獲取根節點
var node = this.root;
//2.迴圈搜尋key
while(node!= null){
if(key < node.key){
node = node.left;
}else if(key > node.key){
node = node.right;
}else{
return true;
}
}
return false;
}
//刪除節點
BinarySearchTree.prototype.remove = function (key){
//1.尋找我們要刪除的節點
//1.1定義變數,儲存資訊
var current = this.root;
var parent = null;
var isLeftChild = true;
//1.2開始尋找刪除的節點
while(current.key != key){
parent = current;
if(key < current.key){
isLeftChild = true;
current = current.left;
}else{
isLeftChild = false;
current = current.right;
}
//如果已經找到了最後一個節點,依然沒找到
if(current == null){
return false;
}
}
//2.根據對應的情況,刪除節點
//找到了current.key === key
if(current.left == null && current.right == null){ //2.1刪除的節點是葉子節點
//2.1.1刪除的是隻有一個節點的根節點
if(current == this.root){
this.root = null;
}else{
if(isLeftChild){
parent.left = null;
}else{
parent.right = null;
}
}
}else if(current.left != null && current.right != null){ //2.2刪除的節點有兩個子節點
var [max,maxParent] = this.findMaxNode(current.left);
console.log(max);
console.log(parent);
if(isLeftChild){
parent.left = max;
if(max!==current.left){
parent.left.left = current.left;
maxParent.right = null;
}
parent.left.right = current.right;
}else{
parent.right = max;
if(max!==current.left){
parent.right.left = current.left;
maxParent.right = null;
}
parent.right.right = current.right;
return;
}
}else{ //2.3刪除的節點有一個子節點
if(current === this.root){ //2.3.1刪除節點的是隻有一個子節點的根節點
if(isLeftChild){
this.root = current.left;
}else{
this.root = current.right;
}
}else if(current.left == null){ //2.3.2刪除節點的左子節點為空
//要刪除的節點是父節點的左子節點
if(isLeftChild){
parent.left = current.right;
}else{
//要刪除的節點是父節點的右子節點
parent.right = current.right
}
}else{ //2.3.2刪除節點的右子節點為空
//要刪除的節點是父節點的左子節點
if(isLeftChild){
parent.left = current.left;
}else{
//要刪除的節點是父節點的右子節點
parent.right = current.left
}
}
}
}
}