2
\$\begingroup\$

I recently started to learn Qt framework and decided to create an app to visualize the sorting algorithms(for this moment there are 5 sorting algorithms). I just want to know if I'm doing everything correctly. Here is a code of visualization function where all of the processes takes place. The visualization class is connected with a signals from "algorithm" class to know about columns swaps, sorts done and array accesses. (65 lines of code)

    #ifndef WIDGET_H
    #define WIDGET_H

    #include <QWidget>
    #include <QtWidgets>

    #include "algorithms.h"

    namespace Ui {
    class Widget;
    }

    class Thread;

    class Widget : public QWidget
    {
        Q_OBJECT

    public:
        explicit Widget(QWidget *parent = nullptr);
        ~Widget();

    private slots:
        void on_sortButton_clicked();
        void on_algorithmSelection_itemClicked(QListWidgetItem*);
        void on_amountChanger_valueChanged(int);
        void on_delayChanger_valueChanged(int);

        void on_comparision(int, int);
        void sortButtonStatus(int);
        void sortDone(int);
        void resetColumns(int, int);

    private:
        Ui::Widget *ui;
        Thread *mThread;
        QGraphicsScene *scene;

        //setting up columns, shuffeling them
        void columnsSetUp(int, int);
        void threadUpdate(int, int);

        std::vector<QGraphicsRectItem*> columns;
        std::vector<double> columnsHeight;

        QMap<int, QString> AlgorithmList;

        //delay of sorting in ms
        int sortDelay;

        double columnsWidth;
        double sceneHeight;
        double sceneWidth;

        int amountOfColumns;
        int comparisions;

        //key which is use to establish the algorithm to sort columns
        int algorithmKey;

        // (-1) - App started, 0 - App ready to sort, (1) - App sorting, (2) - App sorted
        int appStates;
    };

    #endif // WIDGET_H

visualization.cpp (235 lines of code)

    #include "includes/visualization.h"
    #include "ui_widget.h"

    #include <random>
    #include <algorithm>

    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);

        //setting up scene
        scene = new QGraphicsScene(this);
        ui->cellsToSortBackground->setScene(scene);
        ui->cellsToSortBackground->verticalScrollBar()->blockSignals(true);
        ui->cellsToSortBackground->horizontalScrollBar()->blockSignals(true);

        //configuring variables
        appStates = -1; // (-1) - App started

        sceneHeight = ui->cellsToSortBackground->size().height();
        sceneWidth = ui->cellsToSortBackground->size().width();
        comparisions = 0;

        //customize the ListWidget & set a QMap for sorting algorithms
        for(int i = 0; i < ui->algorithmSelection->count(); i++)
        {
          QListWidgetItem *item = ui->algorithmSelection->item(i);
          item->setSizeHint(QSize(item->sizeHint().width(), 50));
          AlgorithmList.insert(i, item->text());
        }

        //to improve UX
        ui->amountChanger->setDisabled(true);
        ui->delayChanger->setDisabled(true);
        ui->sortButton->setDisabled(true);

        //creating 100 columns with sorting delay == 1ms , setting them up
        columnsSetUp(1, 100);
    }

    void Widget::columnsSetUp(int ms, int n)
    {
        //configuring variables
        ui->LabelComparisions_var->setNum(0);
        ui->LabelArrayAccesses_var->setNum(0);

        sortDelay = ms;
        amountOfColumns = n;
        columnsWidth = sceneWidth / amountOfColumns;

        //setting up columns to sort
        columns.resize(static_cast<unsigned>(amountOfColumns));

        //setting up columns height
        double incrementBy = sceneHeight / amountOfColumns;
        for(auto i = incrementBy; i <= sceneHeight; i += incrementBy)
            columnsHeight.push_back(i);

        //randomize an array
        std::random_device m_random;
        std::mt19937 e_random(m_random());
        std::shuffle(columnsHeight.begin(), columnsHeight.end(), e_random);

        //aplying columns to scene
        auto j = 0;
        auto k = 0.0;
        for(auto &p : columns)
        {
            p = new QGraphicsRectItem;
            p->setRect(k, (sceneHeight - columnsHeight[j]), columnsWidth , columnsHeight[j]);
            p->setBrush(QBrush(QColor(255, 0, 68, 255)));

            if(amountOfColumns <= 200)
                p->setPen(QPen(Qt::black, 2));
            else if(amountOfColumns > 200 && amountOfColumns <= 300)
                p->setPen(QPen(Qt::black, 1));
            else
                p->setPen(Qt::NoPen);

            scene->addItem(p);

            j++;
            k += columnsWidth;
        }
    }

    void Widget::resetColumns(int ms, int n)
    {
        for(auto &p : columns)
            scene->removeItem(p);

        columnsHeight.clear();

        columnsSetUp(ms, n);
        threadUpdate(sortDelay, algorithmKey);
    }

    void Widget::threadUpdate(int ms, int key)
    {
        mThread = new Thread(ms, key, static_cast<int>(amountOfColumns), columnsHeight, this);

        connect(mThread, SIGNAL(comparision(int, int)), this, SLOT(on_comparision(int, int)));
        connect(mThread, SIGNAL(sortDone(int)), this, SLOT(sortDone(int)));
        connect(mThread, SIGNAL(arrayAccess(int)), ui->LabelArrayAccesses_var, SLOT(setNum(int)));
        connect(mThread, SIGNAL(changeButtonStatus(int)), this, SLOT(sortButtonStatus(int)));
    }

    void Widget::on_algorithmSelection_itemClicked(QListWidgetItem *item)
    {
        if(appStates == -1)
        {
            ui->sortButton->setEnabled(true);
            ui->amountChanger->setEnabled(true);
            ui->delayChanger->setEnabled(true);

            appStates = 0;
            sortButtonStatus(appStates);
        }

        if(appStates == 0)
        {
            algorithmKey = AlgorithmList.key(item->text());
            ui->LabelSortingWith_var->setText(item->text());
        }
    }

    void Widget::on_amountChanger_valueChanged(int n)
    {
        if(appStates == 0)
            resetColumns(sortDelay, n);
    }

    void Widget::on_delayChanger_valueChanged(int ms)
    {
        if(appStates == 0)
            resetColumns(ms, static_cast<int>(amountOfColumns));
    }


    void Widget::on_sortButton_clicked()
    {
        switch(appStates)
        {
            case 0:
                sortButtonStatus(1);
                comparisions = 0;
                threadUpdate(sortDelay, algorithmKey);
                mThread->start();
                break;

            case 1:
                mThread->terminate();
                sortButtonStatus(2);
                break;

            case 2:
                for(auto &p : columns)
                    scene->removeItem(p);

                columnsHeight.clear();
                columnsSetUp(sortDelay, static_cast<int>(amountOfColumns));
                sortButtonStatus(0);
                break;

            default:
                break;
        }
    }

    void Widget::sortButtonStatus(int state)
    {
        QString buttonText;
        QString style;

        switch(state)
        {
        case 0:
            buttonText = "sort";
            ui->amountChanger->setEnabled(true);
            ui->delayChanger->setEnabled(true);
            ui->algorithmSelection->setEnabled(true);
            style = "background-color: rgba(255, 0, 68, 255); color: #fff";
            break;

        case 1:
            buttonText = "cancel";
            ui->amountChanger->setDisabled(true);
            ui->delayChanger->setDisabled(true);
            ui->algorithmSelection->setDisabled(true);
            style = "background-color: #000; color: #fff";
            break;

        case 2:
            buttonText = "new sort";
            ui->sortButton->setEnabled(true);
            style = "background-color: rgb(85, 0, 255); color: #fff";
            break;
        }

        appStates = state;
        ui->sortButton->setText(buttonText);
        ui->sortButton->setStyleSheet(style);
    }

    void Widget::on_comparision(int n, int k)
    {
        auto nRect = columns[n]->rect();
        auto kRect = columns[k]->rect();
        auto nColumnPos = nRect.left();
        auto kColumnPos = kRect.left();

        nRect.moveLeft(kColumnPos);
        kRect.moveLeft(nColumnPos);

        columns[n]->setRect(nRect);
        columns[k]->setRect(kRect);

        std::swap(columns[n], columns[k]);

        comparisions++;
        ui->LabelComparisions_var->setNum(comparisions);
    }

    void Widget::sortDone(int n)
    {
        columns[n]->setBrush(QBrush(QColor(0,200,0)));
    }

    Widget::~Widget()
    {
        mThread->terminate();
        delete ui;
    }

