Add disjoint set.

This commit is contained in:
Oleksii Trekhleb
2018-05-04 06:18:05 +03:00
parent 2e76caa9d6
commit 843893e8e7
3 changed files with 28 additions and 22 deletions

View File

@@ -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);

View File

@@ -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;
}
/**

View File

@@ -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);
});
});