【入门级-算法-8、图论算法:泛洪算法 (Flood Fill)】

一、算法概述

1.泛洪算法(Flood Fill):图论和图像处理中的一种经典算法,用于确定连通区域。

它的典型应用是 "油漆桶"工具:点击图片中的一个像素,程序会把与该像素颜色相同且连通的区域全部填充为新颜色。

  1. 核心思想
    从种子点(起点)出发,向四周相邻位置(通常四邻域或八邻域)扩散,访问所有"连通"且"满足条件"的节点,直到所有连通区域都被访问。。

3.连通规则:

4 邻域:上、下、左、右

8 邻域:上、下、左、右 + 对角线方向

条件:通常颜色相同(或特征相似)

二、实现方法

图论模型建立

// 网格图的抽象表示

typedef struct {

int color; // 节点颜色

int visited; // 访问标记(可选)

} Node;

// 四连通邻接关系(隐式图,不需要显式存储边)

// 每个节点最多有4个邻居:上、下、左、右

const int dx4 = {-1, 1, 0, 0}; // 行方向偏移

const int dy4 = {0, 0, -1, 1}; // 列方向偏移

//递归DFS版本(最接近图论定义)

#include <stdio.h>

#include <stdlib.h>

// 四连通泛洪填充(递归DFS)

// 参数说明:

// image: 二维数组,存储颜色值

// rows, cols: 图像尺寸

// x, y: 当前坐标

// targetColor: 要填充的目标颜色

// newColor: 新颜色

void floodFillRecursive(int** image,

int rows, int cols,

int x, int y,

int targetColor,

int newColor)

{

// 1. 边界检查(防止越界)

if (x < 0 || x >= rows || y < 0 || y >= cols) {

return;

}

复制代码
// 2. 颜色匹配检查(图论中的"节点值相等")
if (image[x][y] != targetColor) {
    return;
}

// 3. 访问当前节点(染色)
image[x][y] = newColor;

// 4. 递归访问所有邻接节点(图论中的DFS遍历)
floodFillRecursive(image, rows, cols, x + 1, y, targetColor, newColor);
floodFillRecursive(image, rows, cols, x - 1, y, targetColor, newColor);
floodFillRecursive(image, rows, cols, x, y + 1, targetColor, newColor);
floodFillRecursive(image, rows, cols, x, y - 1, targetColor, newColor);

}

// 注意:递归版本在图像较大时(>1000x1000)可能导致栈溢出

测试程序

#include <stdio.h>

#include <stdlib.h>

// 创建动态二维数组

int** createImage(int rows, int cols) {

int** image = (int**)malloc(sizeof(int*) * rows);

for (int i = 0; i < rows; i++) {

imagei = (int*)malloc(sizeof(int) * cols);

}

return image;

}

// 释放内存

void freeImage(int** image, int rows) {

for (int i = 0; i < rows; i++) {

free(imagei);

}

free(image);

}

// 打印图像

void printImage(int** image, int rows, int cols) {

for (int i = 0; i < rows; i++) {

for (int j = 0; j < cols; j++) {

printf("%2d ", imageij);

}

printf("\n");

}

printf("\n");

}

// 复制图像

int** copyImage(int** src, int rows, int cols) {

int** dst = createImage(rows, cols);

for (int i = 0; i < rows; i++) {

for (int j = 0; j < cols; j++) {

dstij = srcij;

}

}

return dst;

}

int main() {

// 创建测试图像(0表示空白,1-9表示不同颜色)

int rows = 8, cols = 8;

int** original = createImage(rows, cols);

复制代码
// 初始化复杂图像(包含多个连通区域)
int init[8][8] = {
    {1, 1, 1, 2, 2, 2, 3, 3},
    {1, 0, 1, 2, 0, 2, 3, 3},
    {1, 1, 1, 2, 2, 2, 3, 3},
    {4, 4, 4, 5, 5, 5, 6, 6},
    {4, 0, 4, 5, 0, 5, 6, 6},
    {4, 4, 4, 5, 5, 5, 6, 6},
    {7, 7, 7, 8, 8, 8, 9, 9},
    {7, 0, 7, 8, 0, 8, 9, 9}
};

for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
        original[i][j] = init[i][j];
    }
}

printf("=== 原始图像 ===\n");
printImage(original, rows, cols);

// 测试1:递归DFS填充左上角区域(颜色1 -> 99)
int** img1 = copyImage(original, rows, cols);
printf("=== 测试1:递归DFS从(0,0)填充颜色1->99 ===\n");
floodFillRecursive(img1, rows, cols, 0, 0, 1, 99);
printImage(img1, rows, cols);
freeImage(img1, rows);

// 测试2:迭代DFS填充中间区域(颜色5 -> 55)
int** img2 = copyImage(original, rows, cols);
printf("=== 测试2:迭代DFS从(3,3)填充颜色5->55 ===\n");
floodFillIterativeDFS(img2, rows, cols, 3, 3, 5, 55);
printImage(img2, rows, cols);
freeImage(img2, rows);

freeImage(original, rows);
return 0;

}

三、经典应用场景

图像编辑器的油漆桶工具

游戏地图区域填充(扫雷翻开一片空白区)

迷宫/连通区域计数

多边形种子填充(计算机图形学)

相关推荐
fqq320 分钟前
力扣刷题前置Java语法
算法·leetcode·职场和发展
2501_906565123 小时前
数学之美探究
算法
oier_Asad.Chen3 小时前
【洛谷题解/AcWing题解/OI学习笔记】洛谷P2868【USACO07DEC】Sightseeing Cows G(01分数规划求最大比率)
算法·图论·spfa·二分·负环
leisoo80975 小时前
财报数据怎么排雷本地化Python构建财务异常预警系统
人工智能·python·算法
luj_17687 小时前
塔防牌:策略与卡牌的智慧碰撞
服务器·c语言·开发语言·经验分享·算法
郝学胜-神的一滴7 小时前
干货版《算法导论》17:二叉树核心原理、遍历逻辑与高阶实操全解
数据结构·c++·python·算法·计算机·编程
爱编程的小新☆8 小时前
【LeetCode】从递归到 Flood Fill:5 道题吃透 DFS 的选择、回溯与标记
java·算法·leetcode·深度优先·回溯·flood fill
Water_Sunzhipeng8 小时前
2024牛客暑期多校训练营1
算法
hetao17338378 小时前
2026-08-09~08-14 hetao1733837 的刷题记录
c++·算法
技术小黑8 小时前
RNN算法实战系列06 | LSTM 实现糖尿病探索与预测
rnn·算法·lstm