Skip to content

Commit

Permalink
Bug fix: No rotation when delete root in AVL.
Browse files Browse the repository at this point in the history
  • Loading branch information
hwc0919 committed Mar 5, 2020
1 parent b2026d7 commit 16909ed
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 55 deletions.
17 changes: 10 additions & 7 deletions dist/TreePlayground.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
<div id="TreePlayground" @mousemove='onTPMouseMove($event)' @touchmove='onTPMouseMove($event)'>
<!-- Top Toolbar -->
<div class="top-toolbar">
<button class="btn btn-primary top-toolbar-item" type="button" @click="loadSampleTree(); update()">Sample</button>
<button class="btn btn-primary top-toolbar-item" type="button"
@click="loadSampleTree(); update()">Sample</button>
<button class="btn btn-primary top-toolbar-item" type="button" @click="traversal(0)">先序遍历</button>
<button class="btn btn-primary top-toolbar-item" type="button" @click="traversal(1)">中序遍历</button>
<button class="btn btn-primary top-toolbar-item" type="button" @click="traversal(2)">后序遍历</button>
Expand All @@ -38,18 +39,17 @@ <h4>Scale: <label v-text="commonParams.treeScale + '%'"></h4>
</div>
<!-- Tree Visualization Part -->
<div class="tree" ref="tree" :style="adjustScale" style="transform-origin: top;"
@mousedown.self="onTreeMouseDown" @mouseup.self="onTreeMouseLeave"
@touchstart.self="onTreeMouseDown" @touchend.self="onTreeMouseLeave">
@mousedown.self="onTreeMouseDown" @mouseup.self="onTreeMouseLeave" @touchstart.self="onTreeMouseDown"
@touchend.self="onTreeMouseLeave">
<!-- Top Functional Node -->
<top-binnode id="trvl-sequence" :data="topSequence" @top-build="onTopBuild" @top-insert="onTopInsert"
@top-search="onTopSearch" @top-help="onTopHelp" @top-proper="onTopProper"></top-binnode>
<div class="left-message">{{ messages.left }}</div>
<div class="right-message">{{ messages.right }}</div>
<!-- Internal Tree Nodes -->
<binnode v-for="(node, ind) in structInfo.nodes" :node="node" :key="'node' + ind"
:class="{'active-node': node.active, 'visited-node': node.visited}"
@remove-below="onRemoveBelow" @remove-one="onRemoveOne"
@intr-update="onIntrUpdate">
:class="{'active-node': node.active, 'visited-node': node.visited}" @remove-below="onRemoveBelow"
@remove-one="onRemoveOne" @intr-update="onIntrUpdate">
</binnode>
<!-- External Tree Nodes -->
<extr-binnode v-for="(node, ind) in structInfo.extrNodes" :node="node" :key="'extNode' + ind"
Expand All @@ -68,7 +68,10 @@ <h4>Scale: <label v-text="commonParams.treeScale + '%'"></h4>
:style="{'left': e[0]+'px', 'top': e[1]+'px', 'width': e[2]+'px', 'height': e[3]+'px'}"></div>
</div>
</div>
<div id="footer" style="position: fixed; left: 0; bottom: 0;">Copyright @ 2020 NitroMelon </div>
<div id="footer" style="position: fixed; left: 0; bottom: 0;">Copyright @ 2020 NitroMelon
<a href="https://github.com/hwc0919/TreePlayground" target="_blank">Source Code</a>
<a href="https://github.com/hwc0919/TreePlayground/issues" target="_blank">Bug report</a>
</div>
<script src="./bundle.js"></script>
</body>

