Как найти минимальное остовное дерево с заданным набором координат из входного файла с помощью алгоритма Прима?

Хорошо, ребята, я не видел этого нигде в Интернете, и я пытался понять это в течение нескольких дней. Как я могу найти MST набора координат из входного файла, используя алгоритм Прима. Есть несколько вещей о том, как это сделать, но если следовать им и быть новичком в C++, они не очень помогут. Может ли кто-нибудь показать мне КОД (желательно) о том, как решить эту проблему?

Предположим, у меня есть набор координат во входном файле "Something.txt", содержащий:
(N количество узлов/вершин)
(x Coord), (y coord)
и т.д...

Eg:

9
50 100
100 150
200 150
300 150
350 100
300 50
200 50
100 50
150 100

Учитывая, что эти точки уже нанесены на график, как будет написан алгоритм Прима? Я понимаю, что это много, но сейчас я совершенно не понимаю, как новичок в C++. (и да, я пытался вырезать код, я пытался смотреть на другие примеры и крутить их, чтобы заставить его работать, я пробовал почти все, кроме того, что видел, как это делается, чтобы я мог лучше понять, что я продолжай отсутствовать.)

Заранее спасибо.

Редактировать: код, отображающий точки через pygraphics, используя входной файл аргумента .txt, который вы передаете ему, который затем переходит в файл .dat, который затем публикуется через предварительно созданный файл построения:

class Point
{

    public:

        // Constructor.
        Point()
        {
            x = 0; y = 0;  
        } // end constructor
        Point(int a, int b, int id)
        {
            x = a; y = b; pointID = id;
        } // end constructor

        int getX() { return x; }
        int getY() { return y; }
        int getID() { return pointID; }
        string data;

        Point(string x)
        {
            data = x;
        }

    private:
        int x = 0; 
        int y = 0;
        int v;
        int xVert;
        int yVert;
        int pointID = 0;

        list<Point*> pointList;
        list<Point*> neighbors;
        //vector<Neighbor> myNeighborvector;

        //locate point containg value x
        Point * findPoint(string x)
        {
            for(Point * v : pointList)
            {
                if (v->data == x)
                    return v;
            }
            return NULL;
        }

        //add Neighbor going from x to y
        void addDirectedNeighbor(string x, string y)
        {
            Point * xVert = findPoint(x);
            Point * yVert = findPoint(y);

            xVert->neighbors.push_back(yVert); //I would think that this should only add y to x's neighbors, but when I try to display I  get x as one of y's neighbors
        }

        void addNeighbor(string x, string y)
        {
            addDirectedNeighbor(x, y);
            addDirectedNeighbor(y, x);
        }

}; // end class Point


//--------------------------------------------------------------------------
class Edge
{

    public:

        // Constructor.
        Edge()
        {

        } // end constructor
        Edge(Point ptA, Point ptB)
        {
            pointA = ptA;
            pointB = ptB;
            length = sqrt(pow(abs(pointA.getX() - pointB.getX() ), 2) + pow(abs(pointA.getY() - pointB.getY() ), 2) );
        } // end constructor

        Point getPtA() { return pointA; }
        Point getPtB() { return pointB; }
        double getLen() { return length; }
        int getPtAID() { return pointA.getID(); }
        int getPtBID() { return pointB.getID(); }

    private:
        Point pointA;
        Point pointB;
        double length;

}; // end class Edge

//--------------------------------------------------------------------------
/*class Neighbor
{

    public:

        // Constructor.
        Neighbor()
        {
            length = sqrt(pow(abs(pointA.getX() - pointB.getX() ), 2) + pow(abs(pointA.getY() - pointB.getY() ), 2) );
        } // end constructor

        double getLen() { return length; }

    private:
        double length;
        int pointID = 0;

};*/ // end class Neighbor

vector<Point> myPointvector;  // vector will expand as needed
vector<Edge> MinSpanTree;

int main (int argc, char *argv[])
{
    ifstream fin;
    int coordPairs;  // number of coordinate pairs in the file
    int ptX, ptY;

    int loopCounter;
    int pointCounter = 0;
    double MSTLength = 0.0;


    // Check the number of arguments. Expected: filename of a file
    if (argc != 2)  // This check is often hardcoded
    {   // If failure in parameters, offer advice for correction
        cout << "\nThis program uses command-line argument.\n";
        cout << "Usage: a.exe <filename>\n";
        exit(0);
    }



    try  // All lines within this block are part of the same exception handler
    {
        fin.open(argv[1]);
    } 
    catch (exception& ex) 
    {
        cout << ex.what();  // display standard explanation of the exception
        exit(0);  // exit the program
    }


    // Read from the file, one token at a time. If the type of token is known, it
    // can be read into a corresponding variable type, such as 
    //          in >> x;    // Read the first item into an integer variable x.
    //          in >> str;  // Read the next item into a string variable str.


    // This line provides the graphic window setup. 
    cout << "800 600 white" << endl;

    fin >> coordPairs;
    cout << coordPairs << endl;
    while (fin >> ptX)
    {
        // Do something with the element read from the file
        // cout << ptX << endl;
        fin >> ptY;   
        // cout << ptY << endl;

        cout << "circle " << ptX << " " << ptY << " " << 20 << " seagreen" << endl;


        Point dummyPoint(ptX, ptY, pointCounter++);
        myPointvector.push_back(dummyPoint);  // vector will expand as needed

        cout << "Now myPointvector has size " << myPointvector.size() << endl;


    } // end while

    fin.close();

    return 0;
}

