Spajanje dinamičkih nizova

Napisati funkciju

template <typename T>
void spoji(DinamickiNiz<T>& a, const DinamickiNiz<T>& b);

koja na kraj niza a dodaje sve elemente niza b. Koristi se klasa DinamickiNiz<T> iz zaglavlja dinamicki_niz.h.

Prvo napisati najprirodnije rešenje i proveriti ga na prvom redu izlaza. Zatim razmisliti: da li radi poziv spoji(a, a)? Pokrenuti program sa sanitajzerom i ispraviti rešenje.

g++ -std=c++17 -Wall -Wextra -g -fsanitize=address,undefined main.cpp -o program

Pitanje za razmišljanje: Funkcija dodaj prima argument po referenci const T&. Šta se dešava ako ta referenca ukazuje na element istog niza, a dodaj pokrene realokaciju?

Ulaz

U prvom redu učitava se broj n $(0 \le n \le 10^4)$, a zatim n celih brojeva niza a. Nakon toga učitava se broj m $(0 \le m \le 10^4)$, a zatim m celih brojeva niza b.

Izlaz

U prvom redu ispisati niz a nakon poziva spoji(a, b), a u drugom redu niz a nakon poziva spoji(a, a).

Primer

Ulaz

2
1 2
2
3 4

Izlaz

1 2 3 4
1 2 3 4 1 2 3 4

Postavka

main.cpp

#include <iostream>

#include "dinamicki_niz.h"

namespace matf {

    // Na kraj niza a dodaje sve elemente niza b.
    template <typename T>
    void spoji(DinamickiNiz<T>& a, const DinamickiNiz<T>& b)
    {
        // Ovde ide vasa implementacija
    }

} // namespace matf

template <typename T>
void ucitaj(DinamickiNiz<T>& niz)
{
    std::size_t n;
    std::cin >> n;
    for (std::size_t i = 0; i < n; ++i) {
        T x;
        std::cin >> x;
        niz.dodaj(x);
    }
}

template <typename T>
void ispisi(const DinamickiNiz<T>& niz)
{
    for (std::size_t i = 0; i < niz.velicina(); ++i)
        std::cout << niz[i] << " ";
    std::cout << std::endl;
}

int main()
{
    DinamickiNiz<int> a;
    DinamickiNiz<int> b;
    ucitaj(a);
    ucitaj(b);

    matf::spoji(a, b);
    ispisi(a);

    matf::spoji(a, a);
    ispisi(a);

    return 0;
}

Rešenje

main.cpp

#include <iostream>

#include "dinamicki_niz.h"

namespace matf {

    // Na kraj niza a dodaje sve elemente niza b.
    template <typename T>
    void spoji(DinamickiNiz<T>& a, const DinamickiNiz<T>& b)
    {
        // Ako je &a == &b, velicina niza b raste tokom petlje, pa se pamti unapred.
        std::size_t m = b.velicina();
        for (std::size_t i = 0; i < m; ++i) {
            // b[i] moze biti element niza a. Kada dodaj realocira, oslobodi blok
            // u kom je b[i], a tek zatim upisuje vrednost, pa se pravi kopija.
            T x = b[i];
            a.dodaj(x);
        }
    }

} // namespace matf

template <typename T>
void ucitaj(DinamickiNiz<T>& niz)
{
    std::size_t n;
    std::cin >> n;
    for (std::size_t i = 0; i < n; ++i) {
        T x;
        std::cin >> x;
        niz.dodaj(x);
    }
}

template <typename T>
void ispisi(const DinamickiNiz<T>& niz)
{
    for (std::size_t i = 0; i < niz.velicina(); ++i)
        std::cout << niz[i] << " ";
    std::cout << std::endl;
}

int main()
{
    DinamickiNiz<int> a;
    DinamickiNiz<int> b;
    ucitaj(a);
    ucitaj(b);

    matf::spoji(a, b);
    ispisi(a);

    matf::spoji(a, a);
    ispisi(a);

    return 0;
}