由于上一次的graph adt结构没有 主索引表allArc,allNode 和 VNode 结构内的inArc,outArc 的相互索引能力,效率比较低.
这一次专门细化了基本结构(VNode,VArc)的元操作,不导致任何功能上的冲突.
写代码期间居然有心情写注释,说明写库如果先自上而下的设计,再自下而上的实现,还是能够增加设计级效率.


0  为了实现相互索引的优化能力,图结构的每一个node和arc都有key和tag两种索引标记,key是面向graph的使用者设计的,tag是面向内在结构设计的,这样,同时让使用者用自由值索引,又保持内在的高效索引.

1 只加了两处测试代码,其他测试代码之后加上去(主要是要考虑使用者会不会进行意想不到的图操作).

2 对于结点数等计数信息直接用引用变量锁定vector的对象,这样,整个代码里面找不到任何关于长度的计数信息(如++,--),完全和vector的n值(长度)同步.

 

 

/*  graph.h :base::adt::graph */

#ifndef GRAPH__

#define GRAPH__

#include 
"base.h"
#include 
"vector.h"


namespace adt
{
    
using adt::vector;
    template
<typename VTypeN,typename VTypeE>
    
class graph : public base::adt
    
{
    
public:
        
struct VArc;
        
struct VNode;
        
struct VArc
        
{
            VNode
* begin;
            VNode
* end;

            
int *tag_begin;
            
int *tag_end;
            VTypeE weight;

            
int tag;/*internal index tag*/
            
int key;/*external index tag*/

            VArc()
            
{
                tag
=0;
                key
=0;
            }

            VArc(VNode 
*_begin,VNode * _end,int _key,int _tag,VTypeE _w)
            
{
                begin
=_begin;
                end
=_end;
                weight
=_w;
                tag
=_tag;
                key
=_key;
                tag_begin
=&begin->tag;
                tag_end
=&end->tag;
            }

            
~VArc()
            
{
                begin
=0;
                end
=0;
                tag
=0;
                key
=0;
            }

            
/*copy to _arc only by data not adr*/
            
void copyTo(VArc * _arc)
            
{
                _arc
->weight=weight;
                _arc
->tag=tag;
                _arc
->key=key;
            }

            
void setKey(int _key)
            
{
                key
=_key;
            }

            
void setTag(int _tag)
            
{
                tag
=_tag;
            }

            
void setWeight(VTypeE _w)
            
{
                weight
=_w;
            }

            
void setBegin(VNode* _begin)
            
{
                begin
=_begin;
                tag_begin
=&begin->tag;
                
            }

            
void setEnd(VNode* _end)
            
{
                end
=_end;
                tag_end
=&end->tag;
            }

        }
;
        
struct VNode
        
{
            vector
<VArc*> inArc;
            vector
<VArc*> outArc;
            
int &inNum;
            
int &outNum;

            VTypeN weight;

            
int tag;/*internal index tag*/
            
int key;/*external index tag*/

            
int status;/*node status*/

            
/*copy to _arc only by data not adr*/
            
void copyTo(VNode * _node)
            
{
                _node
->weight=weight;
                _node
->tag=tag;
                _node
->key=key;
                _node
->status=status;

            }

            VNode():
/*build up ref*/inNum(inArc.n),outNum(outArc.n)
            
{
                status
=0;
                tag
=0;
                key
=0;
            }

