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

}

三、经典应用场景

图像编辑器的油漆桶工具

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

迷宫/连通区域计数

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

相关推荐
倒头就睡的小比特3 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼3 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
旖旎夜光3 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark3 天前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her13 天前
并查集-听课笔记
笔记·算法·并查集
码流子3 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven3 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark3 天前
从算法设计模式看编程思维的抽象能力4
算法
2601_962218613 天前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法