1f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 2f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Licensed under the Apache License, Version 2.0 (the "License"); 3f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// you may not use this file except in compliance with the License. 4f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// You may obtain a copy of the License at 5f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 6f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// http://www.apache.org/licenses/LICENSE-2.0 7f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 8f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Unless required by applicable law or agreed to in writing, software 9f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// distributed under the License is distributed on an "AS IS" BASIS, 10f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// See the License for the specific language governing permissions and 12f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// limitations under the License. 13f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 14f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Copyright 2005-2010 Google, Inc. 15f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Author: wojciech@google.com (Wojciech Skut) 16f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 17f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// \file Union-Find algorithm for dense sets of non-negative 18f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// integers. Implemented using disjoint tree forests with rank 19f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// heuristics and path compression. 20f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 21f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#ifndef __fst_union_find_inl_h__ 22f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#define __fst_union_find_inl_h__ 23f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 24f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <stack> 25f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <vector> 26f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonusing std::vector; 27f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/types.h> 28f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 29f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonnamespace fst { 30f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 31f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Union-Find algorithm for dense sets of non-negative integers 32f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// (exact type: T). 33f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class T> 34f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass UnionFind { 35f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public: 36f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Ctor: creates a disjoint set forest for the range [0;max). 37f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // 'fail' is a value indicating that an element hasn't been 38f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // initialized using MakeSet(...). The upper bound of the range 39f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // can be reset (increased) using MakeSet(...). 40f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson UnionFind(T max, T fail) 41f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson : parent_(max, fail), rank_(max), fail_(fail) { } 42f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 43f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Finds the representative of the set 'item' belongs to. 44f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Performs path compression if needed. 45f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson T FindSet(T item) { 46f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (item >= parent_.size() 47f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson || item == fail_ 48f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson || parent_[item] == fail_) return fail_; 49f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 50f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson T *p = &parent_[item]; 51f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson for (; *p != item; item = *p, p = &parent_[item]) { 52f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson exec_stack_.push(p); 53f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 54f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson for (; ! exec_stack_.empty(); exec_stack_.pop()) { 55f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson *exec_stack_.top() = *p; 56f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 57f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return *p; 58f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 59f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 60f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Creates the (destructive) union of the sets x and y belong to. 61f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void Union(T x, T y) { 62f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson Link(FindSet(x), FindSet(y)); 63f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 64f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 65f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Initialization of an element: creates a singleton set containing 66f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // 'item'. The range [0;max) is reset if item >= max. 67f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson T MakeSet(T item) { 68f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (item >= parent_.size()) { 69f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // New value in parent_ should be initialized to fail_ 70f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson size_t nitem = item > 0 ? 2 * item : 2; 71f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson parent_.resize(nitem, fail_); 72f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson rank_.resize(nitem); 73f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 74f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson parent_[item] = item; 75f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return item; 76f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 77f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 78f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Initialization of all elements starting from 0 to max - 1 to distinct sets 79f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void MakeAllSet(T max) { 80f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson parent_.resize(max); 81f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson for (T item = 0; item < max; ++item) { 82f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson parent_[item] = item; 83f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 84f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 85f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 86f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private: 87f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson vector<T> parent_; // Parent nodes. 88f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson vector<int> rank_; // Rank of an element = min. depth in tree. 89f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson T fail_; // Value indicating lookup failure. 90f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson stack<T*> exec_stack_; // Used for path compression. 91f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 92f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Links trees rooted in 'x' and 'y'. 93f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void Link(T x, T y) { 94f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (x == y) return; 95f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 96f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (rank_[x] > rank_[y]) { 97f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson parent_[y] = x; 98f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } else { 99f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson parent_[x] = y; 100f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (rank_[x] == rank_[y]) { 101f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson ++rank_[y]; 102f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 103f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 104f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 105f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson DISALLOW_COPY_AND_ASSIGN(UnionFind); 106f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}; 107f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 108f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson} // namespace fst 109f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 110f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#endif // __fst_union_find_inl_h__ 111