You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在PHP中获取可用CIDR网段:确定未使用子网的最优算法

解决父子网未使用子网的最优算法实现

核心思路梳理

你一开始的思路其实非常靠谱——从父网出发,逐步拆分并排除已使用子网,这个方法叫「分割-排除法」,是处理这类子网计算问题效率很高的方案。我来把子网拆分的具体逻辑拆解开,帮你补全算法的细节。

子网拆分的核心操作与流程

首先得明确几个基础操作,这是拆分的前提:

  1. 判断子网包含关系:要验证子网A是否包含子网B,需确认B的网络地址落在A的地址范围内,且B的前缀长度≥A的前缀长度。
  2. 拆分单个子网为两个子子网:比如把10.0.0.0/24拆成两个/25,就是10.0.0.0/25和10.0.0.128/25;拆分/25则得到两个/26——本质是把当前子网主机位的最高位分别设为0和1,生成两个新的子网。

接下来是完整的算法执行流程:

  • 初始化$unused数组,只放入父子网$parent。
  • 遍历每个已使用的子网$used_subnet:
    1. 遍历$unused数组,找到包含$used_subnet的唯一目标子网$target(因为$unused里的子网是不重叠且完全覆盖父网的,所以只会有一个)。
    2. 如果$target和$used_subnet完全相等,直接从$unused中移除$target,跳过后续步骤。
    3. 如果$target的前缀长度比$used_subnet小,开始循环拆分:
      • 将$target拆分为两个下一级的子网(比如/24拆成两个/25)。
      • 从$unused中移除$target,把拆分后的两个子网加入$unused。
      • 再次检查这两个新子网,找到包含$used_subnet的那个,继续拆分,直到拆分出的子网前缀长度和$used_subnet一致。
    4. 此时$unused里会有一个和$used_subnet完全匹配的子网,将其移除即可。
  • 遍历结束后,$unused中的就是最精简的未使用子网集合。

补全后的伪代码(含拆分逻辑)

function get_unused_subnets(parent, used):
    unused = [parent]
    # 优化:先按前缀长度从大到小排序已使用子网,减少拆分次数
    sort used in descending order of prefix length
    
    for each used_subnet in used:
        target = find_containing_subnet(unused, used_subnet)
        if target == used_subnet:
            unused.remove(target)
            continue
        
        # 循环拆分直到target的前缀与used_subnet一致
        while target.prefix_length < used_subnet.prefix_length:
            subnet1, subnet2 = split_subnet(target)
            # 替换unused中的target为两个子子网
            unused.remove(target)
            unused.append(subnet1)
            unused.append(subnet2)
            # 更新target为包含used_subnet的子子网
            target = find_containing_subnet([subnet1, subnet2], used_subnet)
        
        # 移除匹配的已使用子网
        unused.remove(target)
    
    # 可选:按网络地址排序,让结果更规整
    sort unused by network address
    return unused

# 辅助函数:拆分子网为两个下一级子网
function split_subnet(subnet):
    network = subnet.network_address  # 比如10.0.0.0
    prefix = subnet.prefix_length     # 比如24
    host_bits = 32 - prefix
    step = 1 << (host_bits - 1)       # 计算拆分步长:2^(主机位-1)
    
    network1 = network
    network2 = network + step
    return (Subnet(network1, prefix+1), Subnet(network2, prefix+1))

# 辅助函数:从列表中找到包含目标子网的条目
function find_containing_subnet(subnets, target):
    for subnet in subnets:
        if subnet.network_address ≤ target.network_address 
           and (target.network_address + target.host_count) ≤ (subnet.network_address + subnet.host_count):
            return subnet
    return null

额外优化建议

  1. 二分查找优化:如果维护unused数组按网络地址排序,find_containing_subnet可以用二分查找替代遍历,大幅提升大数量子网场景下的效率。
  2. 相邻子网合并(可选):如果你的场景允许合并相邻的同前缀子网(比如两个相邻的/29合并为/28),可以在最后对$unused做一次合并操作,让结果更精简——不过你的示例输出没有做合并,所以这一步看业务需求。

用你给出的示例测试:初始unused = ['10.0.0.0/24'],依次处理三个已使用子网后,最终就能得到你给出的$unused结果。

内容的提问来源于stack exchange,提问作者James

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:44:09