            VNode(
int _key,int _tag,VTypeN _w,int _status):/*build up ref*/inNum(inArc.n),outNum(outArc.n)
            
{
                weight
=_w;
                status
=_status;
                tag
=_tag;
                key
=_key;
            }

            
~VNode()
            
{
                tag
=0;
                key
=0;
                status
=0;
            }

            
/*  set key  */
            
void setKey(int _key)
            
{
                key
=_key;
            }

            
/*  set tag */
            
void setTag(int _tag)
            
{
                tag
=_tag;
            }

            
/*  set weight */
            
int setWeight(VTypeN _w)
            
{
                weight
=_w;
                
return 1;
            }

            
/*  set status */
            
void setStatus(int _status)
            
{
                status
=_status;
            }


            
/* add inArc */
            
int addIn(VArc *_inArc )
            
{
                
if(!_inArc)
                    
return 0;
                inArc.push(_inArc);
                
//++inNum;
                return 1;
            }

            
/* and outArc */
            
int addOut(VArc *_outArc )
            
{
                
if(!_outArc)
                    
return 0;
                outArc.push(_outArc);
                
//++outNum;
                return 1;
            }


            
/* remove inArc by weight */
            
int removeInWeight(VTypeE _w)
            
{
                
for(int i=0;i!=inArc_.n;i++)
                
{
                    
if(inArc[i]->weight==_w)
                    
{
                        inArc.remove(i);
                        
//--inNum;
                        --i;
                    }

                }

                
return 1;
            }

            
/* remove outArc by weight */
            
int removeOutWeight(VTypeE _w)
            
{
                
for(int i=0;i!=outArc_.n;i++)
                
{
                    
if(outArc[i]->weight==_w)
                    
{
                        outArc.remove(i);
                        
//--outNum;
                        --i;
                    }

                }

                
return 1;
            }

            
/* remove inArc by tag */
            
int removeInTag(int _tag)
            
{
                
for(int i=0;i!=inArc.n;i++)
                
{
                    
if(inArc[i]->tag==_tag)
                    
{
                        inArc.remove(i);
                        
//--inNum;
                        return 1;
                    }

                }

                
return 0;
            }

            
/* remove outArc by tag */
            
int removeOutTag(int _tag)
            
{
                
for(int i=0;i!=outArc.n;i++)
                
{
                    
if(outArc[i]->tag==_tag)
                    
{
                        outArc.remove(i);
                        
//--outNum;
                        return 1;
                    }

                }

                
return 0;
            }

            
/* remove inArc by key */
            
int removeInKey(int _key)
            
{
                
for(int i=0;i!=inArc_.n;i++)
                
{
                    
if(inArc[i]->key==_key)
                    
{
                        inArc.remove(i);
                        
//--inNum;
                        return 1;
                    }

                }

                
return 0;
            }

            
/* remove outArc by key */
            
int removeOutKey(int _key)
            
{
                
for(int i=0;i!=outArc_.n;i++)
                
{
                    
if(outArc[i]->key==_key)
                    
{
                        outArc.remove(i);
                        
//--outNum;
                        return 1;
                    }

                }

                
return 0;
            }

            
/* search inArc by weight */
            VArc
* findInWeight(VTypeE _w)
            
{
                
for(int i=0;i!=inArc_.n;i++)
                
{
                    
if(inArc[i]->weight==_w)
                    
{
                        
return inArc_[i];
                    }

                }

                
return 0;

            }

            
/* search outArc by weight */
            VArc
* findOutWeight(VTypeE _w)
            
{
                
for(int i=0;i!=outArc.n;i++)
                
{
                    
if(outArc[i]->weight==_w)
                    
{
                        
return outArc[i];
                    }

                }

                
return 0;

            }

            
/* search inArc by tag */
            VArc
* findInTag(int _t)
            
{
                
for(int i=0;i!=inArc.n;i++)
                
{
                    
if(inArc[i]->tag==_t)
                    
{
                        
return inArc[i];
                    }

                }

                
return 0;

            }

            
/* search outArc by tag */
            VArc
* findOutTag(int _t)
            
{
                
for(int i=0;i!=outArc_.n;i++)
                
{
                    
if(outArc[i]->tag==_t)
                    
{
                        
return outArc_[i];
                    }

                }

                
return 0;

            }

            
/* search inArc by key */
            VArc
* findInKey(int _key)
            
{
                
for(int i=0;i!=inArc_.n;i++)
                
{
                    
if(inArc[i]->key==_key)
                    
{
                        
return inArc_[i];
                    }

                }

                
return 0;

            }

            
/* search outArc by key */
            VArc
* findOutKey(int _key)
            
{
                
for(int i=0;i!=outArc_.n;i++)
                
{
                    
if(outArc[i]->key==_key)
                    
{
                        
return outArc_[i];
                    }

                }

                
return 0;

            }

        }
;
        vector
<VNode*> allNode;
        vector
<VArc*>  allArc;
        
int& nodeNum;
        
int& arcNum; 
        graph():
/*build up ref*/nodeNum(allNode.n),arcNum(allArc.n)
        
{

        }

