Re: Проходження графу в ширину.

Якщо в когось буде час перегляньте будь ласка фунцію matrix (це пошук мінімального шляху алгоритмом Дейкстри). Викладач сказав що я по дурному написав. Але воно працює. Весело получилось...

#include <conio.h>
#include <iostream>
#include <string>
using namespace std;


struct station {  
    station* commonst;
    string namest;
    int way;
};


struct list {
    station* st;
    list* next;
};


station** getname(station*** mainst, int num,int index) {  // Функція поверне адресу вказівника ан станцію з потрібним нам ім ям.
    if (index == 1) {
        cout << "Введіть назву станції із якої Ви хочете почати обхід ліній метро в ширину: ";
    }
    else {
        if (index == 2) {
            cout << "Введіть назву станції із якої Ви хочете почати обхід ліній метро в глибину: ";
        }
    }
    string name;
    cin >> name;
    station** mst = *mainst;
    for (int i = 0; i < num; i++) {
        if (mst[i]->namest == name) {
            return &mst[i];
        }
    }
}


station** search(station*** mainst, int num, station* nm) { // Подібна до попередньої, але не потрібно вводити назву.
    station** mst = *mainst;
    for (int i = 0; i < num; i++) {
        if (mst[i]->namest == nm->namest) {
            return &mst[i];
        }
    }
}

station** searchind(station*** mainst, int num, int ind) { // Ця функція потрібна мені для пошуку мінімального шляху між станціями. Також поверне адресу вказівника але з потрібним мені індексом а не ім ям.
    station** mst = *mainst;
    for (int i = 0; i < num; i++) {
        if (i == ind) {
            return &mst[i];
        }
    }
}

bool add(station* qst, list* main) { // Ця функція потрібна для перевірки в стеку, списку, чи є даний елемент у ньому. (Якщо не має - поверне істину). 
    bool ret = true;
    if (main == nullptr) {
        return true;
    }
    else {


        if (main->next == nullptr) {
            if (qst->namest == main->st->namest) {
                return false;
            }
            else {
                return true;
            }
        }
        else {
            while (main!= nullptr) {
                if (qst->namest == main->st->namest) {
                    return false;
                }
                else {
                    main = main->next;
                    ret = true;
                }
            }
            if (ret == true) {
                return true;
            }
        }
    }
}


void mlist(list** main,station*stt) { // Функція для створення списку.
    if ((*main) == nullptr) {
        (*main) = new list;
        (*main)->st = (stt);
        (*main)->next = nullptr;
    }
    else {
        list* last = (*main);
        while (last->next!= nullptr) {
            last = last->next;
        }
        last->next = new list;
        last = last->next;
        last->st = (stt);
        last->next = nullptr;
    }
}


void qlist(list** queue, station* stt) { // Функції для створення стеку.
    if ((*queue) == nullptr) {
        (*queue) = new list;
        (*queue)->st = (stt);
        (*queue)->next = nullptr;
    }
    else {
        list* last = (*queue);
        while (last->next != nullptr) {
            last = last->next;
        }
        last->next = new list;
        last = last->next;
        last->st = (stt);
        last->next = nullptr;
    }
} 
void slist(list** stack, station* stt) {
    if ((*stack) == nullptr) {
        (*stack) = new list;
        (*stack)->st = (stt);
        (*stack)->next = nullptr;
    }
    else {
        list* stacklist = new list;
        stacklist->st = stt;
        stacklist->next = (*stack);
        (*stack) = stacklist;
    
    }
}


void width(list** queue, list** main, station*** mainst, int num) { // Функція для проходження графу в ширину .
    station* sst = *getname(mainst, num,1);
    
        (*queue) = new list;
        (*queue)->st = sst;
        (*queue)->next = nullptr;
        while ((*queue)) {
            station* addd = *search(mainst, num, (*queue)->st); // Доступ до вказівника з спільними вершинами.
            bool addmlist = add(addd, (*main)); 
            if (addmlist == true) { // Перевіряємо чи є елемент у списку
                mlist(main, addd);
                addd = addd->commonst;
            }
            
            while (addd != nullptr) {
                
                bool addqlist = add(addd, (*main));
                
                if (addqlist == true) {// Перевіряємо чи є елемент у стеку.
                    qlist(queue, addd);
                }
                addd = addd->commonst;
            }
            (*queue) = (*queue)->next;
        }
    
}


void depth(list** stack, list** main, station*** mainst, int num) { // Ця фунцыя працює практично як попередня.
    station* sst = *getname(mainst, num, 2);
    (*stack) = new list;
    (*stack)->st = sst;
    (*stack)->next = nullptr; {
        while ((*stack)) {
        station* addd = *search(mainst, num, (*stack)->st);
            bool addmlist = add(addd, (*main));
            if (addmlist == true) {
                mlist(main, addd);
                addd = addd->commonst;
                (*stack) = (*stack)->next;
            }

            while (addd) {

                bool addqlist = add(addd, (*main));

                if (addqlist == true) {
                    slist((stack), addd);
                }
                addd = addd->commonst;
            }
            
        }
    }
    
}


void printlist(list* main) { // Вивід всіх елементів списку.
    list* plist = main;
    cout << "||";
    while (plist) {
        cout << "->";
        cout << plist->st->namest;
        plist = plist->next;
    }
    cout << "||";
    
}


void print(station** mainst, int num) {  // Вивід всіх естінцій (без доступу до суміжніх їм).
    for (int i = 0; i < num; i++) {
        cout << "Назва " << i + 1 << "-ої станції метро: " << mainst[i]->namest << endl;
    }
}


void cincommonst(station*** mainst, int num) { // Ввід суміжніх вершин для кожної станції.
    for (int i = 0; i < num; i++) {
        cout << "Введіть к-сть суміжніх пересадок для станції " << (*mainst)[i]->namest << ": ";
        int numm;
        cin >> numm;
        station* newst = (*mainst)[i];
        for (int q = 0; q < numm; q++) {
            cout << "Введіть назву " << q + 1 << "-ої пересадки із станції: " << (*mainst)[i]->namest << ": ";
            if (newst->commonst == nullptr) {
                (newst)->commonst = new station;
                (newst) = (newst)->commonst;
                cin >> (newst)->namest;
                cout << "Введіть довжину  " << q + 1 << "-ої пересадки із станції: " << (*mainst)[i]->namest << ": ";
                cin >> (newst)->way;
                newst->commonst = nullptr;
            }
            else {
                while (newst->commonst) {
                    newst = newst->commonst;
                }
                (newst)->commonst = new station;
                (newst) = (newst)->commonst;
                cin >> (newst)->namest;
                cout << "Введіть довжину  " << q + 1 << "-ої пересадки із станції: " << (*mainst)[i]->namest << ": ";
                cin >> (newst)->way;
                newst->commonst = nullptr;
            }
        }
        cout << endl;
    }
}


void printcommonst(station** mainst, int num) { // Вивід усіх вершин.

    for (int i = 0; i < num; i++) {
        station* printst = mainst[i];
        while (printst->commonst) {
            printst = printst->commonst;
            cout << "Із станції " << mainst[i]->namest << " можна патрапити у станцію " << printst->namest << " із довжиною шляху: " << printst->way << " км." << endl;

        }
        cout << endl;
    }
}

int find(station*** sst, int num, string nm) { // Ця функція потрыбна мені для повернення індексу потрібної мені станції (використовую в пошуку мін. шляху).
    station** st = (*sst);
    int index = 0;
    for (int i = 0; i < num; i++) {
        if (st[i]->namest == nm) {
            index = i;
        }
        
    }
    return index;
}



void waymatrix(station*** main, int num) { // Можливо можна і простіше якось написати...
    int** matrix = nullptr;
    matrix = new int* [num];
    for (int i = 0; i < num; i++) { // Створюю матрицю та заповнюю її значеннями 99.
        matrix[i] = new int[num];
    }

    for (int i = 0; i < num; i++) {
        for (int j = 0; j < num; j++) {
            matrix[i][j] = 99;
        }
    }
    string name; 
    cout << "Введіть назву станції із якої Ви хочете найти мінімальні шляхи до пересадок: ";
    cin >> name;
    int index = find(main, num, name);
    for (int i = 0; i < num; i++) { // Обераю вершину до якої відстань 0 і позначаю її 66  ( весь стовпець)ахах... Я не знаю як мені описати цю функцію... Але вона працює.
        matrix[i][index] = 66;
    }
    int minindex = index;
    int sumway = 0;
    station* sst = nullptr;
    for (int i = 0; i < num; i++) {
        int minway = 100;
        sst = *searchind(main, num, minindex);
        
        
        while ((sst)) {
            index = find(main, num, (sst)->namest);
            
            if (matrix[i][index] != 66) {
                matrix[i][index] = sumway + (sst)->way;
                (sst) = (sst)->commonst;
            }
            else {
                (sst) = (sst)->commonst;
            }
        }

        for(int j = 0; j <num; j++){
            if (matrix[i][j] < minway) {
                minway = matrix[i][j];
                minindex = j;
                sumway = minway;
            }
            
        }
        cout << minindex << " " << sumway << endl;
        
        for (int a =i; a < num; a++) {
            if ((a+1) < num) {
                matrix[a+1][minindex] = 66;
            }
        }
    }
    for (int i = 0; i < num; i++) {
        for (int j = 0; j < num; j++) {
            cout << matrix[i][j] << " ";
        }
        cout << endl;
    }

}




