mirror of
https://github.com/trekhleb/javascript-algorithms.git
synced 2025-12-19 08:59:05 +08:00
Add disjoint set.
This commit is contained in:
@@ -25,6 +25,8 @@ export default class DisjointSet {
|
||||
}
|
||||
|
||||
/**
|
||||
* Find set representation node.
|
||||
*
|
||||
* @param {*} itemValue
|
||||
* @return {(string|null)}
|
||||
*/
|
||||
@@ -42,6 +44,8 @@ export default class DisjointSet {
|
||||
}
|
||||
|
||||
/**
|
||||
* Union by rank.
|
||||
*
|
||||
* @param {*} valueA
|
||||
* @param {*} valueB
|
||||
* @return {DisjointSet}
|
||||
@@ -62,7 +66,7 @@ export default class DisjointSet {
|
||||
const rootA = this.items[rootKeyA];
|
||||
const rootB = this.items[rootKeyB];
|
||||
|
||||
if (rootA.getAncestorsCount() < rootB.getAncestorsCount()) {
|
||||
if (rootA.getRank() < rootB.getRank()) {
|
||||
// If rootB's tree is bigger then make rootB to be a new root.
|
||||
rootB.addChild(rootA);
|
||||
|
||||
|
||||
@@ -39,25 +39,27 @@ export default class DisjointSetItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Rank basically means the number of all ancestors.
|
||||
*
|
||||
* @return {number}
|
||||
*/
|
||||
getAncestorsCount() {
|
||||
getRank() {
|
||||
if (this.getChildren().length === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let count = 0;
|
||||
let rank = 0;
|
||||
|
||||
/** @var {DisjointSetItem} child */
|
||||
this.getChildren().forEach((child) => {
|
||||
// Count child itself.
|
||||
count += 1;
|
||||
rank += 1;
|
||||
|
||||
// Also add all children of current child.
|
||||
count += child.getAncestorsCount();
|
||||
rank += child.getRank();
|
||||
});
|
||||
|
||||
return count;
|
||||
return rank;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,7 @@ describe('DisjointSetItem', () => {
|
||||
const itemC = new DisjointSetItem('C');
|
||||
const itemD = new DisjointSetItem('D');
|
||||
|
||||
expect(itemA.getAncestorsCount()).toBe(0);
|
||||
expect(itemA.getRank()).toBe(0);
|
||||
expect(itemA.getChildren()).toEqual([]);
|
||||
expect(itemA.getKey()).toBe('A');
|
||||
expect(itemA.getRoot()).toEqual(itemA);
|
||||
@@ -17,11 +17,11 @@ describe('DisjointSetItem', () => {
|
||||
itemA.addChild(itemB);
|
||||
itemD.setParent(itemC);
|
||||
|
||||
expect(itemA.getAncestorsCount()).toBe(1);
|
||||
expect(itemC.getAncestorsCount()).toBe(1);
|
||||
expect(itemA.getRank()).toBe(1);
|
||||
expect(itemC.getRank()).toBe(1);
|
||||
|
||||
expect(itemB.getAncestorsCount()).toBe(0);
|
||||
expect(itemD.getAncestorsCount()).toBe(0);
|
||||
expect(itemB.getRank()).toBe(0);
|
||||
expect(itemD.getRank()).toBe(0);
|
||||
|
||||
expect(itemA.getChildren().length).toBe(1);
|
||||
expect(itemC.getChildren().length).toBe(1);
|
||||
@@ -50,9 +50,9 @@ describe('DisjointSetItem', () => {
|
||||
expect(itemC.isRoot()).toBeFalsy();
|
||||
expect(itemD.isRoot()).toBeFalsy();
|
||||
|
||||
expect(itemA.getAncestorsCount()).toEqual(3);
|
||||
expect(itemB.getAncestorsCount()).toEqual(0);
|
||||
expect(itemC.getAncestorsCount()).toEqual(1);
|
||||
expect(itemA.getRank()).toEqual(3);
|
||||
expect(itemB.getRank()).toEqual(0);
|
||||
expect(itemC.getRank()).toEqual(1);
|
||||
});
|
||||
|
||||
it('should do basic manipulation with disjoint set item with custom key extractor', () => {
|
||||
@@ -65,7 +65,7 @@ describe('DisjointSetItem', () => {
|
||||
const itemC = new DisjointSetItem({ key: 'C', value: 3 }, keyExtractor);
|
||||
const itemD = new DisjointSetItem({ key: 'D', value: 4 }, keyExtractor);
|
||||
|
||||
expect(itemA.getAncestorsCount()).toBe(0);
|
||||
expect(itemA.getRank()).toBe(0);
|
||||
expect(itemA.getChildren()).toEqual([]);
|
||||
expect(itemA.getKey()).toBe('A');
|
||||
expect(itemA.getRoot()).toEqual(itemA);
|
||||
@@ -75,11 +75,11 @@ describe('DisjointSetItem', () => {
|
||||
itemA.addChild(itemB);
|
||||
itemD.setParent(itemC);
|
||||
|
||||
expect(itemA.getAncestorsCount()).toBe(1);
|
||||
expect(itemC.getAncestorsCount()).toBe(1);
|
||||
expect(itemA.getRank()).toBe(1);
|
||||
expect(itemC.getRank()).toBe(1);
|
||||
|
||||
expect(itemB.getAncestorsCount()).toBe(0);
|
||||
expect(itemD.getAncestorsCount()).toBe(0);
|
||||
expect(itemB.getRank()).toBe(0);
|
||||
expect(itemD.getRank()).toBe(0);
|
||||
|
||||
expect(itemA.getChildren().length).toBe(1);
|
||||
expect(itemC.getChildren().length).toBe(1);
|
||||
@@ -108,8 +108,8 @@ describe('DisjointSetItem', () => {
|
||||
expect(itemC.isRoot()).toBeFalsy();
|
||||
expect(itemD.isRoot()).toBeFalsy();
|
||||
|
||||
expect(itemA.getAncestorsCount()).toEqual(3);
|
||||
expect(itemB.getAncestorsCount()).toEqual(0);
|
||||
expect(itemC.getAncestorsCount()).toEqual(1);
|
||||
expect(itemA.getRank()).toEqual(3);
|
||||
expect(itemB.getRank()).toEqual(0);
|
||||
expect(itemC.getRank()).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user