person RivG    schedule 04.02.2016    source источник
comment
Вы новичок в программировании в целом? А вы понимаете алгоритм Прима?   -  person Beta    schedule 04.02.2016
comment
Не новичок в программировании. Я много программировал на Python и таких вещах, как Javascript, HTML и CSS. Я просто новичок в С++ в целом. Немного поработал с ним и классами и т.д. Но я с ними не очень хорошо разбираюсь и меня это иногда сбивает с толку. Обычно я могу читать код и хорошо его понимаю. Но когда дело доходит до того, чтобы начать что-то или найти начало решения, я ужасен. Я понимаю все, что касается алгоритма Прима, просто ничего не могу сделать, используя этот входной файл только с координатами. Большая часть Google использует определенный тип веса. Это расстояние от Pt до Pt.   -  person RivG    schedule 04.02.2016
comment
Stack Overflow — это не сайт, на котором вы можете заставить людей писать для вас код. Это твоя работа. Если у вас есть конкретный вопрос, отличный от вопроса «Как мне написать эту программу?», задайте его.   -  person user253751    schedule 04.02.2016
comment
Это должен был быть мой следующий вопрос; Алгоритм Прима имеет дело со взвешенными графами, а не только с наборами вершин, так что чего-то не хватает. Возможно вы должны принять полный граф с евклидовым расстоянием в качестве веса, но вам придется поговорить с человеком, который дал вам эту задачу, чтобы быть уверенным.   -  person Beta    schedule 04.02.2016
comment
О да. Я забыл упомянуть об этом. Я ЕСМЬ должен предположить полный граф. И да. Расстояние, а не вес.   -  person RivG    schedule 04.02.2016
comment
Хорошо, есть какие-то требования по сложности?   -  person Beta    schedule 04.02.2016
comment
Не совсем. Было бы неплохо, если бы он использовал классы (возможно, векторы?), потому что это, вероятно, лучший способ узнать, что происходит для меня на моем уровне. Когда я упоминаю, что точки уже нанесены, я имею в виду, что я уже написал код для извлечения координат из входного файла и размещения их на холсте, сделанном pygraphics. Я могу отредактировать вопрос с кодом, который делает это, если это необходимо. Но задействована pygraphics, но я не думаю, что это было бы ужасно реализовать. Спасибо, кстати.   -  person RivG    schedule 04.02.2016
comment
Итак, я думаю, вы можете сказать, что самая крутая часть заключается в том, что все это будет проталкиваться через python, поэтому у вас есть визуальное представление всех точек и создаваемого MST. Довольно круто.   -  person RivG    schedule 04.02.2016
comment
У вас есть выбор структур данных. Вы должны хранить два набора вершин, а также где-то хранить расстояния. У вас может быть простая таблица расстояний и два набора целых чисел для представления вершин (с дополнительным списком вершин для использования при расчете таблицы) или класс Vertex, каждый из которых содержит две координаты (x,y) и набор соседи (каждый из которых состоит из идентификационного номера и расстояния). Набор вещей может храниться в контейнере, таком как массив или std::vector.   -  person Beta    schedule 04.02.2016
comment
Класс Vertex кажется более подходящим для этого подхода. Держит вещи на моем уровне, как хорошо!   -  person RivG    schedule 04.02.2016
comment
Хорошо, попробуйте написать класс Vertex, который хранит x, y и идентификационный номер. И функция, которая берет две вершины и возвращает расстояние между ними. Кроме того, немного поиграйте с std::vector, добавляя элементы, удаляя элементы, перебирая вектор.   -  person Beta    schedule 04.02.2016
comment
Не могли бы вы предоставить какой-нибудь код sudo для этого?   -  person RivG    schedule 04.02.2016
comment
Если вы хотите научиться писать на C++, вы должны сделать эти небольшие шаги самостоятельно; когда у вас есть Vertex и вы освоите основы std::vector, мы можем работать над построением деревьев. Или, если вы хотите, чтобы я написал все для вас, я беру 100 долларов в час.   -  person Beta    schedule 04.02.2016
comment
Я уже создал что-то вроде класса для Point(vertex). Хотя не уверен, что это правильно или что-то в этом роде. Я работал с Vectors раньше, так что у меня есть довольно хорошее представление об этом. Я обновил вопрос с классом и добавил остальную часть кода для функции main(). Если хотите, мы можем перенести это на обсуждение. Не уверен, что правила здесь, но я знаю, что им не нравится много комментариев.   -  person RivG    schedule 04.02.2016
comment
Псевдокод (не код sudo) — это просто человеческий язык, описывающий, что делать, как язык программирования с максимально широким синтаксисом. Если вы не знаете, что делать (что я должен предположить из вашей просьбы о том, чтобы кто-то написал для вас псевдокод), я бы посоветовал вам прочитать несколько руководств и поработать с их упражнениями. Серьезно, до сих пор у вас почти ничего не было, кроме шаблона, который выглядит очень знакомым и который, я думаю, вы написали не сами, верно? Это ужасный код, кстати, вы должны потребовать возмещение.   -  person Ulrich Eckhardt    schedule 04.02.2016