int main(void) {
    setlocale(LC_ALL, "Ukr");
    station** mainst = nullptr;
    list* mainlist = nullptr;
    list* queue = nullptr;
    list* mainlist2 = nullptr;
    list* stack = nullptr;
    int num;
    cout << "Введіть к-сть станцій: ";
    cin >> num;
    mainst = new station * [num];
    for (int i = 0; i < num; i++) {
        cout << "Введіть назву " << i + 1 << "-ої станції метро: ";
        mainst[i] = new station;
        string name;
        cin >> name;
        mainst[i]->namest = name;
        mainst[i]->commonst = nullptr;
        mainst[i]->way = NULL;
    }
    print(mainst, num);

    cincommonst(&mainst, num);

    printcommonst(mainst, num);


    depth(&stack, &mainlist2, &mainst, num);

    printlist(mainlist2);

    cout << endl;
    
    width(&queue, &mainlist, &mainst, num);

    printlist(mainlist);
    
    cout << endl;

    waymatrix(&mainst, num);

    _getch();
    return 0;
}

Re: Проходження графу в ширину.

Коментраі ніколи не писав... Скоріш за все вони тупі. Але вона сказала щось написати.

23

Re: Проходження графу в ширину.

чомуБвамНеСпробуватиCamelCaseВіменахФункційТаЗмінних

Подякували: leofun01, plusxx2

Re: Проходження графу в ширину.

Я не зрозумів що Ви написали

25

Re: Проходження графу в ширину.

Львовский сырник в мульти написав:

Я не зрозумів що Ви написали

CamelCase

Re: Проходження графу в ширину.

Весело запитав по чому банани відповіли гарна погода...

27

Re: Проходження графу в ширину.

Не заглиблюючися в алгоритм...

        sst = *searchind(main, num, minindex);
        
        
        while ((sst)) {
            index = find(main, num, (sst)->namest);
            
            if (matrix[i][index] != 66) {
                matrix[i][index] = sumway + (sst)->way;
                (sst) = (sst)->commonst;
            }
            else {
                (sst) = (sst)->commonst;
            }
        }

В if та else останні рядки однакові. Виносимо:

        sst = *searchind(main, num, minindex);        
        while ((sst)) {
            index = find(main, num, (sst)->namest);            
            if (matrix[i][index] != 66) {
                matrix[i][index] = sumway + (sst)->way;
            }
            else {
            }
            (sst) = (sst)->commonst;
        }

else не потрібен, як і дужки навколо sst.

        sst = *searchind(main, num, minindex);
        
        
        while ((sst)) {
            index = find(main, num, (sst)->namest);
            
            if (matrix[i][index] != 66) {
                matrix[i][index] = sumway + (sst)->way;
                (sst) = (sst)->commonst;
            }
            else {
                (sst) = (sst)->commonst;
            }
        }

В if та else останні рядки однакові. Виносимо і прибираємо зайві фігурні дужки:

        sst = *searchind(main, num, minindex);        
        while (sst) {
            index = find(main, num, sst->namest);            
            if (matrix[i][index] != 66)
                matrix[i][index] = sumway + sst->way;
            sst = sst->commonst;
        }

А це насправді for, тільки не до числа, а поки sst не nullptr:

        for(sst = *searchind(main, num, minindex); sst; sst = sst->commonst) {
            index = find(main, num, sst->namest);            
            if (matrix[i][index] != 66)
                matrix[i][index] = sumway + sst->way;
        }

Просто прибрав зайві рядки.

28

Re: Проходження графу в ширину.

Функція searchind - це ви перемудрили. Ні, функцію можна залишити, зі складними вказівниками часто так зручніше, але ж індекс не зберігається в масиві. І в результаті ви порівнюєте i з ind, коли вам точно відоме потрібне значення i.

station** searchind(station*** mainst, int num, int ind) { 
    station** mst = *mainst;
    return &mst[ind];
}

Єдина відмінність з вашою функцією - якщо ind>=num, ваша функція поверне сміття зі стеку, а моя - з пам'яті після mst. UB буде і там, і там.

Re: Проходження графу в ширину.

дякую

30

Re: Проходження графу в ширину.

А ще search(mainst, num, st)  працює майже так само, як find(mainst, num, st->namest). Відмінність у способі передачі назви. Якщо в find передавати посилання на стрічку, то search буде непотрібним. І в getname можна викликати find (а ще краще - прибрати getname, явно вводити стрічку і передавати її в find).

Re: Проходження графу в ширину.

koala написав:

Функція searchind - це ви перемудрили. Ні, функцію можна залишити, зі складними вказівниками часто так зручніше, але ж індекс не зберігається в масиві. І в результаті ви порівнюєте i з ind, коли вам точно відоме потрібне значення i.

station** searchind(station*** mainst, int num, int ind) { 
    station** mst = *mainst;
    return &mst[ind];
}

Єдина відмінність з вашою функцією - якщо ind>=num, ваша функція поверне сміття зі стеку, а моя - з пам'яті після mst. UB буде і там, і там.

Тільки замітив. Не спорю, дурню написав. Просто довго сидів над завданням  і не замітив.