提交记录 14204
| 提交时间 |
评测时间 |
| 2020-09-18 14:24:30 |
2020-09-18 14:24:31 |
#include "router.h"
#include <stdint.h>
#include <stdlib.h>
#include <arpa/inet.h>
/*
RoutingTable Entry 的定义如下:
typedef struct {
uint32_t addr; // 大端序,IPv4 地址
uint32_t len; // 小端序,前缀长度
uint32_t if_index; // 小端序,出端口编号
uint32_t nexthop; // 大端序,下一跳的 IPv4 地址
} RoutingTableEntry;
约定 addr 和 nexthop 以 **大端序** 存储。
这意味着 1.2.3.4 对应 0x04030201 而不是 0x01020304。
保证 addr 仅最低 len 位可能出现非零。
当 nexthop 为零时这是一条直连路由。
你可以在全局变量中把路由表以一定的数据结构格式保存下来。
*/
void copyEntry(RoutingTableEntry * entry, RoutingTableEntry oldEntry) {
entry -> addr = oldEntry.addr;
entry -> len = oldEntry.len;
entry -> if_index = oldEntry.if_index;
entry -> nexthop = oldEntry.nexthop;
}
struct Node {
RoutingTableEntry * entry = nullptr;
Node * parent = nullptr;
Node * lNode = nullptr, * rNode = nullptr;
};
class RoutingTrie {
static Node * root;
public:
static RoutingTableEntry * search(uint32_t addr) {
addr = ntohl(addr);
Node * node = root;
RoutingTableEntry * entry = nullptr;
for (int i = 0; i < 32; i ++) {
int bit = addr >> 31;
node = (bit == 0) ? node -> lNode : node -> rNode;
if (node != nullptr) {
entry = (node -> entry == nullptr) ? entry : node -> entry;
} else {
break;
}
addr = addr << 1;
}
return entry;
}
static void insertNode(RoutingTableEntry entry) {
uint32_t addr = ntohl(entry.addr);
int len = entry.len;
Node * node = root;
for (int i = 0; i < len; i ++) {
int bit = addr >> 31;
if (bit == 0) {
if (node -> lNode == nullptr) {
node -> lNode = new Node;
node -> lNode -> parent = node;
}
node = node -> lNode;
} else {
if (node -> rNode == nullptr) {
node -> rNode = new Node;
node -> rNode -> parent = node;
}
node = node -> rNode;
}
addr = addr << 1;
}
if (node -> entry != nullptr) {
if (node -> entry -> addr == entry.addr) {
copyEntry(node -> entry, entry);
}
} else {
node -> entry = new RoutingTableEntry;
copyEntry(node -> entry, entry);
}
}
static void deleteNode(RoutingTableEntry entry) {
uint32_t addr = ntohl(entry.addr), len = entry.len;
Node * node = root;
while (len != 0) {
int bit = addr >> 31;
node = (bit == 0) ? node -> lNode : node -> rNode;
if (node != nullptr) {
addr = addr << 1;
len --;
} else {
break;
}
}
if (len == 0) { //find node
while (node != root) {
if (node -> lNode == nullptr && node -> rNode == nullptr) {
Node * deleteNode = node;
node = node -> parent;
delete deleteNode;
} else {
node -> entry = nullptr;
break;
}
}
}
}
};
Node * RoutingTrie::root = new Node;
/**
* @brief 插入/删除一条路由表表项
* @param insert 如果要插入则为 true ,要删除则为 false
* @param entry 要插入/删除的表项
*
* 插入时如果已经存在一条 addr 和 len 都相同的表项,则替换掉原有的。
* 删除时按照 addr 和 len **精确** 匹配。
*/
void update(bool insert, RoutingTableEntry entry) {
// TODO:
if (insert) {
RoutingTrie::insertNode(entry);
} else {
RoutingTrie::deleteNode(entry);
}
}
/**
* @brief 进行一次路由表的查询,按照最长前缀匹配原则
* @param addr 需要查询的目标地址,大端序
* @param nexthop 如果查询到目标,把表项的 nexthop 写入
* @param if_index 如果查询到目标,把表项的 if_index 写入
* @return 查到则返回 true ,没查到则返回 false
*/
bool prefix_query(uint32_t addr, uint32_t *nexthop, uint32_t *if_index) {
// TODO:
*nexthop = 0;
*if_index = 0;
RoutingTableEntry * entry = RoutingTrie::search(addr);
if (entry != nullptr) {
*nexthop = entry -> nexthop;
*if_index = entry -> if_index;
return true;
}
return false;
}
void init(int n, int q, const RoutingTableEntry *a) {
for (int i = 0; i < n; i ++) {
RoutingTrie::insertNode(a[i]);
}
}
unsigned query(unsigned addr) {
RoutingTableEntry * entry = RoutingTrie::search(addr);
if (entry != nullptr) {
return entry -> nexthop;
}
return 0;
}
| Compilation | N/A | N/A | Compile Error | Score: N/A | 显示更多 |
Judge Duck Online | 评测鸭在线
Server Time: 2026-03-22 23:20:38 | Loaded in 1 ms | Server Status
个人娱乐项目,仅供学习交流使用 | 捐赠