        graph(graph 
& obj):/*build up ref*/nodeNum(allNode.n),arcNum(allArc.n)
        
{
            obj.copyTo(
*this);
        }

        
int addNode(int _key,VTypeN _w,int _status)
        
{
            

            
if(findNodeTag(_key)!=-1)
            
{
                
#ifdef TEST_OPEN
                TEST_THROW(
"Exception in graph.h graph::addNode Function.")
#endif
                
return 0;

            }


            VNode
* _node=new VNode;
            
/*init data*/
            _node
->setKey(_key);
            _node
->setWeight(_w);
            _node
->setStatus(_status);
            _node
->setTag(nodeNum);/*index reciprocally beginning with 0 */
            
/*push in index list*/
            allNode.push(_node);
            
return 1;
        }

        
int setNode(int _key,VTypeN _w,int _status)
        
{
            
int _tag;

            
if((_tag=findNodeTag(_key))==-1)
            
{
                
#ifdef TEST_OPEN
                TEST_THROW(
"Exception in graph.h graph::setNode Function.")
#endif
                
return 0;

            }


            VNode
* _node=allNode[_tag];
            
/*init data*/
            _node
->setWeight(_w);
            _node
->setStatus(_status);
            
return 1;
        }

        
/* switch key to tag */
        
int findNodeTag(int _key)
        
{
            
for(int i=0;i!=allNode.n;i++)
            
{
                
if(allNode[i]->key==_key)
                
{
                    
return allNode[i]->tag;
                }

            }

            
return -1;
        }

        
/* switch key to tag */
        
int findArcTag(int _key)
        
{
            
for(int i=0;i!=allArc.n;i++)
            
{
                
if(allArc[i]->key==_key)
                
{
                    
return allArc[i]->tag;
                }

            }

            
return -1;
        }

        
/* find node by key */
        
int findNode(int _key)
        
{
            
for(int i=0;i!=allNode.n;i++)
            
{
                
if(allNode[i]->key==_key)
                
{
                    
return 1;
                }

            }

            
return 0;
        }

        
/* find arc by key */
        
int findArc(int _key)
        
{
            
for(int i=0;i!=allArc.n;i++)
            
{
                
if(allArc[i]->key==_key)
                
{
                    
return 1;
                }

            }

            
return 0;
        }

        
int isGo(int _key,VTypeE _w,int &_next_key)
        
{
            
int _tag = findNodeTag(_key);

            
if(_tag>=nodeNum||_tag==-1)
            
{
#ifdef TEST_OPEN
                TEST_THROW(
"Exception in graph.h graph::isGo function.")
#endif
                
return 0;
            }

                

            VNode 
* _node = allNode[_tag];
            VArc
* _arc = _node->findOutWeight(_w);
            
if(!_arc)
                
return 0;
            _next_key 
= _arc->end->key;
            
return 1;
        }

        
int getStatus(int _key)
        
{
            
int _tag = findNodeTag(_key);

            
return allNode[_tag]->status;
        }

        
/* add arc by begin and end 's key */
        
void addArc(int _k_begin,int _k_end,int _key,VTypeE _w)
        
{
            
if(findArcTag(_key)!=-1)
            
{
                
#ifdef TEST_OPEN
                TEST_THROW(
"Exception in graph.h graph::addArc function.")
#endif
                
return;

            }

            VArc
* _arc=new VArc;
            
/* switch key to tag,get begin's and end's adr*/
            
int _tag_begin = findNodeTag(_k_begin);
            
int _tag_end   = findNodeTag(_k_end);
            VNode
* _begin=allNode[_tag_begin];
            VNode
* _end  =allNode[_tag_end];
            
/*init data*/
            _arc
->setBegin(_begin);
            _arc
->setEnd(_end);
            _arc
->setKey(_key);
            _arc
->setWeight(_w);
            
/*index reciprocally beginning with zero */
            _arc
->setTag(arcNum);
            
/*building begin-end link.*/
            _begin
->addOut(_arc);
            _end
->addIn(_arc);
            
/*push in index list*/
            allArc.push(_arc);

        }

        
int setArc(int _key,VTypeE _w)
        
{
            
int _tag;
            
if((_tag=findArcTag(_key))==-1)
            
{
                
#ifdef TEST_OPEN
                TEST_THROW(
"Exception in graph.h graph::setArc function.")
#endif
                
return 0;

            }

            VArc
* _arc=allArc[_tag];
    
            VNode
* _begin=allNode[_arc->begin->tag];
            VNode
* _end  =allNode[_arc->end->tag];
            
/*init data*/
            _arc
->setBegin(_begin);
            _arc
->setEnd(_end);
            _arc
->setWeight(_w);

        }

        
/* copy self to graph-obj */
        
int copyTo(graph & _obj)
        
{
            VNode 
*_node;
            VArc 
*_arc;
            
            
for(int i=0;i!=nodeNum;i++)
            
{
                _node
=allNode[i];
                _obj.allNode.push(
new VNode(_node->key,_node->tag,_node->weight,_node->status));

            }

            
for(int i=0;i!=arcNum;i++)
            
{
                _arc
=allArc[i];
                _obj.addArc(_arc
->begin->key,_arc->end->key,_arc->key,_arc->weight);
            }

            
return 1;
        }

        
int copyFrom(graph & _obj)
        
{
            _obj.copyTo(
*this);
            
return 1;
        }

        
/* get value from rightObj */
        
void operator = (graph& _rObj)
        
{
            copyFrom(_rObj);
        }

        
/* remove arc by tag */
        
int removeArcTag(int _tag)
        
{

            VArc
* _arc=allArc[_tag];
            _arc
->begin->removeOutTag(_tag);
            _arc
->end->removeInTag(_tag);
            allArc.remove(_tag);
            
for(int i=_tag;i!=arcNum;i++)
                
--allArc[i]->tag;

            
return 1;
        }

        
/* remove arc by key */
        
int removeArcKey(int _key)
        
{
            VArc
* _arc;

            
/* search by key */

            
for(int i=0;i!=arcNum;i++)
            
{
                
if(allArc[i]->key==_key)
                
{
                    _arc
=allArc[i];
                    removeArcTag(_arc
->tag);
                    
return 1;
                }

            }


            
return 0;
        }

        
/* remove node by tag*/
        
int removeNodeTag(int _tag)
        
{
            
            VNode
* _node=allNode[_tag];
            
            
/* remove all inArc */
            
for(;0!=_node->inNum;)
            
{
                            
                removeArcTag(_node
->inArc[0]->tag);
                
//_node->inArc.remove(0);
            }

            
/* remove all outArc */
            
for(;0!=_node->outNum;)
            
{
                
                removeArcTag(_node
->outArc[0]->tag);
                
//cout<<_node->outNum;
                
//_node->outArc.remove(0);
            }

            
/* remove itself*/
            allNode.remove(_tag);
            
for(int i=_tag;i!=arcNum;i++)
                
--allArc[i]->tag;
            
return 1;
        }

        
/* remove node by key*/
        
int removeNodeKey(int _key)
        
{

            VNode
* _node;
            
/* search by key */
            
            
for(int i=0;i!=nodeNum;i++)
            
{
                
if(allNode[i]->key==_key)
                
{
                    _node
=allNode[i];
                    
                    removeNodeTag(_node
->tag);
                    
return 1;
                }

            }

            
            
return 0;
        }

        
int free()
        
{


            
for(;0!=nodeNum;)
            
{
                delete allNode.pop();

            }

            
for(;0!=arcNum;)
            
{
                
                delete allArc.pop();
            }


            
return 1;
        }

        
~graph()
        
{
            
            free();
            
        }


    }
;
}
;





