|
|
/**
* @file minimun_spanning_tree.cpp */
/*
* This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2011 Jean-Pierre Charras * Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors. * * derived from this article: * http://compprog.wordpress.com/2007/11/09/minimal-spanning-trees-prims-algorithm
* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, you may find one here: * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
#include <limits.h>
#include <minimun_spanning_tree.h>
#include <class_pad.h>
/*
* The class MIN_SPAN_TREE calculates the rectilinear minimum spanning tree * of a set of points (pads usually having the same net) * using the Prim's algorithm. */
/*
* Prim's Algorithm * Step 0 * Pick any vertex as a starting vertex. (Call it S). * Mark it with any given flag, say 1. * * Step 1 * Find the nearest neighbour of S (call it P1). * Mark both P1 and the edge SP1. * cheapest unmarked edge in the graph that doesn't close a marked circuit. * Mark this edge. * * Step 2 * Find the nearest unmarked neighbour to the marked subgraph * (i.e., the closest vertex to any marked vertex). * Mark it and the edge connecting the vertex. * * Step 3 * Repeat Step 2 until all vertices are marked. * The marked subgraph is a minimum spanning tree. */MIN_SPAN_TREE::MIN_SPAN_TREE(){ MSP_Init( 0 );}
void MIN_SPAN_TREE::MSP_Init( int aNodesCount ){ m_Size = aNodesCount; inTree.clear(); linkedTo.clear(); distTo.clear();
if( m_Size == 0 ) return;
// Reserve space in memory
inTree.reserve( m_Size ); linkedTo.reserve( m_Size ); distTo.reserve( m_Size );
// Initialize values:
for( int ii = 0; ii < m_Size; ii++ ) { // Initialise dist with infinity:
distTo.push_back( INT_MAX );
// Mark all nodes as NOT beeing in the minimum spanning tree:
inTree.push_back( 0 );
linkedTo.push_back( 0 ); }}
/* updateDistances(int target)
* should be called immediately after target is added to the tree; * updates dist so that the values are correct (goes through target's * neighbours making sure that the distances between them and the tree * are indeed minimum) */void MIN_SPAN_TREE::updateDistances( int target ){ for( int ii = 0; ii < m_Size; ++ii ) { if( !inTree[ii] ) // no need to evaluate weight for already in tree items
{ int weight = GetWeight( target, ii ); if( (weight > 0) && (distTo[ii] > weight ) ) { distTo[ii] = weight; linkedTo[ii] = target; } } }}
void MIN_SPAN_TREE::BuildTree(){ /* Add the first node to the tree */ inTree[0] = 1; updateDistances( 0 );
for( int treeSize = 1; treeSize < m_Size; ++treeSize ) { // Find the node with the smallest distance to the tree
int min = -1; for( int ii = 0; ii < m_Size; ++ii ) { if( !inTree[ii] ) { if( (min == -1) || (distTo[min] > distTo[ii]) ) min = ii; } }
inTree[min] = 1; updateDistances( min ); }}
|