Expand Down
61 changes: 37 additions & 24 deletions dist/bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -1647,6 +1647,7 @@ var vm = new _js_vue__WEBPACK_IMPORTED_MODULE_0___default.a({

// Events Handlers
onIntrUpdate(args) { // Internal node requests for value update
this.update();
let node = args[0];
let updation = args[1];
let successMessage = `Change ${node.data} to ${updation}`;
Expand All @@ -1660,8 +1661,10 @@ var vm = new _js_vue__WEBPACK_IMPORTED_MODULE_0___default.a({
node.data = updation;
this.update();
this.messages.left = successMessage;
node.active = true; // Caution: Mark recent active
}, // TODO: active newly updated node. Update before and after every action.
onExtrInsert(args) { // External node requests for value insertion
this.update();
let node = args[0];
let insertion = args[1];
let curTreeType = this.curTreeType;
Expand All @@ -1678,37 +1681,47 @@ var vm = new _js_vue__WEBPACK_IMPORTED_MODULE_0___default.a({
// check new order
if (!this.checkNodeOrder(node, insertion)) return false;
}
var updateH;
var updateH, retNode;
if (curTreeType === "BinTree" || curTreeType === "BST")
updateH = true;
else
updateH = false;

if (node.isRoot)
this.tree.insertAsRoot(insertion, updateH);
retNode = this.tree.insertAsRoot(insertion, updateH);
else if (node.isLC)
this.tree.insertAsLC(node.parent, insertion, updateH);
retNode = this.tree.insertAsLC(node.parent, insertion, updateH);
else
this.tree.insertAsRC(node.parent, insertion, updateH);
retNode = this.tree.insertAsRC(node.parent, insertion, updateH);

if (curTreeType === "AVL") {
this.tree.search(insertion); // locate _hot
this.tree.solveInsertUnbalance(); // TODO: change to async
}
this.update();
console.log(retNode);
retNode.active = true; // Caution: Mark recent active
this.messages.left = `Insert ${insertion}`;
},
checkNodeOrder(node, newV) {
let pred, succ;
let isLC = node.isLC || BinNode.isLC(node);
if (isLC === true && newV > node.parent.data ||
isLC === true && (pred = node.parent.pred()) && newV < pred.data ||
isLC === false && newV < node.parent.data ||
isLC === false && (succ = node.parent.succ()) && newV > succ.data ||
node.lc && newV < node.lc.data || node.rc && newV > node.rc.data) {
this.alertAsync("Must maintain order.", 2500);
return false;
} return true;
if (node.lc === undefined) { // External nodes
if (isLC === true && newV > node.parent.data ||
isLC === true && (pred = node.parent.pred()) && newV < pred.data ||
isLC === false && newV < node.parent.data ||
isLC === false && (succ = node.parent.succ()) && newV > succ.data) {
this.alertAsync("Must maintain order.", 2500);
return false;
}
} else { // Internal nodes
if ((pred = node.pred()) && newV < pred.data ||
(succ = node.succ()) && newV > succ.data) {
this.alertAsync("Must maintain order.", 2500);
return false;
}
}
return true;
},
// Remove whole subtree
onRemoveBelow(node) {
Expand All @@ -1720,10 +1733,8 @@ var vm = new _js_vue__WEBPACK_IMPORTED_MODULE_0___default.a({
onRemoveOne(node) {
this.tree.removeAt(node);
this.tree._size--;
if (this.curTreeType === "AVL") {
this.tree.search(node.data); // locate _hot
if (this.curTreeType === "AVL") // BugFixed0305 : _hot already at position after removeAt
this.tree.solveRemoveUnbalance();
}
else if (0) {}
this.update();
this.alertAsync(`Remove ${node.data}`);
Expand All @@ -1735,14 +1746,14 @@ var vm = new _js_vue__WEBPACK_IMPORTED_MODULE_0___default.a({
this.tree.buildFromBinSequence(sequence);
this.update();
this.messages.left = "真二叉树层次序列构建";

this.curTreeClass.checkValidity(this.tree, (res, message) => {
if (!res) this.alertAsync(message, 3000);
})
},
// Insert sequence
onTopInsert(sequence) {
console.log("Insert by sequence");
this.update();
this.topSequence = sequence;
this.insertAsync();
},
Expand All @@ -1752,12 +1763,15 @@ var vm = new _js_vue__WEBPACK_IMPORTED_MODULE_0___default.a({
let num = this.topSequence.shift();
this.messages.left = `Insert ${num}`;
this.trvlParams.lock = true;
this.searchAsync(this.tree.root(), num, (res) => {
if (res) this.alertAsync(`${num} Exists`);
else { this.tree.insert(num); this.alertAsync(`${num} Inserted`); }
this.searchAsync(this.tree.root(), num, (res, node) => {
let recentNode = null;
if (res) { this.alertAsync(`${num} Exists`); recentNode = node; }
else { recentNode = this.tree.insert(num); this.alertAsync(`${num} Inserted`); }
this.update();
this.trvlParams.lock = true;
this.insertAsync();
if (this.topSequence.length === 0) { // Caution: Add another quit check, to fasten last recent active!
recentNode.active = true; // Caution: Mark recent active
this.trvlParams.lock = false; return false;
} else this.insertAsync();
})
},
// Search value
Expand Down Expand Up @@ -1791,7 +1805,7 @@ var vm = new _js_vue__WEBPACK_IMPORTED_MODULE_0___default.a({
node.active = true;
if (num === node.data) {
this.trvlParams.lock = false; {
if (typeof callback === "function") callback(true);
if (typeof callback === "function") callback(true, node);
return true;
}
} else {
Expand Down Expand Up @@ -1880,9 +1894,8 @@ var vm = new _js_vue__WEBPACK_IMPORTED_MODULE_0___default.a({
},
watch: {
tree: {
handler(oldV, newV) {
handler() {
console.log("Detect Change in tree.");
// this.update();
},
deep: true,
},
Expand Down
61 changes: 37 additions & 24 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ var vm = new Vue({

// Events Handlers
onIntrUpdate(args) { // Internal node requests for value update
this.update();
let node = args[0];
let updation = args[1];
let successMessage = `Change ${node.data} to ${updation}`;
Expand All @@ -124,8 +125,10 @@ var vm = new Vue({
node.data = updation;
this.update();
this.messages.left = successMessage;
node.active = true; // Caution: Mark recent active
}, // TODO: active newly updated node. Update before and after every action.
onExtrInsert(args) { // External node requests for value insertion
this.update();
let node = args[0];
let insertion = args[1];
let curTreeType = this.curTreeType;
Expand All @@ -142,37 +145,47 @@ var vm = new Vue({
// check new order
if (!this.checkNodeOrder(node, insertion)) return false;
}
var updateH;
var updateH, retNode;
if (curTreeType === "BinTree" || curTreeType === "BST")
updateH = true;
else
updateH = false;

if (node.isRoot)
this.tree.insertAsRoot(insertion, updateH);
retNode = this.tree.insertAsRoot(insertion, updateH);
else if (node.isLC)
this.tree.insertAsLC(node.parent, insertion, updateH);
retNode = this.tree.insertAsLC(node.parent, insertion, updateH);
else
this.tree.insertAsRC(node.parent, insertion, updateH);
retNode = this.tree.insertAsRC(node.parent, insertion, updateH);

if (curTreeType === "AVL") {
this.tree.search(insertion); // locate _hot
this.tree.solveInsertUnbalance(); // TODO: change to async
}
this.update();
console.log(retNode);
retNode.active = true; // Caution: Mark recent active
this.messages.left = `Insert ${insertion}`;
},
checkNodeOrder(node, newV) {
let pred, succ;
let isLC = node.isLC || BinNode.isLC(node);
if (isLC === true && newV > node.parent.data ||
isLC === true && (pred = node.parent.pred()) && newV < pred.data ||
isLC === false && newV < node.parent.data ||
isLC === false && (succ = node.parent.succ()) && newV > succ.data ||
node.lc && newV < node.lc.data || node.rc && newV > node.rc.data) {
this.alertAsync("Must maintain order.", 2500);
return false;
} return true;
if (node.lc === undefined) { // External nodes
if (isLC === true && newV > node.parent.data ||
isLC === true && (pred = node.parent.pred()) && newV < pred.data ||
isLC === false && newV < node.parent.data ||
isLC === false && (succ = node.parent.succ()) && newV > succ.data) {
this.alertAsync("Must maintain order.", 2500);
return false;
}
} else { // Internal nodes
if ((pred = node.pred()) && newV < pred.data ||
(succ = node.succ()) && newV > succ.data) {
this.alertAsync("Must maintain order.", 2500);
return false;
}
}
return true;
},
// Remove whole subtree
onRemoveBelow(node) {
Expand All @@ -184,10 +197,8 @@ var vm = new Vue({
onRemoveOne(node) {
this.tree.removeAt(node);
this.tree._size--;
if (this.curTreeType === "AVL") {
this.tree.search(node.data); // locate _hot
if (this.curTreeType === "AVL") // BugFixed0305 : _hot already at position after removeAt
this.tree.solveRemoveUnbalance();
}
else if (0) { }
this.update();
this.alertAsync(`Remove ${node.data}`);
Expand All @@ -199,14 +210,14 @@ var vm = new Vue({
this.tree.buildFromBinSequence(sequence);
this.update();
this.messages.left = "真二叉树层次序列构建";

this.curTreeClass.checkValidity(this.tree, (res, message) => {
if (!res) this.alertAsync(message, 3000);
})
},
// Insert sequence
onTopInsert(sequence) {
console.log("Insert by sequence");
this.update();
this.topSequence = sequence;
this.insertAsync();
},
Expand All @@ -216,12 +227,15 @@ var vm = new Vue({
let num = this.topSequence.shift();
this.messages.left = `Insert ${num}`;
this.trvlParams.lock = true;
this.searchAsync(this.tree.root(), num, (res) => {
if (res) this.alertAsync(`${num} Exists`);
else { this.tree.insert(num); this.alertAsync(`${num} Inserted`); }
this.searchAsync(this.tree.root(), num, (res, node) => {
let recentNode = null;
if (res) { this.alertAsync(`${num} Exists`); recentNode = node; }
else { recentNode = this.tree.insert(num); this.alertAsync(`${num} Inserted`); }
this.update();
this.trvlParams.lock = true;
this.insertAsync();
if (this.topSequence.length === 0) { // Caution: Add another quit check, to fasten last recent active!
recentNode.active = true; // Caution: Mark recent active
this.trvlParams.lock = false; return false;
} else this.insertAsync();
})
},
// Search value
Expand Down Expand Up @@ -255,7 +269,7 @@ var vm = new Vue({
node.active = true;
if (num === node.data) {
this.trvlParams.lock = false; {
if (typeof callback === "function") callback(true);
if (typeof callback === "function") callback(true, node);
return true;
}
} else {
Expand Down Expand Up @@ -344,9 +358,8 @@ var vm = new Vue({
},
watch: {
tree: {
handler(oldV, newV) {
handler() {
console.log("Detect Change in tree.");
// this.update();
},
deep: true,
},
Expand Down

0 comments on commit 16909ed

Please sign in to comment.