数据结构之洪水填充算法(DFS)

简介: 洪水填充算法是一种基于深度优先搜索(DFS)的图像处理技术,主要用于区域填充和图像分割。通过递归或栈的方式探索图像中的连通区域并进行颜色替换。本文介绍了算法的基本原理、数据结构设计(如链表和栈)、核心代码实现及应用实例,展示了算法在图像编辑等领域的高效性和灵活性。同时,文中也讨论了算法的优缺点,如实现简单但可能存在堆栈溢出的风险等。


1 洪水填充算法(DFS)

在图像处理领域,洪水填充算法是一项旨在实现区域填充和图像分割的关键技术。这一算法的核心思想是从一个起始点开始,通过探索相邻的像素并根据特定条件进行颜色替换,逐步填充整个连通区域。这为图像编辑、计算机视觉以及其他相关领域提供了一种高效、灵活的解决方案。

在计算机科学中,深度优先搜索(DFS)是一种用于遍历或搜索图和树等数据结构的算法。洪水填充算法正是基于DFS思想的一种应用,通过递归或栈的方式探索图像中的像素,实现了对连通区域的快速填充。

下面我的代码展示了使用C++语言实现的一种简单而直观的洪水填充算法。通过定义链表节点和栈结构,我成功地构建了一个能够处理图像填充任务的基础框架。该算法在图像处理软件中被广泛应用,为用户提供了便捷的填充工具,同时在计算机科学的教学和研究中也经常作为经典案例进行讨论。

洪水填充算法的应用不仅局限于图像编辑,还延伸至医学图像分析、计算机辅助设计以及虚拟现实等领域。其灵活性和高效性使其成为处理图像中连通区域的理想选择。通过深入理解洪水填充算法,我们能够更好地应用于实际场景,并挖掘出更多图像处理领域的创新可能性。这一算法无疑是图像处理工具箱中的一把强大工具,为处理图像中的复杂任务提供了可靠的解决方案。

2 数据结构及思维导图

深度优先搜索(DFS)
链表(ListNode 结构):

设计目的:用于构建栈数据结构,存储洪水填充算法中需要处理的像素坐标。

属性:int x, y:表示像素的二维坐标。

ListNode* next:指向链表中下一个节点的指针。

操作:构造函数 ListNode(int x_, int y_):初始化节点,设置坐标和 next 指针。
AI 代码解读

栈(Stack 类):

设计目的:用于实现深度优先搜索(DFS)的迭代,存储待处理的像素坐标。

    属性:ListNode* top:指向栈顶节点的指针。

    操作:构造函数 Stack():初始化栈,将栈顶指针置为空。

    bool isEmpty() const:检查栈是否为空。

    void push(int x, int y):将新的像素坐标入栈。

   void pop():弹出栈顶节点。

   int topX() const:返回栈顶节点的 x 坐标。

   int topY() const:返回栈顶节点的 y 坐标。
AI 代码解读

洪水填充算法(floodFill 函数):

设计目的:使用深度优先搜索迭代版本,填充相邻区域的像素。

   输入参数:int image[10][10]:表示图像的二维数组。

   int rows, int cols:图像的行数和列数。

   int x, int y:洪水填充的起始点坐标。

   int newColor:新的颜色值。

   操作:利用栈进行深度优先搜索,修改相邻区域的像素颜色。
AI 代码解读

3 核心代码

使用链表的堆栈的基本实现。它具有检查堆栈是否为空 ()、将新元素推送到堆栈 ()、弹出顶部元素 () 以及检索顶部元素 ( 和 ) 的坐标的功能。StackisEmptypushpoptopXtopY

函数使用堆栈来实现泛洪填充算法。它从指定点开始,并继续填充原始颜色的连接像素,直到不再有这样的像素。它将每个像素的颜色更新为新颜色。floodFill(x, y)

4 代码结果

2,2) 处的像素及其连接区域已填充了泛滥填充算法已正确识别并填充了从指定点开始的原始颜色的连接像素。

    该结果验证了洪水填充算法的成功应用,并在输出图像中用新颜色突出显示了填充区域。
AI 代码解读

5 算法优缺点

算法的优点:

单纯:洪水填充算法的实现相对简单,使其可用于广泛的应用。

    效率:在许多情况下,该算法可以有效地填充连续区域,尤其是在使用堆栈或队列迭代实现时。

    内存效率:此实现中基于堆栈的方法有效地使用内存来跟踪要处理的像素。

    适用性:该算法适用于特定区域需要用新颜色填充的场景。
AI 代码解读

算法的缺点:

堆栈溢出风险:如果连接的区域太大,递归或基于堆栈的实现可能会导致堆栈溢出错误。这可以通过使用带有循环的迭代方法或增加堆栈大小来缓解。

    在大图像上的性能:由于该算法的递归或迭代性质,该算法可能无法在大型图像或区域上发挥最佳性能,从而导致潜在的性能问题。

     断开连接的区域:基本洪水填充算法假定要填充的区域已连接。如果存在多个具有相同原始颜色的断开连接的区域,则每个区域都需要单独调用。

    边界检查开销:该算法涉及频繁的边界检查,这可能会增加开销,尤其是在图像尺寸较大的情况下。

   缺乏优化:此实现不包括某些优化,例如维护访问的数组以避免重新处理像素或合并多线程以进行并行处理。

   对起点的依赖性:结果可能会因具有相同原始颜色的区域内的起点而异。