#endif

 

 



关于匹配的一个case:

主要测试增加删除结点并且测试key,weight是否对应功能,会否出现崩溃.

不过还好目前没有任何输入会引起崩溃.

多次变化增加删除结点.

实现了对一个dfa  的匹配,一开始能匹配/(at|ro)(om)/,当第一次匹配成功后继续匹配时删除一条'o'边,导致r到m的边无法达到,匹配自动变成/atom/.

当第二次匹配成功(对 /atom/ 的匹配),增加回原来的'o'边,使匹配自动回到/(at|ro)(om)/,直到输入流都匹配为结束


 

 

void test_graph()
{

    
using adt::graph;

    graph
<int,char> g,g2;

    g.addNode(
1,1,-1);
    g.addNode(
2,1,0);
    g.addNode(
3,1,0);
    g.addNode(
4,1,0);
    g.addNode(
5,1,0);
    g.addNode(
6,1,1);


    g.addArc(
1,2,1,'a');
    g.addArc(
2,4,2,'t');
    g.addArc(
4,5,3,'o');
    g.addArc(
5,6,4,'m');
    g.addArc(
1,3,5,'r');
    g.addArc(
3,4,6,'o');

    g2
=g;




    
char buf[200]={0},get;
    
int init=1,key=init,tag,_i=0,len,select=0;
    os::control reader;
    
    
do
    
{
    reader.read(buf,len);
    }
while(reader.size(buf)==0);
    
while(1){
        
char list[100]={0};
        
int i=0;
        key
=init;
        
while(1)
        
{
            
if(g2.getStatus(key)==1)
            
{
                
break;
            }

            
if(_i==len)
                
break;
            
if(g2.isGo(key,buf[_i],key))
            
{
                
if(i==0)
                    tag
=_i+1;
                list[i]
=buf[_i];
                
++i;
                
++_i;
            }
else
            
{
                
                
if(i!=0)
                
{
                    _i
=tag;
                    i
=0;
                    key
=init;
                }
else
                
{
                    i
=0;
                    key
=init;
                    
++_i;
                }



            }



        }

        
if(g2.getStatus(key)==1)
        
{
            
if(select==0)
            
{
                g2.removeArcKey(
6);
                cout
<<"your input(\""<<list<<"\") matches the dfa(regex:/(at|ro)(om)/)."<<endl;
                cout
<<"the dfa switch to another dfa(regex:/atom/)"<<endl;
                
            }
else if(select==1)
            
{
                g2.addArc(
3,4,6,'o');
                cout
<<"your input(\""<<list<<"\") matches the dfa(regex:/atom/)."<<endl;
                cout
<<"the dfa switch to another dfa(regex:/(at|ro)(om)/)"<<endl;
                
            }

            select 
= (select+1)%2;
        }

        cout
<<_i<<":"<<len<<endl;
        
if(_i==len)break;
        getch();
    }


}

 


 

Input:

your atom 
is in my room,atomic things..room



 

Output:

your input(
"atom") matches the dfa(regex:/(at|ro)(om)/).
the dfa 
switch to another dfa(regex:/atom/)
9:50
your input(
"atom") matches the dfa(regex:/atom/).
the dfa 
switch to another dfa(regex:/(at|ro)(om)/)
28:50
your input(
"room") matches the dfa(regex:/(at|ro)(om)/).
the dfa 
switch to another dfa(regex:/atom/)
46:50
50:50
请按任意键继续. . .