mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2025-01-18 11:14:05 +00:00
feat: Allow BinaryTree to support adding duplicate keys. docs: BinaryTree
This commit is contained in:
parent
a19080bb53
commit
b759eecf59
|
@ -1017,7 +1017,7 @@ pnpm perf:rbtree
|
|||
<td>Counter</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>LinkedHashMap<K, V></td>
|
||||
<td>ES6 Map<K, V></td>
|
||||
<td>-</td>
|
||||
<td>LinkedHashMap<K, V></td>
|
||||
<td>OrderedDict</td>
|
||||
|
|
|
@ -152,9 +152,10 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|||
) {
|
||||
super();
|
||||
if (options) {
|
||||
const { iterationType, toEntryFn, isMapMode } = options;
|
||||
const { iterationType, toEntryFn, isMapMode, isDuplicate } = options;
|
||||
if (iterationType) this.iterationType = iterationType;
|
||||
if (isMapMode !== undefined) this._isMapMode = isMapMode;
|
||||
if (isDuplicate !== undefined) this._isDuplicate = isDuplicate;
|
||||
if (typeof toEntryFn === 'function') this._toEntryFn = toEntryFn;
|
||||
else if (toEntryFn) throw TypeError('toEntryFn must be a function type');
|
||||
}
|
||||
|
@ -170,6 +171,12 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|||
return this._isMapMode;
|
||||
}
|
||||
|
||||
protected _isDuplicate = false;
|
||||
|
||||
get isDuplicate() {
|
||||
return this._isDuplicate;
|
||||
}
|
||||
|
||||
protected _store = new Map<K, V | undefined>();
|
||||
|
||||
get store() {
|
||||
|
@ -356,8 +363,8 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|||
* Space Complexity: O(1)
|
||||
*
|
||||
* The function `isRange` checks if the input parameter is an instance of the `Range` class.
|
||||
* @param {BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>> | Range<K>}
|
||||
* keyNodeEntryOrPredicate - The `keyNodeEntryOrPredicate` parameter in the `isRange` function can be
|
||||
* @param {BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>> | Range<K>} keyNodeEntryOrPredicate
|
||||
* - The `keyNodeEntryOrPredicate` parameter in the `isRange` function can be
|
||||
* of type `BTNRep<K, V, BinaryTreeNode<K, V>>`, `NodePredicate<BinaryTreeNode<K, V>>`, or
|
||||
* `Range<K>`. The function checks if the `keyNodeEntry
|
||||
* @returns The `isRange` function is checking if the `keyNodeEntryOrPredicate` parameter is an
|
||||
|
@ -461,11 +468,13 @@ export class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = o
|
|||
|
||||
if (!cur) continue;
|
||||
|
||||
// Check for duplicate keys when newNode is not null
|
||||
if (newNode !== null && cur.key === newNode.key) {
|
||||
this._replaceNode(cur, newNode);
|
||||
if (this._isMapMode) this._setValue(cur.key, newValue);
|
||||
return true; // If duplicate keys are found, no insertion is performed
|
||||
if (!this._isDuplicate) {
|
||||
// Check for duplicate keys when newNode is not null
|
||||
if (newNode !== null && cur.key === newNode.key) {
|
||||
this._replaceNode(cur, newNode);
|
||||
if (this._isMapMode) this._setValue(cur.key, newValue);
|
||||
return true; // If duplicate keys are found, no insertion is performed
|
||||
}
|
||||
}
|
||||
|
||||
// Record the first possible insertion location found
|
||||
|
|
|
@ -7,6 +7,7 @@ export type BinaryTreeOptions<K, V, R> = {
|
|||
iterationType?: IterationType;
|
||||
toEntryFn?: ToEntryFn<K, V, R>;
|
||||
isMapMode?: boolean;
|
||||
isDuplicate?: boolean;
|
||||
}
|
||||
|
||||
export type BinaryTreePrintOptions = { isShowUndefined?: boolean; isShowNull?: boolean; isShowRedBlackNIL?: boolean };
|
||||
|
|
|
@ -2,7 +2,7 @@ import type { BinaryTreeOptions } from './binary-tree';
|
|||
import { Comparable } from '../../utils';
|
||||
import { OptValue } from '../../common';
|
||||
|
||||
export type BSTOptions<K, V, R> = BinaryTreeOptions<K, V, R> & {
|
||||
export type BSTOptions<K, V, R> = Omit<BinaryTreeOptions<K, V, R>, 'isDuplicate'> & {
|
||||
specifyComparable?: (key: K) => Comparable
|
||||
isReverse?: boolean;
|
||||
}
|
||||
|
|
|
@ -1434,3 +1434,69 @@ describe('BinaryTree not map mode iterative methods test', () => {
|
|||
expect(cloned.get(cloned.root?.right)).toBe('c');
|
||||
});
|
||||
});
|
||||
|
||||
describe('classic use', () => {
|
||||
it('@example determine loan approval using a decision tree', () => {
|
||||
// Decision tree structure
|
||||
const loanDecisionTree = new BinaryTree<string>(
|
||||
['stableIncome', 'goodCredit', 'Rejected', 'Approved', 'Rejected'],
|
||||
{ isDuplicate: true }
|
||||
);
|
||||
|
||||
function determineLoanApproval(
|
||||
node?: BinaryTreeNode<string> | null,
|
||||
conditions?: { [key: string]: boolean }
|
||||
): string {
|
||||
if (!node) throw new Error('Invalid node');
|
||||
|
||||
// If it's a leaf node, return the decision result
|
||||
if (!node.left && !node.right) return node.key;
|
||||
|
||||
// Check if a valid condition exists for the current node's key
|
||||
return conditions?.[node.key]
|
||||
? determineLoanApproval(node.left, conditions)
|
||||
: determineLoanApproval(node.right, conditions);
|
||||
}
|
||||
|
||||
// Test case 1: Stable income and good credit score
|
||||
expect(determineLoanApproval(loanDecisionTree.root, { stableIncome: true, goodCredit: true })).toBe('Approved');
|
||||
|
||||
// Test case 2: Stable income but poor credit score
|
||||
expect(determineLoanApproval(loanDecisionTree.root, { stableIncome: true, goodCredit: false })).toBe('Rejected');
|
||||
|
||||
// Test case 3: No stable income
|
||||
expect(determineLoanApproval(loanDecisionTree.root, { stableIncome: false, goodCredit: true })).toBe('Rejected');
|
||||
|
||||
// Test case 4: No stable income and poor credit score
|
||||
expect(determineLoanApproval(loanDecisionTree.root, { stableIncome: false, goodCredit: false })).toBe('Rejected');
|
||||
});
|
||||
|
||||
it('@example evaluate the arithmetic expression represented by the binary tree', () => {
|
||||
const expressionTree = new BinaryTree<number | string>(['+', 3, '*', null, null, 5, '-', null, null, 2, 8]);
|
||||
|
||||
function evaluate(node?: BinaryTreeNode<number | string> | null): number {
|
||||
if (!node) return 0;
|
||||
|
||||
if (typeof node.key === 'number') return node.key;
|
||||
|
||||
const leftValue = evaluate(node.left); // Evaluate the left subtree
|
||||
const rightValue = evaluate(node.right); // Evaluate the right subtree
|
||||
|
||||
// Perform the operation based on the current node's operator
|
||||
switch (node.key) {
|
||||
case '+':
|
||||
return leftValue + rightValue;
|
||||
case '-':
|
||||
return leftValue - rightValue;
|
||||
case '*':
|
||||
return leftValue * rightValue;
|
||||
case '/':
|
||||
return rightValue !== 0 ? leftValue / rightValue : 0; // Handle division by zero
|
||||
default:
|
||||
throw new Error(`Unsupported operator: ${node.key}`);
|
||||
}
|
||||
}
|
||||
|
||||
expect(evaluate(expressionTree.root)).toBe(-27);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue