Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Графы. Паскаль  (Прочитано 15476 раз)
0 Пользователей и 2 Гостей смотрят эту тему.
Viwwna
Интересующийся

ru
Offline Offline

« : 01-07-2012 20:02 » 

Вновь обращаюсь к Вам за помощью... Прошу помочь с Графами по поиску в глубину.... Задача такая:
Напишите и используйте в программе процедуру, реализующую метод, отличающийся от поиска в ширину только тем, что вновь достигнутая вершина помещается не в очередь, а в стек.

Спасибо, кто откликнется...

Код: (Pascal)
const n=9;
C:array[0..n,0..n] of 0..1={((...матрица смежности))}
visit:array[0..n] of boolean=(true,true,true,true,true,true,true,true,true);
var v:integer;
procedure DFS(v:integer);
var Stek:array[1..(n+1)] of 0..n;
t,Uk:integer;f:boolean;
begin
  write(v:3);
  Uk:=0;
  Uk:=Uk+1;
  stek[Uk]:=v;
  visit[v]:=false;
  while Uk<>0 do   begin
    v:=stek[Uk];
    t:=0;f:=false;
    repeat
      if(C[v,t]=1) and (visit[t]) then
        f:=true
      else
        t:=t+1;
    until f or (t>n);
    if f then begin
      write(t:3);
      Inc(Uk);
      stek[Uk]:=t;
      visit[t]:=false;
    end
    else
      Uk:=Uk-1;
  end;
end;

begin
  writeln('поиск в глубину');
  writeln('введите вершину начала поиска');
  readln(v);
  DFS(v);
end.
« Последнее редактирование: 01-07-2012 20:45 от Sla » Записан
Sla
Модератор

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 01-07-2012 20:50 » 

хм...
понять бы что такое  поиск в ширину, и поиск в глубину.
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #2 : 02-07-2012 08:47 » 

можно  даже картинками
Записан

Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 02-07-2012 08:53 » 

viwwna, код сложно читать: имена переменных совершенно не говорящие (ну, кроме stek и visit, но, помимо их, там полно "магии"). Кроме того, я бы предложил, как это заведено, сначала дать словесное описание алгоритма, причём подробное: что мы делаем на очередном шаге, что служит критерием остановки алгоритма.
Записан
Viwwna
Интересующийся

ru
Offline Offline

« Ответ #4 : 02-07-2012 11:28 » 

Sla, Алексей1153++, Здесь более или менее понятно написано:
 Основные требования к методам поиска в графе:
1)    метод должен легко реализовываться алгоритмом решения ин-тересующей нас задачи;
2)    каждое ребро графа анализируется один раз (или ограниченное число раз, что существенно не меняет ситуации).
Существует много алгоритмов на графах, в основе которых лежит систематический перебор вершин графа, причем каждая вершина про-сматривается точно один раз.
Рассмотрим один метод поиска в неориентированном графе, ко-торый является основой многих графовых алгоритмов. Этот метод на-зывается поиском в глубину (depth first search).
Общая идея метода состоит в следующем. Начинаем поиск с не-которой фиксированной вершины v0. Затем выбираем произвольную вершину u, смежную с v0, и повторяем наш просмотр от u . В общем случае предположим, что мы находимся в некоторой вершине v. Если существует новая (ещё не просмотренная) вершина u, u-v, то мы рас-сматриваем эту вершину (она перестает быть новой), начиная с неё, продолжаем поиск. Если же не существует новой вершины, смежной с v, мы говорим, что вершина v использована, возвращаемся в вершину, из которой мы попали в v, и продолжаем поиск (если v=v0, то поиск закончен).
Иначе говоря, поиск в глубину из вершины v основывается на по-иске в глубину из всех новых вершин, смежных с v.
Это можно легко записать с помощью рекурсивной процедуры WG(v):
Код: (Pascal)
PROCEDURE WG(v);        {поиск в глубину из вершины v}
{перемен. НОВЫЙ, СПИСОК – глобальные}
BEGIN  рассмотреть v;  НОВЫЙ[v] := false;
        FOR uСПИСОК[v] DO
                IF НОВЫЙ[u] THEN WG(u)
END {вершина использована}
Весь процесс поиска в глубину в произвольном, необязательно связном графе производится по следующему алгоритму:
BEGIN
        FOR vV DO НОВЫЙ[v] := true;  {инициализация}
        FOR vV DO
                IF НОВЫЙ[v] THEN WG(v)