That's how algorithms class looks like(with only Bubble Sort implemented for example) (47 lines of code):

    #ifndef THREAD_H
    #define THREAD_H

    #include <QThread>
    #include <QtWidgets>

    class Thread : public QThread
    {
        Q_OBJECT
    public:
        Thread(int, int, int, std::vector<double>, QObject*);

    signals:
        void comparision(int, int);
        void sortDone(int);
        void arrayAccess(int);
        void changeButtonStatus(int);

    protected:
        void run() override;

    private:
        std::vector<double> columnsHeight;
        int sortDoneDelay;
        int sortDelay;
        int amount;
        int sortWith;
        int arrayAccessVariable;

        void swap(int, int);
        void isAccessToArray();
        void Sorted();

        //sorting algorithms declaration
        void BubbleSort();

        /*
        void RecursiveBubbleSort(int);
        void CocktailSort();
        void GnomeSort();

        int QuickSortPartition(int, int);
        void QuickSort(int, int);

        void Heapify(int n, int i);
        void HeapSort();
        */
    };

    #endif // THREAD_H

Wonder if QThreading is done correctly, I had a lot of problems with that. (63 lines of code)

    #include "includes/algorithms.h"

    Thread::Thread(int ms, int alg, int n, std::vector<double> col, QObject *parent = nullptr) : QThread(parent)
    {
        sortWith = alg;
        amount = n;
        columnsHeight = col;
        arrayAccessVariable = 0;

        sortDoneDelay = (amount >= 300 ? 2 : 5);
        sortDelay = ms;
    }

    void Thread::run()
    {
        switch(sortWith)
        {
            case 0: BubbleSort(); break;
            /*
            case 1: RecursiveBubbleSort(amount); break;
            case 2: CocktailSort(); break;
            case 3: GnomeSort(); break;
            case 4: QuickSort(0, amount -1); break;
            case 5: HeapSort(); break;
            */
        }
        Sorted();
    }

    void Thread::Sorted()
    {
        for(auto i=0; i<amount; i++)
        {
            emit sortDone(i);
            msleep(sortDoneDelay);
        }
        emit changeButtonStatus(2);
    }

    void Thread::swap(int n, int k)
    {
        std::swap(columnsHeight[n], columnsHeight[k]);
        emit comparision(n, k);
    }

    void Thread::isAccessToArray()
    {
        arrayAccessVariable++;
        emit arrayAccess(arrayAccessVariable);
    }

    //--------- BUBBLE SORT -----------

    void Thread::BubbleSort()
    {
        for(auto i = 0; i < amount; i++)
                for(auto j = 0; j< amount-1; j++)
                {
                    if(columnsHeight[j] > columnsHeight[j+1])
                        swap(j, j+1);

                    isAccessToArray();
                    msleep(sortDelay);
                }
    }

    //implementations of recursive bubble sort, cocktail sort, gnome sort, quick sort, heap sort are deleted for this example.

An app preview video is available on my github's project page in README file.

https://github.com/letelete/Visualization_Of_Sorting_Algorithms/blob/master/README.md

Each opinion/review will be appreciated. Thanks in advice.

\$\endgroup\$
  • \$\begingroup\$ Does it work as expected, we can only review working code here. \$\endgroup\$ – pacmaninbw Nov 28 '17 at 14:30
  • 1
    \$\begingroup\$ Yes it does, but I paste there only 2 classes, to run this app You need main.cpp, .pro file and .ui file. I also erase 5 algorithms and left only Bubble Sort to show You an example. You can go to my gist for the rest of the code. github.com/letelete/Visualization_Of_Sorting_Algorithms \$\endgroup\$ – letelete Nov 28 '17 at 14:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.