Ответы (1)


Это займет несколько итераций.

У вас есть Point и векторы. Теперь напишите функцию для вычисления расстояния между двумя точками и функцию для чтения файла данных и создания вектора точек. Кроме того, напишите класс Neighbor, который содержит идентификационный номер и расстояние, и дайте Point элемент данных, который является вектором Neighbor.

Затем дайте Point несколько функций-членов: 1) добавьте соседа, 2) удалите соседа (указывается идентификатором) и 3) верните копию ближайшего соседа точки.

Как только это будет сделано, попробуйте извлечь одну точку A из вектора, затем перебрать оставшийся вектор, по очереди вычислить расстояние от A до каждой другой точки и построить Коллекция соседей А.

Поместите комментарий к этому ответу, когда все это работает.

РЕДАКТИРОВАТЬ 1:
Это многообещающее начало, но крайне важно, чтобы каждая итерация кода была правильной. Он не должен делать все (или изначально ничего), но он должен 1) компилироваться и 2) работать без сбоев. Этот код не компилируется. В Neighbor() вы ссылаетесь на pointA и pointB, не объявляя их; они должны быть аргументами конструктора. В Point вы ссылаетесь на vertex, findVertex, xvert и neighbors, ни один из которых не определен и даже не объявлен. (Класс Edge интересен, но непонятно, как вы собираетесь его использовать.)

Укрепите классы Point и Neighbor (или откажитесь от Neighbor в пользу Edge), чтобы они могли компилироваться и работать, даже если они не делают многого. Я проверю через несколько часов.

РЕДАКТИРОВАТЬ 2:
В последней версии кода есть несколько функций, которые могут оказаться ненужными, но мы посмотрим.

Идея состоит в том, чтобы построить дерево, так как же это будет работать с этими классами? Попробуйте написать небольшую тестовую функцию, которая создает три точки (с жестко закодированными значениями) и собирает их в дерево. Как только это сработает, подумайте, как бы вы применили алгоритм Прима к этим трем точкам.

person Beta    schedule 04.02.2016
comment
Хорошо, я обновил код, добавив часть информации, которую вы хотели, чтобы я собрал. Некоторые вещи я действительно не знал, как делать. Например, удаление соседа и копирование соседа. Это то, что я получил. Это хотя бы отдаленно выглядит правильно? Возможно, какой-то черновик, на который вы можете взглянуть? Спасибо. - person RivG; 04.02.2016
comment
Хорошо, что касается моего конца, обновление кода, которое я только что опубликовал, полностью компилируется. Я последовал вашему совету и прокомментировал Сосед, так что, возможно, что-то упустил. Как это выглядит? - person RivG; 04.02.2016
comment
Что дальше по списку? - person RivG; 04.02.2016
comment
Нужно ли соединять эти точки? Я имею в виду, что у меня уже есть точки, построенные из входного файла, я не уверен, как создать эти точки с жестко заданными координатами. Разве мы не можем просто применить алгоритм Примса к уже нанесенным точкам? Или не могли бы вы помочь с этими пунктами? - person RivG; 05.02.2016
comment
Я тоже пойду и отмечу это как ответ. - person RivG; 05.02.2016
comment
Мое предложение было простым упражнением в построении дерева, но если вы готовы применить предложения Прим к реальным точкам, вперед. Если это работает, все готово; если у вас есть проблемы, вернитесь к простому упражнению, и если вы не знаете, как жестко закодировать три точки, попробуйте жестко закодировать одну: просто объявите точку в main (или в любой другой тестовой функции) и сконструируйте ее. с жестко заданными значениями. - person Beta; 05.02.2016
comment
Хорошо, спасибо за помощь. Я ценю кого-то, кто может провести меня через что-то и действительно предложить помощь, а не просто жаловаться, что я борюсь и не могу помочь. Я возьму форму здесь! - person RivG; 05.02.2016