END.
Можно убедиться в том, что этот алгоритм просмотрит каждую вершину ровно один раз и его сложность порядка О(n+m). Дополни-тельно каждый вызов WG(v) влечет за собой просмотр всех вершин компоненты связности графа, содержащей v (если они ещё не про-смотрены, т.е. НОВЫЙ=true для каждой вершины u, принадлежащей этой компоненте). При этом каждая вершина просматривается не более одного раза.
Сам алгоритм начинает поиск поочередно от каждой ещё не про-смотренной вершины, следовательно, просматриваются все вершины графа (необязательно связного).
Чтобы оценить сложность алгоритма, заметим, что число шагов в обоих циклах FOR (строки 2,3)  n (не считая шагов, выполненных при вызове WG). Эта программа выполняется не более чем n раз во втором цикле сразу после посещения каждой из вершин для каждого из её но-вых соседей, суммарно не более чем (n+m) раз. Полное число шагов, выполняемых циклом в третьей строке процедуры WG (не считая ша-гов, выполняемых WG(n)), для всех вызовов этой процедуры будет порядка m, где m – число ребер. Это дает общую сложность алгоритма О(n+m).
Т.к. поиск в глубину играет важную роль в разработке алгоритмов на графах, представим также нерекурсивную версию процедуры WG.
Стандартным способом устранения рекурсии является использование стека.  Каждая просмотренная вершина помещается в стек и удаляется из него после использования.
   {нерекурсивная версия процедуры WG;
 предполагаем, что в начале поиска P – указатель на 1-ую за-пись списка СПИСОК для каждой вершины u;
массивы Р, НОВЫЙ – глобальные}
Код: (Pascal)
1       PROCEDURE WG1(v);
        {поиск в глубину в графе, начиная с вершины v}
2       BEGIN  СТЕК := 0;  СТЕК <= v;  рассмотреть v; НОВЫЙ[v] := false;
3       WHIKE  СТЕК  0 DO
4            BEGIN t := top(СТЕК);  {t – верхний элемент стека}
             {найти первую новую вершину в списке СПИСОК[t]}
5            IF P[t] = nil THEN b := false
6                      ELSE b := not НОВЫЙ[P[t]^.строка];
7            WHILE  b  DO  BEGIN
8                 P[t] := P[t]^.след;
9                 IF  P[t] = nil  THEN  b := false
10                ELSE  b := not НОВЫЙ[P[t]^.строка]
11           END;
12           IF  P[t]nil  THEN  {найдена новая вершина}
13                BEGIN  t := P[t]^.строка;  СТЕК <= t;
14                рассмотреть t;  НОВЫЙ[t] := false
15           END
16           ELSE  {вершина t использована}
17                t <= СТЕК  {удалить верхний элемент стека}
18           END
19      END
Примечание. В круглых скобках пронумеруем вершины графа в той очередности, в которой они просматриваются в процессе поиска в глубину.


* Безымянный.JPG (28.18 Кб - загружено 1025 раз.)
Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 02-07-2012 11:35 » new

viwwna, это всё вредная копипаста, для нормального понимания лучше писать алгоритм с нуля Улыбаюсь Сам принцип вполне прост, и он не "отличающийся от поиска в ширину только тем, что..." - а фундаментально отличается от поиска в ширину принципом работы.
Если в ширину нам нужно, как верно сказано, хранить очередь вершин, потому что мы постепенно всё расширяем и расширяем круг затрагиваемых вершин, спускаясь по 1 ступеньке вглубь, то в глубину мы спускаемся сразу насколько можем, запоминая весь путь в одном стеке.

Соответственно, зная, как следует организовать сохранение информации, и понимая, когда алгоритм должен остановиться, реализацию написать очень просто, и не надо будет путаться в странном чужом коде.
Записан
Viwwna
Интересующийся

ru
Offline Offline

« Ответ #6 : 02-07-2012 11:41 » 

Поиск в глубину
Поиск в глубину - еще один способ обхода графа. Он используется в таких алгоритмах, как алгоритм топологической сортировки, алгоритм поиска сильно связанных компонент.
Стратегия поиска в глубину такова: идти вглубь пока это возможно (есть непройденные исходящие ребра), возвращатся и искать другой путь когда таких ребер не существует. Если после этого остаются неиспользованные вершины - можно выбрать одну из них и повторять процесс пока остаются необнаруженные вершины.
Найдя впервые вершину v, смежную с u, ми отмечаем это событие, записывая в поле p[v] значение u. Таким образом образуется дерево или несколько деревьев.
Как и поиск в ширину, алгоритм поиска в глубину использует цвета вершин. Сначала все вершины - белые. При обнаружении новой вершины, она красится в серый цвет. Когда вершина полностью обработана, она перекрашивается в черный цвет.
Кроме этого, поиск в глубину ставит на вершинах метки времени. Каждая вершина имеет две метки: d[v] показывает, когда вершина была обнаружена, f[v] - когда обработана. Эти метки впоследствии используются во многих алгоритмах на графах.
Во время выполнения этого алгоритма, обработка каждой вершины происходит ровно один раз. Общее же количество выполнения строк 3 - 6 процедуры DFS-Visit составляет O(E). В итоге сложность данного алгоритма составляет O(V+E), где V - количество вершин в графе, а E - количество ребер.

