首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 其他相关 >

根本数据结构(图)

2013-03-17 
基本数据结构(图)。。。#include iostreamusing namespace std//我们这个图的数据结构 认为://1. 图是由很

基本数据结构(图)


。。。


#include <iostream>using namespace std;//我们这个图的数据结构 认为://1. 图是由很多节点(VERTEX)构成的, 因此图结构是由一个VERTEX的链表构成的, 每个VERTEX则需要有一个id,也就是start, 取start是为了跟LINE更直观地结合。//2. 每个节点关联着很多(LINE)构成,因此每个VERTEX由很多LINE构成, LINE不需要id, 但是它有3 要素: (start, end, weight), start不必说,取VERTEX中的即可,因此需要end和weight2种.注意: 每个VERTEX中都有一个LINE链表哦..//3. 因此,图的结构如下所示:/*Graph{    Vertex1{line1->line2->line3}        |    Vertex2{line1->line2->line3}        .        .        .    Vertexn{line1->line2->line3}}*///图的边struct LINE{    int end;//尾端点    int weight;//权重    LINE *next;//所有LINE的链表    LINE(int e, int w){        end = e;        weight = w;        next = 0;        cout<<"LINE:"<<end<<","<<weight<<" created"<<endl;    }};struct VERTEX{    int start;//起始点    int lineNums;//LINE的数量    LINE *first;//与点相关联的边的链表    VERTEX *next;//所有VERTEX的链表    VERTEX(int s){        start = s;        lineNums = 0;        first = 0;        next = 0;        cout<<"Vertex:"<<start<<" created"<<endl;    }    void visit(){        cout<<start<<" ";    }};//最小生成树的Line结构struct MinTreeLine{    int start;    int end;//尾端点    int weight;//权重    MinTreeLine *next;//所有LINE的链表    MinTreeLine(int s, int e, int w){        start = s;        end = e;        weight = w;        next = 0;    }};//最小生成树结构struct MinTree{    int start;     int vn, ln;    int weight;    MinTreeLine*first;    VERTEX* list;    MinTree(int s){        start = s;        vn = 1;        ln = 0;        weight = 0;        first = 0;        list = 0;    }    void insertVertex(int start){        if(list){            VERTEX * tmp = list;            while(tmp->next){                tmp = tmp->next;            }            tmp->next = new VERTEX(start);        }else{            list = new VERTEX(start);        }    }    void deleteVertex(int start){        if(list){            VERTEX* tmp = list;            if(tmp->start == start){                delete tmp;                list = 0;                return;            }else{                while(tmp->next){                    if(tmp->start ==start){                        VERTEX* t = tmp;                        tmp = tmp->next;                        delete t;                    }                }            }        }    }    MinTreeLine* getLast(){        MinTreeLine* l = first;        if(l){            while(l->next){                l = l->next;            }            return l;        }else{            return 0;        }    }    MinTreeLine* getFormer(MinTreeLine* l){        MinTreeLine* line = first;        while(line){            if(line->next && line->next->end == l->end){                break;            }else{                line = line->next;            }        }        return line;    }    void insertLine(MinTreeLine* l){        if(first){            getLast()->next = l;        }else{            first = l;        }        ln++;        vn++;        //cout<<"加入line: "<<l->end<<"####ln=="<<ln<<", vn =="<<vn<<endl;    }    void rmLine(MinTreeLine*l){//不用delete,因为Line是在graph中的。        MinTreeLine * f = getFormer(l);        if(f){            MinTreeLine*d = f->next;            f->next = d->next;            delete d;        }else{            MinTreeLine*d = first;            first = first->next;            delete d;        }    }    ~MinTree(){        while(first){            MinTreeLine* tmp = first;            first = first->next;            rmLine(tmp);        }    }    void print(){        int p = start;        MinTreeLine*l = first;        while(l){            cout<<"["<<l->start<<"]---"<<l->weight<<"---["<<l->end<<"]";            l = l->next;        }        cout<<endl;    }};struct GRAPH{    enum Kind{DG, NG, DN, NN};    Kind kind;    int count;    VERTEX* first;    bool *visitDFSArr;    GRAPH(): count(0), first(0){        kind = DG;        visitDFSArr = 0;    }    GRAPH(Kind k): count(0), first(0){        kind = k;        visitDFSArr = 0;    }    GRAPH(Kind k, int start, int end, int weight){        kind = k;        visitDFSArr = 0;        addVertexWithLine(start, end, weight);    }    ~GRAPH(){        while(first){            VERTEX* v = first;            first = first->next;            deleteVertex(v->start);        }        if(visitDFSArr)            delete visitDFSArr;    }    //建立一条新的Line    LINE* createNewLine(int end, int weight){//建立一个新LINE        return new LINE(end,weight);    }    //建立一个新的Vertex    VERTEX* createNewVertex(int start){//创建新Vertex        return new VERTEX(start);    }    //在图中查找一个Vertex, 如果找到p返回的就是该vertex否则返回最后一个节点。    VERTEX* findVertex(VERTEX** p, int start){//寻找Vertex在graph中        VERTEX* tmp = first;        if(p)*p = 0;        while(tmp){            if(tmp->start == start)                return tmp;            if(p)*p = tmp;            tmp = tmp->next;        }        return 0;    }    //从某一个Vertex的Line表中,查找一个Line, 如果找到, p返回的就是该Line否则返回最后一个Line。    LINE* findLine(LINE**p, LINE*first, int end){        LINE* tmp = first;        if(p) *p = 0;        while(tmp){            if(tmp->end == end)                return tmp;            if(p)*p = tmp;            tmp = tmp->next;        }        return 0;    }    //增加一个Vertex到图中    VERTEX* addVertexToGraph(int start){        VERTEX*f = 0;        if(!findVertex(&f, start)){            if(f){                f->next = createNewVertex(start);                count++;                return f->next;            }else{                first = createNewVertex(start);                count++;                return first;            }        }        return 0;    }    LINE* addLineToVertex(LINE *l, VERTEX*v){//前提:l和v必须都存在.        LINE* vl = v->first;        LINE *p = v->first;        if(!vl){            v->first = l;        }else{            while(vl){                p = vl;                vl = vl->next;            }            p->next = l;        }    }    //增加一条线到Vertex    LINE* addLineToVertex(int start, int end, int weight){        VERTEX *v;        LINE* resLine = 0;        if(findVertex(&v, start)){            LINE* f = 0;            if(v){                v = v->next;            }else{                v = first;            }            if(!findLine(&f, v->first, end)){                if(f){                    f->next = createNewLine(end,weight);                    resLine = f->next;                }else{                    v->first = createNewLine(end,weight);                    resLine = v->first;                }                if(kind == NG){//如果是无向图还需要反向来一次的说,这个不会形成无限递归的.                    addLineToVertex(end, start, weight);                }            }        }        return resLine;    }    //增加一个带有一条Line的节点, 只有带边的点,和孤独的点,却没有孤独的边。因此没有类似的addLine的函数。    void addVertexWithLine(int start, int end, int weight){        if(addVertexToGraph(start)){            if(addLineToVertex(start, end, weight)){                cout<<"addVertexWithLine sucess!"<<endl;            }else{                cout<<"addVertexWithLine error1"<<endl;            }        }else{            cout<<"addVertexWithLine error2!"<<endl;        }    }    //删除一条线,首先,在LINE中的链表中删除,然后在Vertex中删除    void deleteLine(int start, int end){//只有知道边的2个端点才能唯一确定一条边        //首先找到顶点        VERTEX *v;        if(findVertex(&v, start)){            if(v){                v = v->next;            }else{                v = first;            }        }        deleteLine(v, end);    }    //删除一条线,首先,在LINE中的链表中删除,然后在Vertex中删除    void deleteLine(VERTEX*v, int end){//只有知道边的2个端点才能唯一确定一条边        LINE*l;        if(findLine(&l, v->first, end)){            if(l){                delete l->next;                l->next = l->next->next;            }else{                LINE*f =  v->first;                v->first = f->next;                delete f;            }            v->lineNums--;        }    }    void deleteAllLine(VERTEX*v){//只有知道边的2个端点才能唯一确定一条边        LINE*l = v->first;        while(l){            LINE*tmp = l;            l = l->next;            delete tmp;        }        v->first = 0;        v->lineNums = 0;    }    void deleteAllLine(int start){//只有知道边的2个端点才能唯一确定一条边        //首先找到顶点        VERTEX *v;        if(findVertex(&v, start)){            if(v){                v = v->next;            }else{                v = first;            }        }        deleteAllLine(v);    }    void deleteVertex(int start){        VERTEX*v;        if(findVertex(&v, start)){            //首先删除从start点出发的LINE            deleteAllLine(start);            //然后删除节点            VERTEX*tmp = v->next;            v->next = v->next->next;            delete tmp;            count--;            //删除以start为终点的Lines.            VERTEX* f = first;            while(f){                deleteLine(f, start);                f = f->next;            }        }    }    //深度优先遍历。    void DFS(VERTEX*v){        v->visit();        visitDFSArr[v->start] = true;        LINE * l = v->first;        while(l){            VERTEX* pv;            findVertex(&pv, l->end);            if(pv){                pv = pv->next;            }else{                pv = first;            }            if(!visitDFSArr[pv->start]) DFS(pv);            l = l->next;        }    }    void DFSTraversal(){        delete visitDFSArr;        visitDFSArr = new bool[count];//泄漏        for(int i = 0; i < count; i++){            visitDFSArr[i] = false;        }        VERTEX*v = first;        while(v){            if(!visitDFSArr[v->start]) DFS(v);            v = v->next;        }        cout<<endl;    }    //广度优先遍历。广度优先遍历选择一个队列辅助操作还是比较合理的。略    //最小生成树    //prim算法: 条件是加权连通图。找出图的最小生成树。    MinTree getPrimMinTree(int start){        MinTree p(start);        if(visitDFSArr){            delete []visitDFSArr;            visitDFSArr = 0;        }        visitDFSArr = new bool[count];        for(int i = 0; i < count; i++){            visitDFSArr[i] = false;        }        p.insertVertex(start);//起点加入p.list        visitDFSArr[start] = true;        while(p.list){//如果list为空则结束。每次循环增加一条线            VERTEX* vlist = p.list;            VERTEX* vp =0;//遍历当前list表找出最短的line            MinTreeLine* shortest = 0;//最短line            while(vlist){//遍历p.list中的所有的点,在所有点中找到一个最短的路径。                vp = findVertex(0, vlist->start);                LINE* bianli = vp->first;//遍历line                while(bianli){//遍历该点上的所有line                    if(!visitDFSArr[bianli->end]){//这条LINE是合法的。if里面是判断它是否最短                        if(shortest){//如果shortest已经有值了。则判断                            if(bianli->weight < shortest->weight){                                shortest->start = vlist->start;                                shortest->end = bianli->end;                                shortest->weight = bianli->weight;                            }                        }else{//如果没有值,shortest被赋值为合法值                            shortest = new MinTreeLine(vlist->start, bianli->end, bianli->weight);                        }                    }                    bianli = bianli->next;                }                if(!shortest){//这说明,某个点上没有找到可以用的LINE,那就应该删除这个点。                    p.deleteVertex(vp->start);                }                vlist = vlist->next;//下一个点            }            if(shortest){                //cout<<"加入: "<<shortest->start<<"-"<<shortest->end<<"("<<shortest->weight<<")"<<endl<<endl;                p.insertLine(shortest);                p.insertVertex(shortest->end);                visitDFSArr[shortest->end] = true;                shortest = 0;            }else{                //cout<<"结束"<<endl;                //break;            }        }        if(visitDFSArr){            delete []visitDFSArr;            visitDFSArr = 0;        }        return p;    }};//希望在构造图的时候应该先构造所有的点.int main(){    //GRAPH g(GRAPH::DG);    GRAPH g(GRAPH::NG);    //使用维基百科上prim词条中的图    g.addVertexToGraph(1);    g.addVertexToGraph(2);    g.addVertexToGraph(3);    g.addVertexToGraph(4);    g.addVertexToGraph(5);    g.addVertexToGraph(6);    g.addVertexToGraph(7);    g.addLineToVertex(1, 2, 7);    g.addLineToVertex(1, 4, 5);    g.addLineToVertex(2, 3, 8);    g.addLineToVertex(2, 4, 9);    g.addLineToVertex(2, 5, 7);        g.addLineToVertex(3, 5, 5);    g.addLineToVertex(4, 5, 15);    g.addLineToVertex(4, 6, 6);        g.addLineToVertex(5, 6, 8);    g.addLineToVertex(5, 7, 9);    g.addLineToVertex(6, 7, 11);    cout<<g.count<<endl;    g.DFSTraversal();    /*g.deleteVertex(2);    g.deleteVertex(3);    g.DFSTraversal();    */    //生成树    MinTree p = g.getPrimMinTree(5);    p.print();    cout<<p.ln<<" "<<p.vn<<endl;}

没有考虑优化问题,有内存泄漏的可能。

有时空复杂度不佳的可能。

热点排行