poniedziałek, 15 września 2014

Algorytmy STL w C++

#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm> // Dla for_each.
#include <cstdlib> // Dla funkcji abs.
#include <deque>
#include <functional> // Dla bind2nd.
#include <list>
#include <set>
#include <numeric>

template <typename type> inline void print_elements(const type &collection, const char *before = "") {
    typename type::const_iterator position;

    std::cout << before;

    for (position = collection.begin(); position != collection.end(); ++position)
        std::cout << *position << ' ';

    std::cout << std::endl;
}

template <typename type> inline void insert_elements(type &collection, int first, int last) {
    for (int iterator = first; iterator <= last; ++iterator)
        collection.insert(collection.end(), iterator);
}

void print(int element) {
    std::cout << element << ' ';
}

bool is_even(int element) {
    return ((element % 2) == 0);
}

bool abs_less(int element_one, int element_two) {
    return (abs(element_one) < abs(element_two)); // Funkcja abs zwraca wartość bezwzględną z podanego argumentu.
}

void print_collection(const std::list<int> &list_collection) {
    print_elements(list_collection);
}

bool lest_for_collection(const std::list<int> &list_collection_one, const std::list<int> &list_collection_two) {
    return std::lexicographical_compare(list_collection_one.begin(), list_collection_one.end(), list_collection_two.begin(), list_collection_two.end());
}