Алгоритм:
Код:
DFS
1 for (для) всех вершин u
2        do color[u]= БЕЛЫЙ
3          parent[u]= NIL
4 time=0
5 for (для) всех вершин u
6  do if color[u]=БЕЛЫЙ
7  then DFS-Visit[u]

DFS-Visit(u)
1 color[u]=СЕРЫЙ
2 d[u]=time
3 time=time+1
4 for (для) всех v (потомков u)
5      do if color[v]=БЕЛЫЙ
6            then parent[v]=u
7                DFS-Visit(v)
8 color[u]=ЧЕРНЫЙ
9 f[u]=time
10 time=time+1

 Поиск в ширину
Поиск в ширину - один из базовых алгоритмов теории графов. Он является основой для многих других алгоритмов.
Пусть задан граф и фиксированная начальная вершина s. Алгоритм поиска в ширину перечисляет все достижимые из s (если идти по ребрам) вершины в порядке возрастания расстояния от s. В процессе поиска из графа выделяется часть, которая называется деревом поиска в ширину с корнем в s. Она содержит все достижимые из s вершины (и только их).
Для наглядности будем считать, что в процессе работы алгоритма вершины графа могут быть белыми, серыми и черными. Сначала они все белые, а в ходе работы алгоритма белая вершина может стать серую, серая - черной, но не наоборот. Встретив новую вершину, алгоритм поиска красит ее, так что серые и черные вершины - уже обнаруженные вершины.
Сначала дерево поиска в ширину состоит только из начальной вершины s. Как только алгоритм находит новую вершину v, смежную с ранее найденной вершиной u, вершина v вместе с ребром (u,v) добавляется к дереву поиска и становится потомком u. Каждая вершина обнаруживается только один раз, так что двух родителей у вершины быть не может.
Оценивая сложность работы этого алгоритма замечаем, что вершины только темнеют, то есть важдая вершина обрабатывается только один раз, т.е. вычислительная сложность алгоритма O(V+E).
Алгоритм:
Код:
BFS(G,s)

for (для) каждой из  вершин G - {s}
      do p[i]= NIL
        d[i]= MAX
        color[i]= БЕЛЫЙ
color[s]= СЕРЫЙ
d[s]= 0
p[i]= NIL
Q <- {s}
while Q  - не пустое
    do u <- Dequeue(Q)
        for (для) всех v - потомков u
            do color[v]= СЕРЫЙ
                p[v]= u
                d[v]= d[u]+1
        color[u]= ЧЕРНыЙ
Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 02-07-2012 11:43 » 

viwwna, поверь, Слава и Лёша знают, что такое поиск в глубину - они лишь хотели убедиться, что ты это знаешь. А ты пока говоришь это не своими словами, а цитируешь какие-то учебники - что ничуть не подтверждает знание обсуждаемого предмета.
Записан
Viwwna
Интересующийся

ru
Offline Offline

« Ответ #8 : 02-07-2012 11:54 » 

Вад, очередь соответствует поиску в ширину, а стек - в глубину
отличие стека от очереди... и т.п. и т.д. и Что? У меня не в этом вопрос...

Добавлено через 2 минуты и 48 секунд:

   Если своими словами, то  находясь в вершине  x, нужно двигаться в любую другую, ранее не посещенную вершину (если таковая найдется), одновременно запоминая дугу, по которой мы впервые попали в данную вершину;
    если из вершины x мы не можем попасть в ранее не посещенную вершину или таковой вообще нет, то мы возвращаемся в вершину z, из которой впервые попали в x, и продолжаем обход в глубину из вершины z.
« Последнее редактирование: 02-07-2012 11:57 от viwwna » Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 02-07-2012 12:16 » 

viwwna, если вопрос не в этом - тогда в чём? Просьба помочь прозвучала, но не очень понятно, с чем тогда помочь, если понятно, как оно всё устроено. Алгоритм довольно простой, ошибиться почти негде.
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines