AVLNode.js
/**
* @author redcrow
* @link http://na5cent.blogspot.com/2013/06/avl-tree-javascript.html
* @create 25/06/2013
*/
var AVLNode = function(item) {
var item_ = item || null;
var left_ = null;
var right_ = null;
var height_ = 0;
this.getItem = function() {
return item_;
};
this.getLeft = function() {
return left_;
};
this.setLeft = function(node) {
left_ = node;
};
this.getRight = function() {
return right_;
};
this.setRight = function(node) {
right_ = node;
};
this.getHeight = function() {
return height_;
};
this.size = function(node) {
if (node === null) {
return 0;
} else {
return size(node.getLeft()) + size(node.getRight()) + 1;
}
};
this.preorderPrint = function(padding) {
padding = padding || '';
padding = '--' + padding;
console.log(padding + item_);
if (left_ !== null) {
left_.preorderPrint(padding);
}
if (right_ !== null) {
right_.preorderPrint(padding);
}
};
this.inorderPrint = function(padding) {
padding = padding || '';
padding = '--' + padding;
if (left_ !== null) {
left_.inorderPrint(padding);
}
console.log(padding + item_);
if (right_ !== null) {
right_.inorderPrint(padding);
}
};
this.postorderPrint = function(padding) {
padding = padding || '';
padding = '--' + padding;
if (left_ !== null) {
left_.postorderPrint(padding);
}
if (right_ !== null) {
right_.postorderPrint(padding);
}
console.log(padding + item_);
};
};
AVLTree.js
/**
* @author redcrow
* @link http://na5cent.blogspot.com/2013/06/avl-tree-javascript.html
* @create 25/06/2013
*/
var AVLTree = function() {
var root_ = null;
var lastNode_;
var deleteNode_;
this.getRoot = function() {
return root_;
};
var height_ = function(node) {
if (node === null) {
return -1;
} else {
return Math.max(height_(node.getLeft()), height_(node.getRight())) + 1;
}
};
this.height = function(node) {
return height_(node);
};
var singleRotateRight_ = function(node) {
var tmp = node.getLeft();
node.setLeft(tmp.getRight());
tmp.setRight(node);
return tmp;
};
var singleRotateLeft_ = function(node) {
var tmp = node.getRight();
node.setRight(tmp.getLeft());
tmp.setLeft(node);
return tmp;
};
var doubleRotateRight_ = function(node) {
node.setLeft(singleRotateLeft_(node.getLeft()));
return singleRotateRight_(node);
};
var doubleRotateLeft_ = function(node) {
node.setRight(singleRotateRight_(node.getRight()));
return singleRotateLeft_(node);
};
var insert_ = function(key, node) {
if (node === null) {
node = new AVLNode(key);
} else if (key < node.getItem()) {
node.setLeft(insert_(key, node.getLeft()));
if (node.getLeft() !== null) {
if ((height_(node.getLeft()) - height_(node.getRight())) === 2) {
if (key < node.getLeft().getItem()) {
node = singleRotateRight_(node);
} else {
node = doubleRotateRight_(node);
}
}
}
} else if (key > node.getItem()) {
node.setRight(insert_(key, node.getRight()));
if (node.getRight() !== null) {
if ((height_(node.getRight()) - height_(node.getLeft())) === 2) {
if (key > node.getRight().getItem()) {
node = singleRotateLeft_(node);
} else {
node = doubleRotateLeft_(node);
}
}
}
} else {
//duplicate not allow!
}
return node;
};
this.insertNode = function(key) {
root_ = insert_(key, root_);
};
var delete_ = function(key, node) {
if (node === null) {
return null;
}
lastNode_ = node;
if (key < node.getItem()) {
node.setLeft(delete_(key, node.getLeft()));
} else {
deleteNode_ = node;
node.setRight(delete_(key, node.getRight()));
}
if (node === lastNode_) {
if (deleteNode_ !== null && key === deleteNode_.getItem()) {
if (deleteNode_ === lastNode_) {
node = node.getLeft();
} else {
var tmp = deleteNode_.getItem();
deleteNode_.setItem(lastNode_.getItem());
lastNode_.setItem(tmp);
node = node.getRight();
}
}
} else {
if ((height_(node.getLeft()) - height_(node.getRight())) === 2) {
if (key < node.getLeft().getItem()) {
node = singleRotateRight_(node);
} else {
node = doubleRotateRight_(node);
}
}
if ((height_(node.getRight()) - height_(node.getLeft())) === 2) {
if (key > node.getRight().getItem()) {
node = singleRotateLeft_(node);
} else {
node = doubleRotateLeft_(node);
}
}
}
};
this.deleteNode = function(key) {
lastNode_ = null;
deleteNode_ = null;
root_ = delete_(key, root_);
};
this.findMinNode = function(node) {
if (node !== null) {
while (node.getLeft() !== null) {
node = node.getLeft();
}
}
return node;
};
this.findMaxNode = function(node) {
if (node !== null) {
while (node.getRight() !== null) {
node = node.getRight();
}
}
return node;
};
var removeMinNode_ = function(node) {
if (node === null) {
console.log('Error! tree is empty.');
return null;
} else if (node.getLeft() !== null) {
node.setLeft(removeMinNode_(node.getLeft()));
return node;
} else {
return node.getRight();
}
};
var removeMaxNode_ = function(node) {
if (node === null) {
console.log('Error! tree is empty.');
return null;
} else if (node.getRight() !== null) {
node.setRight(removeMaxNode_(node.getRight()));
return node;
} else {
return node.getLeft();
}
};
this.removeMinNode = function(node) {
return removeMinNode_(node);
};
this.removeMaxNode = function(node) {
return removeMaxNode_(node);
};
this.printAVLTree = function() {
console.log('Items : ');
root_.preorderPrint();
console.log();
};
};
Main.js
/**
* @author redcrow
* @link http://na5cent.blogspot.com/2013/06/avl-tree-javascript.html
* @create 25/06/2013
*/
var tree = new AVLTree();
var data = [8, 12, 14, 18, 20, 21, 23, 33, 48, 50, 52, 60, 80, 100, 23, 50, 59, 50, 40, 30, 20, -2, 40, 30];
for (var i = 0; i < data.length; i++) {
tree.insertNode(data[i]);
}
//tree.printAVLTree();
//console.log('root => ' + tree.getRoot().getItem());
var parent = document.getElementsByTagName('body')[0];
walkTree(tree.getRoot(), parent, 255);
//console.log('tree height => '+ tree.height(tree.getRoot()));
function walkTree(node, parent, color) {
var element = document.createElement('div');
element.setAttribute('style', 'background-color : rgb(' + color + ',' + color + ',' + color + ')');
element.setAttribute('class', 'tree-node');
var item = document.createElement('center');
color = color - 10;
if (node !== null) {
item.innerHTML = node.getItem();
element.appendChild(item);
parent.appendChild(element);
walkTree(node.getLeft(), element, color);
walkTree(node.getRight(), element, color);
} else {
item.innerHTML = 'null';
element.appendChild(item);
parent.appendChild(element);
}
}
UI.css
.tree-node{
border : solid 1px #ccc;
float: left;
margin: 5px;
border-radius: 20px;
padding : 5px;
}
.tree-node center{
font-weight : bold;
padding-top : 5px;
}

ไม่มีความคิดเห็น:
แสดงความคิดเห็น