【图论小结】

图的保存

边的表示
// 适用于一般情况的边的表示
// 根据不同的情况有不同的变体
struct Edge {
    int from, to, cost;
}
邻接矩阵

d[from][to]=cost
最简单的方式,适用于密集图
缺点:内存消耗是O(V2),点太多会存不下

静态邻接表

貌似有很多称呼,我觉得还是这个比较贴切。
优势:
直接访问从某个节点出发的所有弧,效率高。
可以直接通过id(下标)来访问某条边。
节省内存。

Edge E[MaxE], tot;
int head[MaxV], next[MaxE];

void init() {
    memset(head, -1, sizeof(head));
    tot = 0;
}

void add_edge(int from, int to, cost) {
    next[tot] = head[from];
    head[from] = tot;
    E[tot++] = Edge(from, to, cost);
}
// 遍历从u出发的所有弧
void foo(int u) {
    for (int i = head[u];i != -1;i = next[i]) {
        // ...
    }
}
使用vector的邻接表

根据个人习惯有很多变体,列举一下我常用的
优点:
相比静态内存的邻接矩阵,往往可以减少很多内存消耗。
同时比邻接表易于coding。
缺点:访问速度较慢。

第一种
// 直接存放边
vector<Edge> G[MaxV];

void add_edge(int from, int to, int cost) {
    G[from].push_back( Edge(from, to, cost) );
}

// 访问
void foo(int u) {
    int sz = G[u].size();
    for (int i=0;i<sz;++i) {
        Edge &e = G[u][i];
        // ...
    }
}
第二种

我更偏好这一种,很多时候会更方便。

vector<Edge> E;
vector<int> G[MaxV]; // 图中只保存边的id

void add_edge(int from, int to, int cost) {
    G[from].push_back(E.size());
    E.push_back( Edge(from, to, cost) );
}

// 访问
void foo(int u) {
    int sz = G[u].size();
    for (int i=0;i<sz;++i) {
        Edge &e = E[G[u][i]];
        // ...
    }
}
动态内存的邻接表

编程复杂度高,容易出错。。

struct node{
    int to, cost;
    node *next;
    node (int to, int cost) :to(to), cost(cost){
        next = NULL;
    }
};

class Graph {
    node **G;
    int MaxV;
    void init(int V) {
        MaxV = V;
        G = new node*[V];
    }

    void add_edge(int from, int to, int cost) {
        node * p = new node(to, cost);
        p->next = G[from];
        G[from] = p;
    }

    void clear() {
        for (int i=0;i<MaxV;++i) if (G[i] != NULL) {
            node *p = G[i];
            while (p) {
                node *tmp = p->next;
                delete p;
                p = tmp;
            }
        }
        delete [] G;
    }
};
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值