Skip to content

Commit 16909ed

Browse files
committed
Bug fix: No rotation when delete root in AVL.
1 parent b2026d7 commit 16909ed

File tree

3 files changed

+84
-55
lines changed

3 files changed

+84
-55
lines changed

dist/TreePlayground.html

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
<div id="TreePlayground" @mousemove='onTPMouseMove($event)' @touchmove='onTPMouseMove($event)'>
1515
<!-- Top Toolbar -->
1616
<div class="top-toolbar">
17-
<button class="btn btn-primary top-toolbar-item" type="button" @click="loadSampleTree(); update()">Sample</button>
17+
<button class="btn btn-primary top-toolbar-item" type="button"
18+
@click="loadSampleTree(); update()">Sample</button>
1819
<button class="btn btn-primary top-toolbar-item" type="button" @click="traversal(0)">先序遍历</button>
1920
<button class="btn btn-primary top-toolbar-item" type="button" @click="traversal(1)">中序遍历</button>
2021
<button class="btn btn-primary top-toolbar-item" type="button" @click="traversal(2)">后序遍历</button>
@@ -38,18 +39,17 @@ <h4>Scale: <label v-text="commonParams.treeScale + '%'"></h4>
3839
</div>
3940
<!-- Tree Visualization Part -->
4041
<div class="tree" ref="tree" :style="adjustScale" style="transform-origin: top;"
41-
@mousedown.self="onTreeMouseDown" @mouseup.self="onTreeMouseLeave"
42-
@touchstart.self="onTreeMouseDown" @touchend.self="onTreeMouseLeave">
42+
@mousedown.self="onTreeMouseDown" @mouseup.self="onTreeMouseLeave" @touchstart.self="onTreeMouseDown"
43+
@touchend.self="onTreeMouseLeave">
4344
<!-- Top Functional Node -->
4445
<top-binnode id="trvl-sequence" :data="topSequence" @top-build="onTopBuild" @top-insert="onTopInsert"
4546
@top-search="onTopSearch" @top-help="onTopHelp" @top-proper="onTopProper"></top-binnode>
4647
<div class="left-message">{{ messages.left }}</div>
4748
<div class="right-message">{{ messages.right }}</div>
4849
<!-- Internal Tree Nodes -->
4950
<binnode v-for="(node, ind) in structInfo.nodes" :node="node" :key="'node' + ind"
50-
:class="{'active-node': node.active, 'visited-node': node.visited}"
51-
@remove-below="onRemoveBelow" @remove-one="onRemoveOne"
52-
@intr-update="onIntrUpdate">
51+
:class="{'active-node': node.active, 'visited-node': node.visited}" @remove-below="onRemoveBelow"
52+
@remove-one="onRemoveOne" @intr-update="onIntrUpdate">
5353
</binnode>
5454
<!-- External Tree Nodes -->
5555
<extr-binnode v-for="(node, ind) in structInfo.extrNodes" :node="node" :key="'extNode' + ind"
@@ -68,7 +68,10 @@ <h4>Scale: <label v-text="commonParams.treeScale + '%'"></h4>
6868
:style="{'left': e[0]+'px', 'top': e[1]+'px', 'width': e[2]+'px', 'height': e[3]+'px'}"></div>
6969
</div>
7070
</div>
71-
<div id="footer" style="position: fixed; left: 0; bottom: 0;">Copyright @ 2020 NitroMelon </div>
71+
<div id="footer" style="position: fixed; left: 0; bottom: 0;">Copyright @ 2020 NitroMelon
72+
<a href="https://github.com/hwc0919/TreePlayground" target="_blank">Source Code</a>
73+
<a href="https://github.com/hwc0919/TreePlayground/issues" target="_blank">Bug report</a>
74+
</div>
7275
<script src="./bundle.js"></script>
7376
</body>
7477

