【入门级-算法-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;

}

三、经典应用场景

图像编辑器的油漆桶工具

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

迷宫/连通区域计数

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

相关推荐
MartinYeung51 小时前
[论文学习]LLM 情境学习资料的快速精确遗忘技术:基于 In-Context Learning 与量化 K-Means 的 ERASE 方法
学习·算法·kmeans
林森lsjs1 小时前
【日耕一题】5. 青春常数(17届蓝桥杯C++B组第一题)
算法·蓝桥杯
Tisfy1 小时前
LeetCode 3838.带权单词映射:求和、取模、拼接(附python一行版)
python·算法·leetcode·字符串·题解·模拟·取模
め.1 小时前
GJK算法实现细节
算法
AI科技星1 小时前
第六卷:量天尺传奇(几何学)
网络·人工智能·算法·概率论·学习方法·几何学·拓扑学
Y_Bk2 小时前
第十七届蓝桥杯C/C++A组省赛
c语言·数据结构·c++·算法·蓝桥杯
帅小伙―苏2 小时前
力扣76最小覆盖子串
算法·leetcode
RH2312112 小时前
2026.5.24 数据结构 KMP算法实现
数据结构·算法
江屿风2 小时前
C++图论基础单源最短路-常规版dijkstra算法/堆优化版dijkstra算法/bellman-ford 算法/spfa 算法流食般投喂
开发语言·c++·笔记·算法·图论