int bNNI( double[][] avgDistArray, int count )
	{
		edge e;
		edge[] edgeArray;
		heap p, q;
		direction[] location;
		int i;
		int possibleSwaps;
		double[] weights;
		//FILE *mfile;
		p = new heap(size+1);
		q = new heap(size+1);
		edgeArray = new edge[size+1];
		weights = new double[size+1];
		location = new direction[size+1];
		for (i=0;i<size+1;i++)
	    {
			weights[i] = 0.0;
			location[i] = direction.NONE;
	    }
		e = root.leftEdge.findBottomLeft(); 
		while ( null != e )
	    {
	      	edgeArray[e.head.index+1] = e;
	      	location[e.head.index+1] = 
	      		bNNIEdgeTest( e, avgDistArray, weights, e.head.index + 1 );
	      	e = depthFirstTraverse(e);
	    } 
		possibleSwaps = p.makeThreshHeap( q,weights,size+1,0.0 );
		p.permInverse( q,size+1 );
		// we put the negative values of weights into a heap, indexed by p
	    // with the minimum value pointed to by p[1]
		// p[i] is index (in edgeArray) of edge with i-th position 
	    // in the heap, q[j] is the position of edge j in the heap 
		while ( weights[p.p[1]] < 0 )
	    {
			//centerEdge = edgeArray[p.p[1]];
			count++;
			bNNItopSwitch(edgeArray[p.p[1]],location[p.p[1]],avgDistArray);
			location[p.p[1]] = direction.NONE;
			//after the bNNI, this edge is in optimal configuration
			weights[p.p[1]] = 0.0;  
			p.popHeap(q,weights,possibleSwaps--,1);
			// but we must retest the other edges of T
	      	// CHANGE 2/28/2003 expanding retesting to _all_ edges of T
			e = depthFirstTraverse(null);
			while (null != e)
			{
				possibleSwaps = bNNIRetestEdge(p,q,e,avgDistArray,weights,
					location,possibleSwaps);
				e = depthFirstTraverse(e);
			}
	    }
		assignBalWeights(avgDistArray);
		return count;
	}