构建一个图并使用graphconncomp
G = sparse( A(:,1), A(:,2), 1, max(A(:)), max(A(:)) );
G = G + G.';
[S C] = graphconncomp( G );
如果您没有生物信息学工具箱
我在mex中实现的graphconncomp
:
graph_conn_comp.m
代码:
function [l c] = graph_conn_comp(sA)
sA = spfun(@(x) ones(size(x)),sA);
if ~isequal(sA, sA')
[ii jj] = find(sA);
sA = sparse([ii jj],[jj ii], ones(1, 2*numel(ii)), size(sA,1), size(sA,2));
end
[l c] = graph_conn_comp_mex(sA);
l = double(l);
使用Matlab编译graph_conn_comp_mex.cpp
的代码。
>> mex -largeArrayDims -O graph_conn_comp_mex.cpp
#include "mex.h"
#include <string.h>
#line __LINE__ "graph_conn_comp_mex"
#define STR(s) #s
#define ERR_CODE(a,b) a ":" "line_" STR(b)
enum {
AIN = 0,
NIN };
enum {
LOUT = 0,
COUT,
NOUT };
void
ConnComp(const mxArray* sA, unsigned int* pl, const double* pnc, mwIndex start_node);
mwIndex
FindUnLabeled(unsigned int* pl, mwIndex n);
void mexFunction(
int nout,
mxArray* pout[],
int nin,
const mxArray* pin[]) {
if ( nin != NIN )
mexErrMsgIdAndTxt(ERR_CODE(__FILE__, __LINE__),"must have %d inputs", NIN);
if (nout==0)
return;
if (nout != NOUT )
mexErrMsgIdAndTxt(ERR_CODE(__FILE__, __LINE__),"must have exactly %d output", NOUT);
if ( mxIsComplex(pin[AIN]) || !mxIsSparse(pin[AIN]) )
mexErrMsgIdAndTxt(ERR_CODE(__FILE__, __LINE__),"sA must be real sparse matrix");
if ( mxGetM(pin[AIN]) != mxGetN(pin[AIN]) )
mexErrMsgIdAndTxt(ERR_CODE(__FILE__, __LINE__),"sA must be square matrix");
mwIndex n = mxGetM(pin[AIN]);
mwIndex ii(0);
pout[LOUT] = mxCreateNumericMatrix(1, n, mxUINT32_CLASS, mxREAL);
unsigned int* pl = (unsigned int*)mxGetData(pout[LOUT]);
memset(pl, 0, n*sizeof(unsigned int));
unsigned int cl = 0;
pout[COUT] = mxCreateDoubleMatrix(1, 1, mxREAL);
double* pnc = mxGetPr(pout[COUT]);
pnc[0] = 0;
ii = 0;
do {
ConnComp(pin[AIN], pl, pnc, ii);
pnc[0]++;
ii = FindUnLabeled(pl, n);
} while ( ii < n );
}
mwIndex
FindUnLabeled(unsigned int* pl, mwIndex n) {
for ( mwIndex ii(0); ii<n ; ii++ ){
if ( pl[ii]==0 ) {
return ii;
}
}
return n+1;
}
void
ConnComp(const mxArray* sA, unsigned int* pl, const double* pnc, mwIndex start_node) {
mwIndex n = mxGetM(sA);
unsigned int curr_label = (unsigned int)(pnc[0]+1);
mwIndex *stack = (mwIndex*)mxMalloc( (n)*sizeof(mwIndex) );
memset(stack, 0, (n)*sizeof(mwIndex));
mwIndex sp(0);
pl[start_node]=curr_label;
stack[sp] = start_node;
sp++;
mwIndex* pir = mxGetIr(sA);
mwIndex* pjc = mxGetJc(sA);
mwIndex ii(0), neighbor(0);
while ( sp > 0 ) {
sp--;
start_node = stack[sp];
for ( ii = pjc[start_node] ; ii < pjc[start_node+1] ; ii++ ) {
neighbor = pir[ii];
if (pl[neighbor]==0) {
pl[neighbor] = curr_label;
stack[sp] = neighbor;
sp++;
} else {
if (pl[neighbor]!=curr_label)
mexErrMsgIdAndTxt(ERR_CODE(__FILE__, __LINE__),"Got mixed labeling %d <-> %d",pl[neighbor], curr_label);
}
}
}
mxFree(stack);
}