un travail non-récursive diffuseur algorithme écrit en C?
J'ai essayé de trouver un travail diffuseur de l'algorithme. De nombreux algorithmes j'ai essayé le "récursive de la ligne de remplissage" on se comporte exactement comme il se doit avec le bémol de taille que de temps en temps des coups de la pile. 🙁
J'ai essayé beaucoup de non-récursive implémentations j'ai trouvé et ils ont tous été exceptionnellement tempermental: soit ils laissent des lacunes dans des endroits étranges, ou flood l'ensemble de la zone (alors qu'ils devraient être inclus).
Quelqu'un a une NON-récursive diffuseur de travail code source écrit en C (ou c++ qui n'est pas trop fortement de la POO et je peux démêler assez facilement)?
- Juste un nit à ramasser: des Algorithmes en pseudo-code (et/ou des images), vous êtes en train de demander à une mise en œuvre (en C).
- Une fois, j'ai cette question dans le cadre d'une maison de programmation interview, et je devine que par votre urgence que vous avez trop.
- en fait, andy, non ce n'est pas pour une interview 🙂 c'est pour une bibliothèque graphique, je suis en train d'écrire 🙂
- Pour répondre à la question: Oui, j'ai un non-récursive floodfilling mise en œuvre. Il a utilisé une todo-list (et un fait-liste, IIRC).
Vous devez vous connecter pour publier un commentaire.
Voici un code C++ qui fait ce que vous voulez. Il utilise une file d'attente, et est plus efficace sur les insertions dans la file d'attente.
Mettre en œuvre une pile de type int paires avec un parc de taille fixe (peut-être la taille de l'image en pixels ou la racine carrée de ce que, par exemple) pour la pile et de suivre le dessus avec un int.
Voici un code C# qui implémente remplir de manière non-récursive:
Une rapide recherche sur google apporte la Article de wikipédia sur le pot de peinture qui comprend pseudocode implémentations qui ne sont pas récursives. Ci-dessous est un code qui pourrait vous aider à démarrer, une file d'attente de mise en œuvre dans C:
N'est-ce pas là une preuve quelque part que toutes les fonctions récursives peuvent être mis en œuvre comme un processus itératif de la fonction à l'aide des données pour simuler une pile? Vous pourriez probablement utiliser std::vector pour créer une pile comme le comportement de l'algorithme sans faire exploser la pile car il utilise le tas.
EDIT: j'ai remarqué que vous êtes à l'aide de C, de sorte qu'au lieu de std::vector, vous pouvez simplement mettre en œuvre un comportement similaire via le realloc que vous avez besoin d'ajouter plus d'éléments à votre local de la "pile" de quelle que soit la structure de données que vous utiliseriez.
Vous pouvez convertir n'importe quel récursive de l'algorithme itératif par la création d'un explicite de la pile ou de la file d'attente et de chargement de travail sur elle/tirant dessus.
Tous vous avez besoin est de choisir une belle représentation compacte du travail à faire. Le pire des cas: créer une
struct
holding les arguments que vous auriez normalement passer à une version récursive...Nous avons remarqué que notre diffuseur mise en œuvre sur des volumes 3d était en train de consommer beaucoup de mémoire; nous avons modifié le code de la façon suivante (il y a eu une grande amélioration):
Créer une sphère de rayon = 10 voxs autour du point de départ, et de marquer tous les voxels dans ce rayon comme "visités"
Si le voxel > seuil, insérer 1.
Aller à l'voisins [+1, -1, 0] (aussi vérifier que l'on ne veut pas revoir toute voxel), si le voisin.getVoxVal = 0 (la valeur d'initialisation pour le volume cible), puis il tombe à la limite de la sphère, insérer les coordonnées dans une autre pile. (ce serait le point de départ de notre côté de la sphère)
rayon = rayon de + 10 (voxels)
À un moment, notre diffuseur est de travailler sur une sphère concentrique, et le remplissage des choses, qui est une partie de l'ensemble du volume, et comme je l'ai dit, cela a permis de réduire la consommation de mémoire de façon drastique, mais je suis toujours à la recherche d'une mise en œuvre ou de l'idée que ce serait mieux.
Je ne sais pas si ma réponse est parfaitement pertinente à la question que vous avez mis, mais ci je vous propose ma version C de l'Inondation-algorithme de Remplissage, qui n'utilise pas les appels récursifs.
1-11-2017: NOUVELLE VERSION; AVEC SUCCÈS TESTÉ AVEC DEUX BITMAPS.
Il utilise seulement une file d'attente de la décalages de nouveaux points, il fonctionne sur la fenêtre: WinnOffs-(WinDimX,WinDimY) de la double mémoire tampon: *VBuffer (copie d'écran ou une image) et, en option, d'écrire un masque de l'inondation de remplissage du résultat (*ExtraVBuff).
ExtraVBuff doit être rempli avec de l'0 avant l'appel (si vous n'avez pas besoin d'un masque, vous pouvez définir ExtraVBuff= NULL); à l'utiliser après l'appel, vous pouvez le faire gradient de remplissage ou d'autres effets de peinture. NewFloodFill fonctionne avec 32 Bits par Pixel et c'est une fonction C. J'ai réinventé cet algorithme en 1991 (j'ai écrit son en Pascal), mais maintenant il travaille dans C à 32 Bits par Pixel; aussi n'utilise pas toutes les fonctions d'appels, n'a seulement une division après chaque "pop" de la file d'attente, et de ne jamais les débordements de la file d'attente, qui, si elle est de taille moyenne dans le droit chemin (environ 1/4 de pixels de l'image), il permet toujours de remplir correctement une zone quelconque; je montre avant de la c-fonction (FFILL.C), après le programme de test (TEST.C):
Ici, il y a le programme de test:
Que j'ai utilisé, pour l'entrée de l'essai de programme indiqué, le Windows non compressé .Image BMP (ffill1.bmp):
Rempli, par le programme de test indiqué, comme suit (ffill2.bmp):
À l'aide de "masque" au lieu de NULL, la sortie bitmap (ffill3.bmp):
J'ai un non-récursive de remplissage, mais je ne vais pas le publier parce que c'est la solution pour un devoir à la maison. Mais voici un indice: depth-first search, qui est l'algorithme utilise loin auxiliaire d'espace qu'une largeur d'abord de recherche. Voici ce que j'ai écrit à l'époque (convenablement expurgée):
Pour ma structure de données, j'ai utilisé le
Seq_T
de Dave Hanson C Interfaces et Implémentations; la modification de la profondeur, de la première à la largeur de la première nécessite la modification d'un seul appel de fonction.Vous pouvez convertir rapidement récursive de remplissage dans un ultra-performant pseudo-récursive... de Ne pas modifier les lignes,il suffit d'ajouter de nouvelles lignes:
place de la fonction récursive dans un XY boucle pour l'ajout de la structure.
enregistrement de la trouvé voisins d'une "trouvés voisins tableau"
au lieu de mémoire, alors vous allez commencer à emballer les 4-16-64 style arbre de la récursion dans un XY tableau. l'utilisation de la mémoire va de 1 gygabyte à 2 mo.
Aussi l'utilisation d'un tableau 2D appelé "rempli voisins array"... annuler la fonction pour tous les pixels marqués comme rempli le "rempli voisins tableau", il utilise 2 des instructions pour chaque duplicata, 20 instructions pour chaque diffuseur de l'opération, et il remplit de manière itérative vers la gauche et vers le haut, comme des dominos, incroyablement rapidement.
1024x1024 utilise sur 1 million *20 instructions qui est de 0,1 secondes pour un seul cœur.
Je atteindre 9 millions rempli de pixels par seconde sur un core i7 de cette façon, j'ai une vidéo comme preuve, et une page de blog avec le code et les explications théoriques:
http://www.youtube.com/watch?v=4hQ1wA4Sl4c
et voici une page où j'ai essayé d'expliquer comment il fonctionne.
http://unity3dmc.blogspot.com/2017/02/ultimate-3d-floodfill-scanline.html?m=1
Et le code.
Récurrences serait la manière la plus rapide s'ils pouvaient rester organisé.
Si vous recurse travers d'une grille de données (image) vous pouvez stocker le traitement des récurrences sous forme de grille trop, parce que le traité étapes représentent des pixels de la grille, plutôt que d'exploser les résultats sous la forme d'un arbre.
Ci-dessous est mon BFS axée sur c++ pour la méthode de remplissage problème: