QuickUnion.ixx

Quick-union (lazy approach)

Download source code for Visual Studio 2022 from Github
QuickUnionTest.ixx
#include "pch.h"
#include <iostream>
#include <crtdbg.h>
#include <span>
#include<tuple>


import unionfind;
import nodes;
import utilitytest;
import unionfindtest;



class QuickUnionTest : public ::testing::Test {
protected:
	std::unique_ptr<UnionFind> m_unionFind;
	OneBasedArray oneBasedArray;
	ZeroBasedArray zeroBasedArray;
	
public:


	virtual void SetUp() override
	{
		int size = 8;
		m_unionFind = std::make_unique <QuickUnion>(size, oneBasedArray);
		m_unionFind->initialize();

	}



	virtual void TearDown() override
	{

	}

};




TEST_F(QuickUnionTest, testUnion3and7)
{
	MemoryLeakDetector leakDetector;
	m_unionFind->union_nodes(3, 7);
	int expected[] = { 1, 2, 7, 4, 5, 6, 7, 8 };
	const std::vector<int>& values = m_unionFind->getAllValues();
	assert_that(values, expected);

}


TEST_F(QuickUnionTest, testMultipleUnion)
{
	MemoryLeakDetector leakDetector;
	unionlistOfNodes(m_unionFind.get(), {{3,7},{2,5},{2,3},{3,6},{1,4},{8,1},{4,7}});
	int expected[] = { 4, 5, 7, 6, 7, 6, 6, 4 };
	const std::vector<int>& values = m_unionFind->getAllValues();
	assert_that(values, expected);

}



TEST_F(QuickUnionTest, testMultipleUnion_pathCompressionWith2Nodes)
{
	MemoryLeakDetector leakDetector;
	std::unique_ptr<QuickUnion> quickUnion;
	constexpr int size = 2;
	ZeroBasedArray zeroBasedArray;
	quickUnion = std::make_unique <QuickUnion>(size, zeroBasedArray);

	quickUnion->setRootpathCompressionWithSinglePass;

	std::vector<int> values = { 0, 1 };

	quickUnion->setAllValuesmove(values);

	quickUnion->union_nodes(0, 1);

	int expected[size] = { 1, 1 };
	const std::vector<int>& newValues = quickUnion->getAllValues();
	printAll(newValues);
	assert_that(newValues, expected);

}


QuickUnion.ixx
#include "pch.h"
#include <functional>

export  module unionfind:quickunion;

import :uf;
import nodes;


using rootFunction = std::function<int(Nodes &, int)>;


export class QuickUnion : public UnionFind {
	
	rootFunction root_fn;

public:
	
	class RootFunctions {
	public:
		static int root(Nodes& nodes, int a)
		{
			for (; nodes[a] != a; a = nodes[a]);
			return a;
		}

		static int pathCompressionWithSinglePass(Nodes& nodes, int a)
		{
			for (; nodes[a] != a; nodes[a] = nodes[nodes[a]], a = nodes[a]);
			return a;
		}

		static int pathCompressionWithDoublePass(Nodes& nodes, int a)
		{
			int r = root(nodes, a);
			while ( r != a)
			{
				int parent = nodes[a];
				nodes[a] = r;
				a = parent;
			}
			return a;
		}


	};
	
	
	virtual ~QuickUnion() = default;

	QuickUnion(const int size, ArrayType& arrayType) :UnionFind(size, arrayType)
	{
		root_fn = RootFunctions::root;
	}

	virtual int getValue(const int index)
	{
		return m_nodes[index];
	}

	void setRoot(rootFunction rf)
	{
		root_fn = rf;
	}

	virtual int root(  int a)
	{
		return root_fn(m_nodes, a);
	}


	virtual void union_nodes(
		const int a, 
		const int b
		)
	{
		const int i = root( a );
		const int j = root( b );
		m_nodes.set(m_nodes.get(i), j);
	}

	virtual int depth(int a)
	{
		int depthOfNode = 1;
		for ( ; m_nodes[a] != a; a = m_nodes[a], depthOfNode++ );
		return depthOfNode;
	}

	virtual int maxDepth()
	{
		int depthestNode;
		for (int i = m_nodes.firstIndex(); i <= m_nodes.lastIndex(); i++)
			depthestNode = std::max( depthestNode, depth(i) );

		return depthestNode;
	}

};