Copy Graph(BFS)

    自从中午饿得被迫起来吃完了一个午饭之后,就开始做这道题。鉴于之前做过一道Copy List with Random Pointer的题,看了大神的答案之后比自己想的快,就借鉴了那个思想,原先我的想法是用map的key记录原结点的引用,将新建结点的引用存入value,鉴于大神是将copy的结点接在原结点之后再删除,代码简洁得让我震惊啦,而且效率也比我的高,这回用的也是这个思想,就是将copy的结点插入原结点的neighbors的第一个,之后再拆掉。。。用的BFS。。。结果。。因为BFS之前完全没写过,第一次写,用了一个下午写完了(中间间歇和我家亲爱哒聊个QQ神马的降低效率的事情我才不会写粗来呢~╭(╯^╰)╮),之后调程序用了一个晚上。。。有个错误是

GZRS9(3@HJS`39IU%GN~%6N

让我纠结了好久。。。差点就放弃想看答案了。。。后来试着把每个插入原结点的neighbors的第一个结点给删掉了就好了。。。。

     还有就是怎么判断结点是否被访问过,这个也让我想了很久,出了很多错,因为《算法导论》里是有color来标记的,可是这个题目并没有这个属性,所以几乎每次遍历都是不一样的判断方法,但是总归思想就是,如果没有访问过,就要标记访问了,并且入队,之前错误在于入队了,但是没有标记访问,所以出了各种错。

    写了好大一长串。。。后来看了大神答案,然后又被大神简洁的代码震惊了一次。。。好吧,一直在震惊,从未停止过。。。发现大神用的居然是用map储存key的思想。。。而且提交后还是比我的快。。。虽然只快了十几ms,但是也是快了。。。T_T。。。突然觉得。。。思想我是学会了,可是还是不会灵活运用啊。。。哎。。。不管了,明天用map的方法写个DFS的试试。。

    下面上我的代码:

class Solution {
public:
// 三次遍历,第一次clone原结点, 第二次clone neighbors节点,第三次删除clone的结点
// 1. 访问过一个结点,则在其neighbors的头插入新建的clone的结点,如果一个结点的neighbors[0]的label是自己,且地址不是自己,则表明被访问过
// 2. 再遍历一遍,结点node的neighbors是原来的neighbors的第一个结点
    UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
        if(node == NULL) return NULL;
        // 用BFS遍历
        UndirectedGraphNode *cur = node, *nei;
        queue<UndirectedGraphNode *> que;
        vector<UndirectedGraphNode *> neighbors;
        UndirectedGraphNode *p = new UndirectedGraphNode(node->label);
        (cur->neighbors).insert(cur->neighbors.begin(), p);
        que.push(cur);
        while(!que.empty()){ // 第一遍
            cur = que.front();
            que.pop();
            neighbors = cur->neighbors;
            if(neighbors.size() > 1){
                for(int i = 1; i != neighbors.size(); ++ i){ // 遍历cur的相邻结点, 不包括nei[0],因为0是cur的clone
                    nei = neighbors[i];
                    // 如果nei没被访问过,则clone并入队
                    if(nei->neighbors.empty() ||(nei->neighbors[0]->label != nei->label) || (nei->neighbors[0] == nei)){ 
                        p = new UndirectedGraphNode(nei->label);
                        (nei->neighbors).insert(nei->neighbors.begin(), p);
                        que.push(nei);
                    }
                }
            }
        }
        que.push(node);
        // 先将node的neighbors复制给newNode的neighbors
        copyNeighbors(node);
        while(!que.empty()){// 第二遍,如果nei的neighbors.size() > 1,并且nei的neighbors[0].neighbors为空,则说明没访问过
            cur = que.front();
            que.pop();
            neighbors = cur->neighbors;
            for(int i = 1; i != neighbors.size(); ++i){ // 将cur的相邻结点入队
                nei = neighbors[i];
                UndirectedGraphNode *newNode = nei->neighbors[0];
                if(((nei->neighbors).size() > 1)  && (newNode->neighbors).empty()){ // 说明没被访问过
                    copyNeighbors(nei); // 访问他,并将它入队
                    que.push(nei);
                }
            }
        }
        UndirectedGraphNode *u = node->neighbors[0];
        // 第三遍,删除vector的第一项
        que.push(node);
        node->neighbors.erase(node->neighbors.begin());
        while(!que.empty()){
            cur = que.front();
            que.pop();
            neighbors = cur->neighbors;
            for(int i = 0; i != neighbors.size(); ++i){
                if(neighbors.empty()) break;
                nei = neighbors[i];
                if(!nei->neighbors.empty() && (nei->label == nei->neighbors[0]->label) && (nei != nei->neighbors[0])){
                    nei->neighbors.erase(nei->neighbors.begin());
                    que.push(nei);
                }
            }
        }
        return u;
    }
    void copyNeighbors(UndirectedGraphNode *node){
        UndirectedGraphNode *newNode = node->neighbors[0];
        vector<UndirectedGraphNode *> neighbors = node->neighbors;
        for(int i = 1; i != neighbors.size(); ++ i){// 先将node的neighbors复制给newNode的neighbors
                    (newNode->neighbors).push_back(neighbors[i]->neighbors[0]);
            }
    }
};
posted @ 2014-10-19 23:35  薇清浅  阅读(343)  评论(0编辑  收藏  举报