dist/bundle.js

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,6 +1647,7 @@ var vm = new _js_vue__WEBPACK_IMPORTED_MODULE_0___default.a({
16471647

16481648
// Events Handlers
16491649
onIntrUpdate(args) { // Internal node requests for value update
1650+
this.update();
16501651
let node = args[0];
16511652
let updation = args[1];
16521653
let successMessage = `Change ${node.data} to ${updation}`;
@@ -1660,8 +1661,10 @@ var vm = new _js_vue__WEBPACK_IMPORTED_MODULE_0___default.a({
16601661
node.data = updation;
16611662
this.update();
16621663
this.messages.left = successMessage;
1664+
node.active = true; // Caution: Mark recent active
16631665
}, // TODO: active newly updated node. Update before and after every action.
16641666
onExtrInsert(args) { // External node requests for value insertion
1667+
this.update();
16651668
let node = args[0];
16661669
let insertion = args[1];
16671670
let curTreeType = this.curTreeType;
@@ -1678,37 +1681,47 @@ var vm = new _js_vue__WEBPACK_IMPORTED_MODULE_0___default.a({
16781681
// check new order
16791682
if (!this.checkNodeOrder(node, insertion)) return false;
16801683
}
1681-
var updateH;
1684+
var updateH, retNode;
16821685
if (curTreeType === "BinTree" || curTreeType === "BST")
16831686
updateH = true;
16841687
else
16851688
updateH = false;
16861689

16871690
if (node.isRoot)
1688-
this.tree.insertAsRoot(insertion, updateH);
1691+
retNode = this.tree.insertAsRoot(insertion, updateH);
16891692
else if (node.isLC)
1690-
this.tree.insertAsLC(node.parent, insertion, updateH);
1693+
retNode = this.tree.insertAsLC(node.parent, insertion, updateH);
16911694
else
1692-
this.tree.insertAsRC(node.parent, insertion, updateH);
1695+
retNode = this.tree.insertAsRC(node.parent, insertion, updateH);
16931696

16941697
if (curTreeType === "AVL") {
16951698
this.tree.search(insertion); // locate _hot
16961699
this.tree.solveInsertUnbalance(); // TODO: change to async
16971700
}
16981701
this.update();
1702+
console.log(retNode);
1703+
retNode.active = true; // Caution: Mark recent active
16991704
this.messages.left = `Insert ${insertion}`;
17001705
},
17011706
checkNodeOrder(node, newV) {
17021707
let pred, succ;
17031708
let isLC = node.isLC || BinNode.isLC(node);
1704-
if (isLC === true && newV > node.parent.data ||
1705-
isLC === true && (pred = node.parent.pred()) && newV < pred.data ||
1706-
isLC === false && newV < node.parent.data ||
1707-
isLC === false && (succ = node.parent.succ()) && newV > succ.data ||
1708-
node.lc && newV < node.lc.data || node.rc && newV > node.rc.data) {
1709-
this.alertAsync("Must maintain order.", 2500);
1710-
return false;
1711-
} return true;
1709+
if (node.lc === undefined) { // External nodes
1710+
if (isLC === true && newV > node.parent.data ||
1711+
isLC === true && (pred = node.parent.pred()) && newV < pred.data ||
1712+
isLC === false && newV < node.parent.data ||
1713+
isLC === false && (succ = node.parent.succ()) && newV > succ.data) {
1714+
this.alertAsync("Must maintain order.", 2500);
1715+
return false;
1716+
}
1717+
} else { // Internal nodes
1718+
if ((pred = node.pred()) && newV < pred.data ||
1719+
(succ = node.succ()) && newV > succ.data) {
1720+
this.alertAsync("Must maintain order.", 2500);
1721+
return false;
1722+
}
1723+
}
1724+
return true;
17121725
},
17131726
// Remove whole subtree
17141727
onRemoveBelow(node) {
@@ -1720,10 +1733,8 @@ var vm = new _js_vue__WEBPACK_IMPORTED_MODULE_0___default.a({
17201733
onRemoveOne(node) {
17211734
this.tree.removeAt(node);
17221735
this.tree._size--;
1723-
if (this.curTreeType === "AVL") {
1724-
this.tree.search(node.data); // locate _hot
1736+
if (this.curTreeType === "AVL") // BugFixed0305 : _hot already at position after removeAt
17251737
this.tree.solveRemoveUnbalance();
1726-
}
17271738
else if (0) {}
17281739
this.update();
17291740
this.alertAsync(`Remove ${node.data}`);
@@ -1735,14 +1746,14 @@ var vm = new _js_vue__WEBPACK_IMPORTED_MODULE_0___default.a({
17351746
this.tree.buildFromBinSequence(sequence);
17361747
this.update();
17371748
this.messages.left = "真二叉树层次序列构建";
1738-
17391749
this.curTreeClass.checkValidity(this.tree, (res, message) => {
17401750
if (!res) this.alertAsync(message, 3000);
17411751
})
17421752
},
17431753
// Insert sequence
17441754
onTopInsert(sequence) {
17451755
console.log("Insert by sequence");
1756+
this.update();
17461757
this.topSequence = sequence;
17471758
this.insertAsync();
17481759
},
@@ -1752,12 +1763,15 @@ var vm = new _js_vue__WEBPACK_IMPORTED_MODULE_0___default.a({
17521763
let num = this.topSequence.shift();
17531764
this.messages.left = `Insert ${num}`;
17541765
this.trvlParams.lock = true;
1755-
this.searchAsync(this.tree.root(), num, (res) => {
1756-
if (res) this.alertAsync(`${num} Exists`);
1757-
else { this.tree.insert(num); this.alertAsync(`${num} Inserted`); }
1766+
this.searchAsync(this.tree.root(), num, (res, node) => {
1767+
let recentNode = null;
1768+
if (res) { this.alertAsync(`${num} Exists`); recentNode = node; }
1769+
else { recentNode = this.tree.insert(num); this.alertAsync(`${num} Inserted`); }
17581770
this.update();
1759-
this.trvlParams.lock = true;
1760-
this.insertAsync();
1771+
if (this.topSequence.length === 0) { // Caution: Add another quit check, to fasten last recent active!
1772+
recentNode.active = true; // Caution: Mark recent active
1773+
this.trvlParams.lock = false; return false;
1774+
} else this.insertAsync();
17611775
})
17621776
},
17631777
// Search value
@@ -1791,7 +1805,7 @@ var vm = new _js_vue__WEBPACK_IMPORTED_MODULE_0___default.a({
17911805
node.active = true;
17921806
if (num === node.data) {
17931807
this.trvlParams.lock = false; {
1794-
if (typeof callback === "function") callback(true);
1808+
if (typeof callback === "function") callback(true, node);
17951809
return true;
17961810
}
17971811
} else {
@@ -1880,9 +1894,8 @@ var vm = new _js_vue__WEBPACK_IMPORTED_MODULE_0___default.a({
18801894
},
18811895
watch: {
18821896
tree: {
1883-
handler(oldV, newV) {
1897+
handler() {
18841898
console.log("Detect Change in tree.");
1885-
// this.update();
18861899
},
18871900
deep: true,
18881901
},

src/app.js

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ var vm = new Vue({
111111

112112
// Events Handlers
113113
onIntrUpdate(args) { // Internal node requests for value update
114+
this.update();
114115
let node = args[0];
115116
let updation = args[1];
116117
let successMessage = `Change ${node.data} to ${updation}`;
@@ -124,8 +125,10 @@ var vm = new Vue({
124125
node.data = updation;
125126
this.update();
126127
this.messages.left = successMessage;
128+
node.active = true; // Caution: Mark recent active
127129
}, // TODO: active newly updated node. Update before and after every action.
128130
onExtrInsert(args) { // External node requests for value insertion
131+
this.update();
129132
let node = args[0];
130133
let insertion = args[1];
131134
let curTreeType = this.curTreeType;
@@ -142,37 +145,47 @@ var vm = new Vue({
142145
// check new order
143146
if (!this.checkNodeOrder(node, insertion)) return false;
144147
}
145-
var updateH;
148+
var updateH, retNode;
146149
if (curTreeType === "BinTree" || curTreeType === "BST")
147150
updateH = true;
148151
else
149152
updateH = false;
150153

151154
if (node.isRoot)
152-
this.tree.insertAsRoot(insertion, updateH);
155+
retNode = this.tree.insertAsRoot(insertion, updateH);
153156
else if (node.isLC)
154-
this.tree.insertAsLC(node.parent, insertion, updateH);
157+
retNode = this.tree.insertAsLC(node.parent, insertion, updateH);
155158
else
156-
this.tree.insertAsRC(node.parent, insertion, updateH);
159+
retNode = this.tree.insertAsRC(node.parent, insertion, updateH);
157160

158161
if (curTreeType === "AVL") {
159162
this.tree.search(insertion); // locate _hot
160163
this.tree.solveInsertUnbalance(); // TODO: change to async
161164
}
162165
this.update();
166+
console.log(retNode);
167+
retNode.active = true; // Caution: Mark recent active
163168
this.messages.left = `Insert ${insertion}`;
164169
},
165170
checkNodeOrder(node, newV) {
166171
let pred, succ;
167172
let isLC = node.isLC || BinNode.isLC(node);
168-
if (isLC === true && newV > node.parent.data ||
169-
isLC === true && (pred = node.parent.pred()) && newV < pred.data ||
170-
isLC === false && newV < node.parent.data ||
171-
isLC === false && (succ = node.parent.succ()) && newV > succ.data ||
172-
node.lc && newV < node.lc.data || node.rc && newV > node.rc.data) {
173-
this.alertAsync("Must maintain order.", 2500);
174-
return false;
175-
} return true;
173+
if (node.lc === undefined) { // External nodes
174+
if (isLC === true && newV > node.parent.data ||
175+
isLC === true && (pred = node.parent.pred()) && newV < pred.data ||
176+
isLC === false && newV < node.parent.data ||
177+
isLC === false && (succ = node.parent.succ()) && newV > succ.data) {
178+
this.alertAsync("Must maintain order.", 2500);
179+
return false;
180+
}
181+
} else { // Internal nodes
182+
if ((pred = node.pred()) && newV < pred.data ||
183+
(succ = node.succ()) && newV > succ.data) {
184+
this.alertAsync("Must maintain order.", 2500);
185+
return false;
186+
}
187+
}
188+
return true;
176189
},
177190
// Remove whole subtree
178191
onRemoveBelow(node) {
@@ -184,10 +197,8 @@ var vm = new Vue({
184197
onRemoveOne(node) {
185198
this.tree.removeAt(node);
186199
this.tree._size--;
187-
if (this.curTreeType === "AVL") {
188-
this.tree.search(node.data); // locate _hot
200+
if (this.curTreeType === "AVL") // BugFixed0305 : _hot already at position after removeAt
189201
this.tree.solveRemoveUnbalance();
190-
}
191202
else if (0) { }
192203
this.update();
193204
this.alertAsync(`Remove ${node.data}`);
@@ -199,14 +210,14 @@ var vm = new Vue({
199210
this.tree.buildFromBinSequence(sequence);
200211
this.update();
201212
this.messages.left = "真二叉树层次序列构建";
202-
203213
this.curTreeClass.checkValidity(this.tree, (res, message) => {
204214
if (!res) this.alertAsync(message, 3000);
205215
})
206216
},
207217
// Insert sequence
208218
onTopInsert(sequence) {
209219
console.log("Insert by sequence");
220+
this.update();
210221
this.topSequence = sequence;
211222
this.insertAsync();
212223
},
@@ -216,12 +227,15 @@ var vm = new Vue({
216227
let num = this.topSequence.shift();
217228
this.messages.left = `Insert ${num}`;
218229
this.trvlParams.lock = true;
219-
this.searchAsync(this.tree.root(), num, (res) => {
220-
if (res) this.alertAsync(`${num} Exists`);
221-
else { this.tree.insert(num); this.alertAsync(`${num} Inserted`); }
230+
this.searchAsync(this.tree.root(), num, (res, node) => {
231+
let recentNode = null;
232+
if (res) { this.alertAsync(`${num} Exists`); recentNode = node; }
233+
else { recentNode = this.tree.insert(num); this.alertAsync(`${num} Inserted`); }
222234
this.update();
223-
this.trvlParams.lock = true;
224-
this.insertAsync();
235+
if (this.topSequence.length === 0) { // Caution: Add another quit check, to fasten last recent active!
236+
recentNode.active = true; // Caution: Mark recent active
237+
this.trvlParams.lock = false; return false;
238+
} else this.insertAsync();
225239
})
226240
},
227241
// Search value
@@ -255,7 +269,7 @@ var vm = new Vue({
255269
node.active = true;
256270
if (num === node.data) {
257271
this.trvlParams.lock = false; {
258-
if (typeof callback === "function") callback(true);
272+
if (typeof callback === "function") callback(true, node);
259273
return true;
260274
}
261275
} else {
@@ -344,9 +358,8 @@ var vm = new Vue({
344358
},
345359
watch: {
346360
tree: {
347-
handler(oldV, newV) {
361+
handler() {
348362
console.log("Detect Change in tree.");
349-
// this.update();
350363
},
351364
deep: true,
352365
},

0 commit comments

Comments
 (0)