AI 代码解读

6 附件之源代码

#include <iostream>

#include <stack>



// 定义链表节点

struct ListNode {

    int x, y;

    ListNode* next;

    ListNode(int x_, int y_) : x(x_), y(y_), next(nullptr) {}

};



// 定义栈结构

class Stack {

private:

    ListNode* top;



public:

    Stack() : top(nullptr) {}



    bool isEmpty() const {

        return top == nullptr;

    }



    void push(int x, int y) {

        ListNode* newNode = new ListNode(x, y);

        newNode->next = top;

        top = newNode;

    }



    void pop() {

        if (!isEmpty()) {

            ListNode* temp = top;

            top = top->next;

            delete temp;

        }

    }



    int topX() const {

        return top->x;

    }



    int topY() const {

        return top->y;

    }

};



// 洪水填充算法的实现

void floodFill(int image[10][10], int rows, int cols, int x, int y, int newColor) {

    int originalColor = image[x][y];

    if (originalColor == newColor) {

        return; // 避免重复填充

    }



    Stack stack;

    stack.push(x, y);



    while (!stack.isEmpty()) {

        x = stack.topX();

        y = stack.topY();

        stack.pop();



        if (x < 0 || x >= rows || y < 0 || y >= cols || image[x][y] != originalColor) {

            continue;

        }



        // 修改当前像素的颜色

        image[x][y] = newColor;



        // 将相邻像素入栈

        stack.push(x + 1, y);

        stack.push(x - 1, y);

        stack.push(x, y + 1);

        stack.push(x, y - 1);

    }

}



int main() {

    int image[10][10] = {

        {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},

        {1, 0, 0, 0, 1, 1, 1, 1, 1, 1},

        {1, 0, 0, 0, 1, 1, 1, 1, 1, 1},

        {1, 1, 0, 1, 1, 1, 1, 1, 1, 1},

        {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},

        {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},

        {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},

        {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},

        {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},

        {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}

    };



    int rows = 10;

    int cols = 10;



    // 在(2,2)处进行洪水填充,将0替换为2

    floodFill(image, rows, cols, 2, 2, 2);



    // 输出填充后的图像

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

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

            std::cout << image[i][j] << " ";

        }

        std::cout << std::endl;

    }



    return 0;

}



​
AI 代码解读
目录
打赏
0
0
0
0
129
分享
相关文章
算法系列之搜索算法-深度优先搜索DFS
深度优先搜索和广度优先搜索一样,都是对图进行搜索的算法,目的也都是从起点开始搜索,直到到达顶点。深度优先搜索会沿着一条路径不断的往下搜索,直到不能够在继续为止,然后在折返,开始搜索下一条候补路径。
119 62
算法系列之搜索算法-深度优先搜索DFS
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构。本文介绍了K-means算法的基本原理,包括初始化、数据点分配与簇中心更新等步骤,以及如何在Python中实现该算法,最后讨论了其优缺点及应用场景。
287 6
C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合
本文深入解析了C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合,旨在帮助读者掌握这一高效的数据处理方法。
164 1
|
1月前
|
算法系列之数据结构-二叉树
树是一种重要的非线性数据结构,广泛应用于各种算法和应用中。本文介绍了树的基本概念、常见类型(如二叉树、满二叉树、完全二叉树、平衡二叉树、B树等)及其在Java中的实现。通过递归方法实现了二叉树的前序、中序、后序和层次遍历,并展示了具体的代码示例和运行结果。掌握树结构有助于提高编程能力,优化算法设计。
51 9
 算法系列之数据结构-二叉树
|
1月前
|
算法系列之数据结构-Huffman树
Huffman树(哈夫曼树)又称最优二叉树,是一种带权路径长度最短的二叉树,常用于信息传输、数据压缩等方面。它的构造基于字符出现的频率,通过将频率较低的字符组合在一起,最终形成一棵树。在Huffman树中,每个叶节点代表一个字符,而每个字符的编码则是从根节点到叶节点的路径所对应的二进制序列。
55 3
 算法系列之数据结构-Huffman树
|
1月前
|
算法系列之数据结构-二叉搜索树
二叉查找树(Binary Search Tree,简称BST)是一种常用的数据结构,它能够高效地进行查找、插入和删除操作。二叉查找树的特点是,对于树中的每个节点,其左子树中的所有节点都小于该节点,而右子树中的所有节点都大于该节点。
77 22
C 408—《数据结构》算法题基础篇—链表(下)
408考研——《数据结构》算法题基础篇之链表(下)。
106 29
C 408—《数据结构》算法题基础篇—链表(上)
408考研——《数据结构》算法题基础篇之链表(上)。
140 25
C 408—《数据结构》算法题基础篇—数组(通俗易懂)
408考研——《数据结构》算法题基础篇之数组。(408算法题的入门)
102 23
探索局域网电脑监控软件:Python算法与数据结构的巧妙结合
在数字化时代,局域网电脑监控软件成为企业管理和IT运维的重要工具,确保数据安全和网络稳定。本文探讨其背后的关键技术——Python中的算法与数据结构,如字典用于高效存储设备信息,以及数据收集、异常检测和聚合算法提升监控效率。通过Python代码示例,展示了如何实现基本监控功能,帮助读者理解其工作原理并激发技术兴趣。
106 20

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等