int main() {
    // Algorytm for_each.

    std::vector<int> vector_one;

    insert_elements(vector_one, 1, 9);

    std::for_each(vector_one.begin(), vector_one.end(), print); // Dla każdego elementu wektora wywołaj podaną funkcję.

    std::cout << std::endl;

    // Algorytmy niemodyfikujące.

    int number;

    number = std::count(vector_one.begin(), vector_one.end(), 4); // Zlicz elementy o wartości 4;

    number = std::count_if(vector_one.begin(), vector_one.end(), is_even); // Zlicz elementy o wartościach parzystych.

    std::cout << "Wartosc najmniejsza: " << *std::min_element(vector_one.begin(), vector_one.end()) << std::endl;
  
    std::cout << "Najwieksza z wartosci bezwzglednych: " << *std::max_element(vector_one.begin(), vector_one.end(), abs_less) << std::endl;

    std::vector<int>::iterator vector_pointer;

    vector_pointer = std::find(vector_one.begin(), vector_one.end(), 4); // Znajdź pierwszy element o podanej wartości.

    vector_pointer = std::find_if(vector_one.begin(), vector_one.end(), std::bind2nd(std::greater<int>(), 3)); // Znajdź pierwszy element większy od 3.

    vector_pointer = std::search_n(vector_one.begin(), vector_one.end(), 2, 3); // Znajdź dwa kolejne elementy o wartości równej 3.

    vector_pointer = std::search_n(vector_one.begin(), vector_one.end(), 2, 3, std::greater<int>()); // Znajdź dwa kolejne elementy o wartości większej niż 3.

    std::deque<int> deque_one;
    std::list<int> list_one;

    insert_elements(deque_one, 1, 7);

    insert_elements(list_one, 3, 6);

    auto deque_pointer = std::search(deque_one.begin(), deque_one.end(), list_one.begin(), list_one.end()); // Szukaj pierwszego wystąpienia ciągu "list_one" w kolekcji "deque_one".

    deque_pointer = std::find_end(deque_one.begin(), deque_one.end(), list_one.begin(), list_one.end()); // Szukaj ostatniego wystąpienia ciągu "list_one" w kolekcji "deque_one".

    vector_pointer = std::find_first_of(vector_one.begin(), vector_one.end(), list_one.begin(), list_one.end()); // Szukaj pierwszego wystąpienia elementu kolekcji "list_one" w kolekcji "vector_one".

    vector_pointer = std::adjacent_find(vector_one.begin(), vector_one.end()); // Szukaj pierwszych dwóch elementów o równej wartości.

    if (std::equal(vector_one.begin(), vector_one.end(), list_one.begin()))
        std::cout << "Kolekcja \"vector_one\" jest rowna kolekcji \"list_one\".\n";
    else
        std::cout << "Kolekcja \"vector_one\" nie jest rowna kolekcji \"list_one\".\n";

    std::pair<std::vector<int>::iterator, std::list<int>::iterator> values;

    values = std::mismatch(vector_one.begin(), vector_one.end(), list_one.begin()); // Znajdź pierwszą niezgodność.

    if (values.first == vector_one.end())
        std::cout << "Brak niezgodnosc pomiedzy \"vector_one\" a \"list_one\".\n";
    else {
        std::cout << "Pierwsza niezgodnosc pomiedzy \"vector_one\" a \"list_one\": " << *values.first << ".\n";

        std::cout << "Druga niezgodnosc pomiedzy \"vector_one\" a \"list_one\": " << *values.second << ".\n";
    }

    std::list<int> list_two, list_three, list_four, list_five;

    insert_elements(list_two, 1, 5);

    list_five = list_four = list_three = list_two;

    list_two.push_back(7);

    list_three.push_back(2);

    list_four.push_back(0);

    list_five.push_back(2);

    std::vector<std::list<int> > collection_of_collection;

    collection_of_collection.push_back(list_two);

    collection_of_collection.push_back(list_three);

    collection_of_collection.push_back(list_four);

    collection_of_collection.push_back(list_five);

    collection_of_collection.push_back(list_four);

    collection_of_collection.push_back(list_two);

    collection_of_collection.push_back(list_five);

    collection_of_collection.push_back(list_three);

    std::sort(collection_of_collection.begin(), collection_of_collection.end(), lest_for_collection); // Posortuj kolekcje leksykograficznie.

    // Algorytmy modyfikujące.

    std::copy(vector_one.begin(), vector_one.end(), std::back_inserter(list_one)); // Kopiuj elementy kolekcji "vector_one" do "list_one" (kopiuje zakres na początek) i użyj wstawiacza końcowego aby elementy były wstawiane, a nie nadpisywane.

    std::vector<int> vector_two(vector_one.begin(), vector_one.end());

    std::copy_backward((vector_one.begin() + 2), (vector_one.begin() + 4), (vector_two.begin() + 5)); // Kopiuj zakres jak wyżej z tym, że na koniec.

    std::transform(vector_one.begin(), vector_one.end(), vector_one.begin(), std::negate<int>()); // Wykonaj negację wszystkich elementów.

    std::deque<int> deque_two;
    std::deque<int>::iterator deque_int_pointer;

    insert_elements(deque_two, 11, 23);

    deque_int_pointer = std::swap_ranges(vector_one.begin(), vector_one.end(), deque_two.begin()); // Wymień elementy kolekcji "vector_one" z odpowiadającymi im elementami kolekcji "deque_one".

    std::fill_n(std::ostream_iterator<float>(std::cout, " "), 10, 7.7); // Wypisz 10 razy wartość 7,7.

    std::cout << std::endl;

    std::fill(++list_one.begin(), --list_one.end(), 1); // Zastąp elementy od drugiego do przedostatniego wartością 1.

    std::generate_n(std::back_inserter(list_one), 5, rand); // Wstaw 5 losowych liczb.

    std::generate(list_one.begin(), list_one.end(), rand); // Nadpisz pięcioma liczbami losowymi.

    std::replace(list_one.begin(), list_one.end(), 5, 33); // Zastąp wszystkie wartości równe 5 wartościami równymi 33.

    std::replace_if(list_one.begin(), list_one.end(), std::bind2nd(std::less<int>(), 5), 0); // Zastąp wszystkie wartości spełniające podane kryterium wartościami równymi 0.

    std::replace_copy(list_two.begin(), list_two.end(), std::ostream_iterator<int>(std::cout, " "), 5, 55); // Wypisz wszystkie elementy o wartości 5 zastąpione wartością 55.

    std::cout << std::endl;

    std::replace_copy_if(list_two.begin(), list_two.end(), std::ostream_iterator<int>(std::cout, " "), std::bind2nd(std::less<int>(), 5), 42); // Wypisz wszystkie elementy o wartości większej od 5 i zastąpione wartością 42.

    std::cout << std::endl;

    // Algorytmy usuwające.

    vector_pointer = std::remove(vector_one.begin(), vector_one.end(), 5); // Usuń wszystkie elementy o wartości 5.

    vector_one.erase(std::remove_if(vector_one.begin(), vector_one.end(), std::bind2nd(std::less<int>(), 4)), vector_one.end()); // Usuń wszystkie elementy mniejsze od 4.

    std::remove_copy(list_one.begin(), list_one.end(), std::ostream_iterator<int>(std::cout, " "), 3); // Wypisz wszystkie elementy oprócz tych o wartości 3.

    std::cout << std::endl;

    std::remove_copy_if(list_one.begin(), list_one.end(), std::ostream_iterator<int>(std::cout, " "), std::bind2nd(std::greater<int>(), 4)); // Wypisz wszystkie elementy oprócz tych o wartościach większych od 4.

    std::cout << std::endl;

    std::list<int>::iterator list_pointer;

    list_pointer = std::unique(list_one.begin(), list_one.end()); // Usuń kolejne powtórzenia.

    std::unique_copy(list_two.begin(), list_two.end(), std::ostream_iterator<int>(std::cout, " ")); // Wypisz elementy z usuniętymi kolejnymi powtórzeniami.

    std::cout << std::endl;

    // Algorytmy mutujące.

    std::reverse(vector_one.begin(), vector_one.end()); // Odwróć kolejnośc elementów.

    std::reverse_copy(vector_two.begin(), vector_two.end(), std::ostream_iterator<int>(std::cout, " ")); // Wypisz wszystkie elementy w odwrotnej kolejności.

    std::cout << std::endl;

    std::rotate(vector_one.begin(), (vector_one.begin() + 1), vector_one.end()); // Przesuń cyklicznie o jeden element w lewo.

    std::set<int> set_one;

    insert_elements(set_one, 1, 9);

    std::set<int>::iterator set_int_pointer = set_one.begin();

    std::advance(set_int_pointer, 1);

    std::rotate_copy(set_one.begin(), set_int_pointer, set_one.end(), std::ostream_iterator<int>(std::cout, " ")); // Wypisz wszystkie elementy przesunięte cylicznie o jeden element w lewo.

    std::cout << std::endl;

    std::random_shuffle(vector_one.begin(), vector_one.end()); // Potasuj losowo wszystkie elementy.

    // Algorytmy sortujące.

    std::sort(deque_one.begin(), deque_one.end()); // Sortuj elementy rosnąco.

    std::sort(deque_one.begin(), deque_one.end(), std::greater<int>()); // Sortuj w kolejności malejącej.

    std::partial_sort(deque_one.begin(), (deque_one.begin() + 5), deque_one.end()); // Sortuj do momentu gdy posortowanych będzie 5 pierwszych elementów.

    std::partial_sort_copy(deque_one.begin(), deque_one.end(), vector_one.begin(), vector_one.end()); // Kopiuje elementy kolekcji "deque_one" do "vector_one".

    std::nth_element(deque_one.begin(), (deque_one.begin() + 4), deque_one.end()); // Wyłuskaj cztery najmniejsze elementy.

    std::copy(deque_one.begin(), (deque_one.begin() + 4), std::ostream_iterator<int>(std::cout, " ")); // Wypisz te cztery najmniejsze elementy.

    std::cout << std::endl;

    // Algorytmy przeznaczonego dla zakresów posortowanych.

    if (std::binary_search(list_one.begin(), list_one.end(), 5)) // Sprawdź czy istnieje element o wartości 5.
        std::cout << "Element o wartosci 5 jest obecny w liscie \"list_one\".\n";
    else
        std::cout << "Element o wartosci 5 nie jest obecny w liscie \"list_one\".\n";

    list_one.insert(std::lower_bound(list_one.begin(), list_one.end(), 3), 3); // Wstaw wartość 3 na pierwszej możliwej pozycji bez naruszania uporządkowania.

    list_one.insert(std::upper_bound(list_one.begin(), list_one.end(), 7), 7); // Wstaw wartość 3 na ostatniej możliwej pozycji bez naruszania uporządkowania.

    // Scalanie elementów.

    int table_one[] = { 1, 2, 2, 4, 6, 7, 7, 9 };
    int table_two[] = { 2, 2, 2, 3, 6, 6, 8, 9 };
    int length_one = (sizeof(table_one) / sizeof(int));
    int length_two = (sizeof(table_two) / sizeof(int));

    std::merge(table_one, (table_one + length_one), table_two, (table_two + length_two), std::ostream_iterator<int>(std::cout, " ")); // Połącz zakresy.

    std::cout << std::endl;

    std::set_union(table_one, (table_one + length_one), table_two, (table_two + length_two), std::ostream_iterator<int>(std::cout, " ")); // Zsumuj zakresy.

    std::cout << std::endl;

    std::set_intersection(table_one, (table_one + length_one), table_two, (table_two + length_two), std::ostream_iterator<int>(std::cout, " ")); // Iloczyn zakresów.

    std::cout << std::endl;

    std::set_difference(table_one, (table_one + length_one), table_two, (table_two + length_two), std::ostream_iterator<int>(std::cout, " ")); // Wyznacz elementy pierwszego zakresu bez elementów drugiego zakresu.

    std::cout << std::endl;

    std::set_symmetric_difference(table_one, (table_one + length_one), table_two, (table_two + length_two), std::ostream_iterator<int>(std::cout, " ")); // Różnica symetryczna zakresów.

    std::cout << std::endl;

    // Algorytmy numeryczne.

    std::cout << "Suma elementow \"vector_one\": " << std::accumulate(vector_one.begin(), vector_one.end(), 0) << std::endl; // Oblicz sumę elementów (argument trzeci to wartość początkowa).

    std::cout << "Iloczyn skalarny dla \"list_one\": " << std::inner_product(vector_one.begin(), vector_one.end(), vector_one.begin(), 0) << std::endl;

    std::partial_sum(vector_one.begin(), vector_one.end(), std::ostream_iterator<int>(std::cout, " ")); // Wypisz wszystkie sumy częściowe.

    std::cout << std::endl;

    std::adjacent_difference(deque_one.begin(), deque_one.end(), std::ostream_iterator<int>(std::cout, " ")); // Wypisz wszystkie różnice pomiędzy elementami.

    std::cout << std::endl;
}

Źródło:
- Prata S., Język C++. Szkoła programowania. Wydanie VI, Helion SA, 2012,
- Josuttis N. M., C++. Biblioteka standardowa, Helion SA, 2003.