mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2024-11-23 12:54:04 +00:00
feat: The print method supports switches for empty nodes and guardian nodes. refactor: It eliminates some unnecessary type definitions.
This commit is contained in:
parent
cbe6dedfd6
commit
54c74f9af6
|
@ -8,7 +8,7 @@ All notable changes to this project will be documented in this file.
|
|||
- [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
|
||||
- [`auto-changelog`](https://github.com/CookPete/auto-changelog)
|
||||
|
||||
## [v1.46.7](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming)
|
||||
## [v1.46.8](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming)
|
||||
|
||||
### Changes
|
||||
|
||||
|
|
|
@ -48,15 +48,15 @@
|
|||
"type": "git",
|
||||
"url": "git+https://github.com/zrwusa/data-structure-typed.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/zrwusa/data-structure-typed/issues"
|
||||
},
|
||||
"homepage": "https://data-structure-typed-docs.vercel.app",
|
||||
"author": "Tyler Zeng <zrwusa@gmail.com>",
|
||||
"license": "MIT",
|
||||
"publishConfig": {
|
||||
"@zrwusa:registry": "https://npm.pkg.github.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/zrwusa/data-structure-typed/issues"
|
||||
},
|
||||
"homepage": "https://data-structure-typed-docs.vercel.app",
|
||||
"devDependencies": {
|
||||
"@swc/core": "^1.3.96",
|
||||
"@types/benchmark": "^2.1.3",
|
||||
|
|
|
@ -7,7 +7,14 @@
|
|||
*/
|
||||
|
||||
import type { BinaryTreeNodeNested, BinaryTreeOptions, BTNCallback, BTNKey } from '../../types';
|
||||
import { BiTreeDeleteResult, DFSOrderPattern, FamilyPosition, IterationType } from '../../types';
|
||||
import {
|
||||
BinaryTreePrintOptions,
|
||||
BiTreeDeleteResult,
|
||||
DFSOrderPattern,
|
||||
FamilyPosition,
|
||||
IterationType,
|
||||
NodeDisplayLayout
|
||||
} from '../../types';
|
||||
import { IBinaryTree } from '../../interfaces';
|
||||
import { trampoline } from '../../utils';
|
||||
import { Queue } from '../queue';
|
||||
|
@ -1727,16 +1734,25 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
|
||||
/**
|
||||
* The `print` function is used to display a binary tree structure in a visually appealing way.
|
||||
* @param {N | null | undefined} beginRoot - The `root` parameter is of type `BTNKey | N | null |
|
||||
* @param {BTNKey | N | null | undefined} [beginRoot=this.root] - The `root` parameter is of type `BTNKey | N | null |
|
||||
* undefined`. It represents the root node of a binary tree. The root node can have one of the
|
||||
* following types:
|
||||
* @param {BinaryTreePrintOptions} [options={ isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false}] - Options object that controls printing behavior. You can specify whether to display undefined, null, or sentinel nodes.
|
||||
*/
|
||||
print(beginRoot: BTNKey | N | null | undefined = this.root): void {
|
||||
print(beginRoot: BTNKey | N | null | undefined = this.root, options?: BinaryTreePrintOptions): void {
|
||||
const opts = { isShowUndefined: false, isShowNull: false, isShowRedBlackNIL: false, ...options };
|
||||
beginRoot = this.ensureNotKey(beginRoot);
|
||||
if (!beginRoot) return;
|
||||
|
||||
if (opts.isShowUndefined) console.log(`U for undefined
|
||||
`);
|
||||
if (opts.isShowNull) console.log(`N for null
|
||||
`);
|
||||
if (opts.isShowRedBlackNIL) console.log(`S for Sentinel Node
|
||||
`);
|
||||
|
||||
const display = (root: N | null | undefined): void => {
|
||||
const [lines, , ,] = this._displayAux(root);
|
||||
const [lines, , ,] = this._displayAux(root, opts);
|
||||
for (const line of lines) {
|
||||
console.log(line);
|
||||
}
|
||||
|
@ -1745,39 +1761,54 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
display(beginRoot);
|
||||
}
|
||||
|
||||
protected _displayAux(node: N | null | undefined): [string[], number, number, number] {
|
||||
if (!node) {
|
||||
return [['─'], 1, 0, 0];
|
||||
protected _displayAux(node: N | null | undefined, options: BinaryTreePrintOptions): NodeDisplayLayout {
|
||||
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
||||
const emptyDisplayLayout = <NodeDisplayLayout>[['─'], 1, 0, 0];
|
||||
|
||||
// Check if node is null or undefined or key is NaN
|
||||
if (node === null && !isShowNull) {
|
||||
return emptyDisplayLayout;
|
||||
} else if (node === undefined && !isShowUndefined) {
|
||||
return emptyDisplayLayout;
|
||||
} else if (node !== null && node !== undefined && isNaN(node.key) && !isShowRedBlackNIL) {
|
||||
return emptyDisplayLayout;
|
||||
} else if (node !== null && node !== undefined) {
|
||||
// Display logic of normal nodes
|
||||
|
||||
const key = node.key, line = isNaN(key) ? 'S' : key.toString(), width = line.length;
|
||||
|
||||
return _buildNodeDisplay(line, width, this._displayAux(node.left, options), this._displayAux(node.right, options))
|
||||
|
||||
} else {
|
||||
// For cases where none of the conditions are met, null, undefined, and NaN nodes are not displayed
|
||||
const line = node === undefined ? 'U' : 'N', width = line.length;
|
||||
|
||||
return _buildNodeDisplay(line, width, [[''], 1, 0, 0], [[''], 1, 0, 0])
|
||||
}
|
||||
|
||||
const line = node.key.toString();
|
||||
const width = line.length;
|
||||
function _buildNodeDisplay(line: string, width: number, left: NodeDisplayLayout, right: NodeDisplayLayout) {
|
||||
const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
|
||||
const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
|
||||
const firstLine = ' '.repeat(Math.max(0, leftMiddle + 1))
|
||||
+ '_'.repeat(Math.max(0, leftWidth - leftMiddle - 1))
|
||||
+ line
|
||||
+ '_'.repeat(Math.max(0, rightMiddle))
|
||||
+ ' '.repeat(Math.max(0, rightWidth - rightMiddle));
|
||||
|
||||
if (!node.left && !node.right) {
|
||||
return [[line], width, 1, Math.floor(width / 2)];
|
||||
const secondLine = (leftHeight > 0 ? ' '.repeat(leftMiddle) + '/' + ' '.repeat(leftWidth - leftMiddle - 1) : ' '.repeat(leftWidth))
|
||||
+ ' '.repeat(width)
|
||||
+ (rightHeight > 0 ? ' '.repeat(rightMiddle) + '\\' + ' '.repeat(rightWidth - rightMiddle - 1) : ' '.repeat(rightWidth));
|
||||
|
||||
const mergedLines = [firstLine, secondLine];
|
||||
|
||||
for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
|
||||
const leftLine = i < leftHeight ? leftLines[i] : ' '.repeat(leftWidth);
|
||||
const rightLine = i < rightHeight ? rightLines[i] : ' '.repeat(rightWidth);
|
||||
mergedLines.push(leftLine + ' '.repeat(width) + rightLine);
|
||||
}
|
||||
|
||||
return <NodeDisplayLayout>[mergedLines, leftWidth + width + rightWidth, Math.max(leftHeight, rightHeight) + 2, leftWidth + Math.floor(width / 2)];
|
||||
}
|
||||
|
||||
const [leftLines, leftWidth, leftHeight, leftMiddle] = node.left ? this._displayAux(node.left) : [[''], 0, 0, 0];
|
||||
const [rightLines, rightWidth, rightHeight, rightMiddle] = node.right ? this._displayAux(node.right) : [[''], 0, 0, 0];
|
||||
|
||||
const firstLine = ' '.repeat(Math.max(0, leftMiddle + 1))
|
||||
+ '_'.repeat(Math.max(0, leftWidth - leftMiddle - 1))
|
||||
+ line
|
||||
+ '_'.repeat(Math.max(0, rightMiddle))
|
||||
+ ' '.repeat(Math.max(0, rightWidth - rightMiddle));
|
||||
|
||||
const secondLine = (leftHeight > 0 ? ' '.repeat(leftMiddle) + '/' + ' '.repeat(leftWidth - leftMiddle - 1) : ' '.repeat(leftWidth))
|
||||
+ ' '.repeat(width)
|
||||
+ (rightHeight > 0 ? ' '.repeat(rightMiddle) + '\\' + ' '.repeat(rightWidth - rightMiddle - 1) : ' '.repeat(rightWidth));
|
||||
|
||||
const mergedLines = [firstLine, secondLine];
|
||||
for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
|
||||
const leftLine = i < leftHeight ? leftLines[i] : ' '.repeat(leftWidth);
|
||||
const rightLine = i < rightHeight ? rightLines[i] : ' '.repeat(rightWidth);
|
||||
mergedLines.push(leftLine + ' '.repeat(width) + rightLine);
|
||||
}
|
||||
|
||||
return [mergedLines, leftWidth + width + rightWidth, Math.max(leftHeight, rightHeight) + 2, leftWidth + Math.floor(width / 2)];
|
||||
}
|
||||
|
||||
protected _defaultOneParamCallback = (node: N) => node.key;
|
||||
|
|
|
@ -10,11 +10,6 @@ export enum CP {
|
|||
gt = 'gt'
|
||||
}
|
||||
|
||||
export const enum IterateDirection {
|
||||
DEFAULT = 0,
|
||||
REVERSE = 1
|
||||
}
|
||||
|
||||
export interface IterableWithSize<T> extends Iterable<T> {
|
||||
size: number | ((...args: any[]) => number);
|
||||
}
|
||||
|
@ -24,3 +19,5 @@ export interface IterableWithLength<T> extends Iterable<T> {
|
|||
}
|
||||
|
||||
export type IterableWithSizeOrLength<T> = IterableWithSize<T> | IterableWithLength<T>
|
||||
|
||||
export type BinaryTreePrintOptions = {isShowUndefined?: boolean, isShowNull?: boolean, isShowRedBlackNIL?: boolean}
|
|
@ -29,9 +29,5 @@ export type BiTreeDeleteResult<N> = { deleted: N | null | undefined; needBalance
|
|||
export type BinaryTreeNodeNested<T> = BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
|
||||
export type BinaryTreeOptions = { iterationType?: IterationType }
|
||||
//
|
||||
// export type BTNIdentifierOrNU<N> = BTNKey | N | null | undefined;
|
||||
//
|
||||
// export type BTNIdentifierOrU<N> = BTNKey | N | undefined;
|
||||
//
|
||||
// export type BTNOrNU<N> = N | null | undefined;
|
||||
|
||||
export type NodeDisplayLayout = [string[], number, number, number];
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
<head>
|
||||
<meta charset='UTF-8'>
|
||||
<title>CDN Test</title>
|
||||
<script src="../../dist/umd/data-structure-typed.min.js"></script>
|
||||
<!-- <script src="../../dist/umd/data-structure-typed.js"></script>-->
|
||||
<!-- <script src="../../dist/umd/data-structure-typed.min.js"></script>-->
|
||||
<script src="../../dist/umd/data-structure-typed.js"></script>
|
||||
<!-- <script src='https://cdn.jsdelivr.net/npm/data-structure-typed/dist/umd/data-structure-typed.min.js'></script>-->
|
||||
<!-- <script src='https://cdn.jsdelivr.net/npm/data-structure-typed@1.42.2/dist/umd/data-structure-typed.min.js'></script>-->
|
||||
<!-- <script src='https://cdn.jsdelivr.net/npm/data-structure-typed@1.43.3/dist/umd/data-structure-typed.min.js'></script>-->
|
||||
|
@ -19,17 +19,18 @@
|
|||
</ul>
|
||||
</div>
|
||||
<script defer>
|
||||
|
||||
const $modules = document.querySelector('.modules');
|
||||
|
||||
|
||||
try {
|
||||
const { Queue } = dataStructureTyped;
|
||||
const queue = new Queue();
|
||||
const n = 100000;
|
||||
const n = 1000000;
|
||||
const startEn = performance.now();
|
||||
for (let i = 0; i < n; i++) {
|
||||
queue.enqueue(i);
|
||||
}
|
||||
console.log(`Queue ${n} enqueue `, performance.now() - startEn);
|
||||
console.log((performance.now() - startEn).toFixed(2), `Queue ${n.toLocaleString()} enqueue `);
|
||||
let last = 0;
|
||||
const startTime = performance.now();
|
||||
|
||||
|
@ -37,13 +38,14 @@
|
|||
last = queue.dequeue();
|
||||
}
|
||||
|
||||
console.log(`Queue ${n} dequeue `, performance.now() - startTime);
|
||||
console.log((performance.now() - startTime).toFixed(2) ,`Queue ${n.toLocaleString()} dequeue `);
|
||||
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
try {
|
||||
const { AVLTree } = window.dataStructureTyped;
|
||||
const { AVLTree } = dataStructureTyped;
|
||||
|
||||
const avlTree = new AVLTree();
|
||||
const $avlTree = document.createElement('li');
|
||||
const $avlTreeSpan = document.createElement('span');
|
||||
|
@ -52,8 +54,8 @@
|
|||
for (let i = 1; i < 31; i++) {
|
||||
avlTree.add(i, i);
|
||||
}
|
||||
console.log(avlTree.bfs());
|
||||
// avlTree.print();
|
||||
console.log(avlTree.bfs(), `avlTree.bfs()`);
|
||||
avlTree.print();
|
||||
$modules.append($avlTree);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
@ -66,18 +68,18 @@
|
|||
tree.add(12);
|
||||
tree.addMany([1, 6, 9, 8, 5, 2, 3, 4, 7])
|
||||
tree.add(10);
|
||||
console.log(tree.isPerfectlyBalanced());
|
||||
tree.print();
|
||||
console.log(tree.isPerfectlyBalanced(), `tree.isPerfectlyBalanced()`);
|
||||
tree.print(undefined, {isShowUndefined: true});
|
||||
|
||||
const node3 = tree.getNode(3);
|
||||
if (node3) node3.right = tree.createNode(1);
|
||||
console.log(tree.isPerfectlyBalanced());
|
||||
console.log(tree.isPerfectlyBalanced(), `tree.isPerfectlyBalanced()`);
|
||||
tree.print();
|
||||
|
||||
tree.clear();
|
||||
tree.addMany([1, null, 2, null, 3, null, 4, null, 5, null, 6, null]);
|
||||
console.log(tree.isPerfectlyBalanced());
|
||||
tree.print();
|
||||
console.log(tree.isPerfectlyBalanced(), `tree.isPerfectlyBalanced()`);
|
||||
tree.print(undefined, {isShowNull: true});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
@ -85,26 +87,26 @@
|
|||
|
||||
try {
|
||||
const { OrderedMap } = sdsl;
|
||||
const { RedBlackTree, AVLTree } = dataStructureTyped;
|
||||
const { RedBlackTree } = dataStructureTyped;
|
||||
const cRBTree = new OrderedMap();
|
||||
const rbTree = new RedBlackTree();
|
||||
const tS = performance.now();
|
||||
const n = 100000;
|
||||
for (let i = 1; i < n; i++) {
|
||||
for (let i = 0; i < n; i++) {
|
||||
rbTree.add(i, i);
|
||||
}
|
||||
console.log(`RedBlackTree ${n} add`, performance.now() - tS);
|
||||
console.log(rbTree.size);
|
||||
console.log(( performance.now() - tS).toFixed(2), `RedBlackTree ${n.toLocaleString()} add`);
|
||||
console.log(`rbTree.size`, rbTree.size);
|
||||
for (let i = 0; i < n - 20; i++) {
|
||||
rbTree.delete(i)
|
||||
}
|
||||
rbTree.print(rbTree.root,{isShowRedBlackNIL: true});
|
||||
const cS = performance.now();
|
||||
for (let i = 1; i < 100000; i++) {
|
||||
cRBTree.setElement(i, i);
|
||||
}
|
||||
console.log(`CRedBlackTree ${n} add`, performance.now() - cS);
|
||||
console.log(cRBTree.size());
|
||||
|
||||
// console.log(tree.isPerfectlyBalanced());
|
||||
// tree.print();
|
||||
|
||||
console.log((performance.now() - cS).toFixed(2), `CRedBlackTree ${n.toLocaleString()} add`);
|
||||
console.log(cRBTree.size(), `cRBTree.size()`);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
@ -123,8 +125,8 @@
|
|||
for (let i = 0; i < n; i++) {
|
||||
pq.pop();
|
||||
}
|
||||
console.log(`PriorityQueue ${n} add`, performance.now() - tS);
|
||||
console.log(pq.size);
|
||||
console.log(( performance.now() - tS).toFixed(2), `PriorityQueue ${n.toLocaleString()} add`);
|
||||
console.log(pq.size, `pq.size`);
|
||||
const cS = performance.now();
|
||||
const cpq = new CPriorityQueue();
|
||||
|
||||
|
@ -135,8 +137,8 @@
|
|||
for (let i = 0; i < n; i++) {
|
||||
cpq.pop();
|
||||
}
|
||||
console.log(`CPriorityQueue ${n} add`, performance.now() - cS);
|
||||
console.log(cpq.size());
|
||||
console.log((performance.now() - cS).toFixed(), `CPriorityQueue ${n.toLocaleString()} add`);
|
||||
console.log(cpq.size(), `cpq.size()`);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue