Advertisement
Guest User

Untitled

a guest
Sep 23rd, 2017
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 12.34 KB | None | 0 0
  1. using System;
  2. using System.IO;
  3. using System.Collections.Generic;
  4.  
  5. namespace Ulyanov_220917new_graphClass
  6. {
  7.     /** Класс Graph реализует математический объект "граф", задаваемый списком смежности,
  8.      * хранящим ориентированные ребра т.е. являющийся ориентированным графом.
  9.      */
  10.     class Graph
  11.     {
  12.         /** Список vertexes_ вершин экземпляра графа хранит информацию о каждой вершине
  13.          * и исходящих из неё дугах (ориентированных ребрах).
  14.          * Это единственное поле класса.
  15.          */
  16.         private List<Node> vertexes_;
  17.  
  18.         /** Вложенный класс Node реализует единичный элемент списка vertexes_,
  19.          * описывающий одну вершину графа.
  20.          * Публичное поле name хранит название вершины, закрытый список вершин neighbours_
  21.          * содержит названия вершин, к которым исходят дуги из данной вершины.
  22.          */
  23.         class Node
  24.         {
  25.             public string name;
  26.             private List<string> neighbours_;
  27.  
  28.             /** Публичный конструктор Node(string) принимает строку вида:
  29.              * a:b,c
  30.              * где a это название новой вершины, b и c - названия всех вершин, к которым
  31.              * от неё исходят дуги (вершин-"соседей").
  32.              */
  33.             public Node(string parse)
  34.             {
  35.                 char[] delims =
  36.                 {
  37.                     ':',
  38.                     ','
  39.                 };
  40.                 string[] parseResult = parse.Split(delims);
  41.                 name = parseResult[0];
  42.                 neighbours_ = new List<string>();
  43.                 for(int i = 1; i < parseResult.Length; i++)
  44.                 {
  45.                     neighbours_.Add(parseResult[i]);
  46.                 }
  47.                
  48.             }          
  49.  
  50.             /** Публичный метод print() выводит название вершины и всех исходящих из неё дуг
  51.              * на экран.
  52.              */
  53.             public void print()
  54.             {
  55.                 if(neighbours_.Count == 0)
  56.                 {
  57.                     Console.WriteLine("- Вершина {0} не имеет исходящих дуг.", name);
  58.                     return;
  59.                 }
  60.  
  61.                 Console.WriteLine("- Вершина {0}:", name);
  62.                 Console.WriteLine("Исходящие дуги:");
  63.                 foreach(var i in neighbours_)
  64.                 {
  65.                     Console.WriteLine("{0} -> {1}", name, i);
  66.                 }
  67.             }
  68.  
  69.             /** Метод addEdge(string) добавляет в список вершин-"соседей" вершину
  70.              * с заданным именем, т.е. создает новую дугу, исходящую из this
  71.              * в new Edge.
  72.              */
  73.             public void addEdge(string newEdge)
  74.             {
  75.                 neighbours_.Add(newEdge);
  76.             }
  77.  
  78.             /** Метод deleteEdge(string) удаляет из списка вершин-"соседей" this
  79.              * все вхождения deletedEdge, т.е. удаляет все дуги, исходящие из this
  80.              * в deletedEdge.
  81.              */
  82.             public void deleteEdge(string deletedEdge)
  83.             {
  84.                 while (neighbours_.Remove(deletedEdge)) ;
  85.             }
  86.  
  87.             /** Метод findLoop() выполняет роль функции-предиката,
  88.              * возвращающей true в случае если вершина содержит себя в списке
  89.              * вершин-"соседей", то есть в случае если вершина имеет петлю,
  90.              * и false в случае если вершина не имеет петель.
  91.              * Метод используется при поиске петель в графе, его вызов производится
  92.              * для каждой вершины в графе (для каждого элемента списка vertexes_).
  93.              */
  94.             public bool findLoop()
  95.             {
  96.                 foreach(var i in neighbours_)
  97.                 {
  98.                     if(name == i)
  99.                     {
  100.                         return true;
  101.                     }
  102.                 }
  103.                 return false;
  104.             }
  105.         } /** Конец реализации класса вершины Node */
  106.  
  107.         /** Публичный конструктор класса Graph() создает "пустой" граф -
  108.          * граф, не имеющий ни вершин, ни дуг, инициализируя поле vertexes_ пустым списком вершин.
  109.          */
  110.         public Graph()
  111.         {
  112.             vertexes_ = new List<Node>();
  113.         }
  114.  
  115.         /** Публичный конструктор класса Graph(string) создает граф,
  116.          * заданный файлом filename.
  117.          * Файл имеет вид:
  118.          * a:b,c
  119.          * b:c,a
  120.          * c:a,b
  121.          * где a, b и с - вершины графа, а запись вида
  122.          * a:b,c
  123.          * означает что вершина a имеет две исходящие дуги: одна из a к b, другая из a к c.
  124.          */
  125.         public Graph(string filename)
  126.         {
  127.             vertexes_ = new List<Node>();
  128.             StreamReader fileReader = new StreamReader(filename);
  129.             string stringBuff;
  130.             while( (stringBuff = fileReader.ReadLine()) != null )
  131.             {
  132.                 addNode(stringBuff);
  133.             }
  134.         }
  135.  
  136.         /** Публичный конструктор Graph(Graph) реализует глубокое копирование
  137.          * уже имеющегося объекта графа для независимого (не изменяющего состояние оригинала)
  138.          * выполнения операций над копией.
  139.          */
  140.         public Graph(Graph source)
  141.         {
  142.             vertexes_ = new List<Node>();
  143.             foreach(var i in source.vertexes_)
  144.             {
  145.                 vertexes_.Add(i);
  146.             }
  147.         }
  148.  
  149.         /** Метод класса Graph addNode(string) добавляет в список вершин новую, принимая строку из файла,
  150.          * описывающего граф, или строку того же формата
  151.          * ([вершина-источник дуги]:[вершина-приемник],[вершина-приемник]).
  152.          */
  153.         public void addNode(string parse)
  154.         {
  155.             vertexes_.Add(new Node(parse));
  156.         }
  157.  
  158.         /** Метод класса Graph deleteNode(string) удаляет из списка вершин
  159.          * вершину с заданным именем nodeName, а также все её упоминания в списках вершин-"соседей"
  160.          * остальных вершин.
  161.          */
  162.         public void deleteNode(string nodeName)
  163.         {
  164.             for(var i = 0; i < vertexes_.Count; i++)
  165.             {
  166.                 if(nodeName == vertexes_[i].name)
  167.                 {
  168.                     /** При удалении вершины с заданным именем длина списка уменьшается на 1,
  169.                      * и счетчик i указывает теперь на следующий, необработанный по условию if
  170.                      * элемент списка. Счетчик декрементируется после завершения работы
  171.                      * метода Remove, чтобы не пропустить удаление упоминаний искомой вершины во
  172.                      * впередистоящем элементе списка.
  173.                      */
  174.                     vertexes_.Remove(vertexes_[i--]);
  175.                 }
  176.                 else
  177.                 {
  178.                     vertexes_[i].deleteEdge(nodeName);
  179.                 }
  180.                
  181.             }
  182.         }
  183.  
  184.         /** Метод класса Graph addEdge(string, string) добавляет в число вершин-"соседей"
  185.          * вершины sourceNode вершину destinationNode, т.е. создаёт дугу из вершины sourceNode
  186.          * в вершину destinationNode.
  187.          */
  188.         public void addEdge(string sourceNode, string destinationNode)
  189.         {
  190.             /** Для поиска вершины-"источника" (вершины, из которой исходит создаваемая дуга)
  191.              * применяется предикат "element => element.name == sourceNode",
  192.              * применяемый методом Find ко всем элементам списка vertexes_ и
  193.              * метод Node.addEdge вызывается только для той вершины, которая имеет
  194.              * название sourceNode.
  195.              */
  196.             vertexes_.Find(element => element.name == sourceNode).addEdge(destinationNode);
  197.         }
  198.  
  199.         /** Метод класса Graph deleteEdge(string, string) удаляет все имеющиеся в графе
  200.          * дуги с началом в вершине sourceNode и концом в вершине destinationNode.
  201.          */
  202.         public void deleteEdge(string sourceNode, string destinationNode)
  203.         {
  204.             vertexes_.Find(element => element.name == sourceNode).deleteEdge(destinationNode);
  205.         }
  206.  
  207.         /** Метод класса Graph print() выводит информацию обо всех вершинах
  208.          * (название и список вершин-"соседей") на экран.
  209.          */
  210.         public void print()
  211.         {
  212.             Console.WriteLine("Ориентированный граф:");
  213.             foreach(var i in vertexes_)
  214.             {
  215.                 i.print();
  216.             }
  217.             Console.WriteLine();
  218.         }
  219.  
  220.         /** Метод класса Graph printLoopVertexes() выполняет поиск дуг в графе,
  221.          * у которых вершина-"источник" и вершина-"приемник" совпадают,
  222.          * и выводит их названия на экран.
  223.          */
  224.         public void printLoopVertexes()
  225.         {
  226.             Console.WriteLine("Поиск петель в ориентированном графе...");
  227.             bool anyLoopsFound = false;
  228.             foreach (var i in vertexes_)
  229.             {
  230.                 if( i.findLoop() )
  231.                 {
  232.                     Console.WriteLine("Вершина {0} имеет одну или несколько петель.", i.name);
  233.                     anyLoopsFound = true;
  234.                 }
  235.             }
  236.  
  237.             if(!anyLoopsFound)
  238.             {
  239.                 Console.WriteLine("Граф не содержит петель.");
  240.             }
  241.             Console.WriteLine();
  242.         }
  243.  
  244.     }
  245.  
  246.     class Program
  247.     {
  248.         static void Main(string[] args)
  249.         {
  250.             Graph myGraph = new Graph("input1.txt");
  251.             myGraph.print();
  252.             myGraph.printLoopVertexes();
  253.  
  254.             myGraph.deleteNode("a");
  255.             myGraph.print();
  256.             myGraph.printLoopVertexes();
  257.  
  258.             Graph secondGraph = new Graph(myGraph);
  259.             myGraph.deleteEdge("b", "b");
  260.             myGraph.deleteEdge("b", "c");
  261.             myGraph.print();
  262.             myGraph.printLoopVertexes();
  263.  
  264.             Console.WriteLine("Нажмите любую клавишу...");
  265.             Console.ReadKey();
  266.         }
  267.     }
  268. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement