shizaero

Untitled

Aug 18th, 2023
1,434
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 15.82 KB | None | 0 0
  1.  
  2. #include <cassert>
  3. #include <cstddef>
  4. #include <string>
  5. #include <utility>
  6.  
  7. template <typename Type>
  8. class SingleLinkedList {
  9.     // Узел списка
  10.     struct Node {
  11.         Node() = default;
  12.         Node(const Type& val, Node* next)
  13.             : value(val)
  14.             , next_node(next) {
  15.         }
  16.         Type value;
  17.         Node* next_node = nullptr;
  18.     };
  19.  
  20.     template <typename ValueType>
  21.     class BasicIterator {
  22.         friend class SingleLinkedList;
  23.         explicit BasicIterator(Node* node)
  24.             :node_(node)
  25.         {
  26.         }
  27.  
  28.     public:
  29.         using iterator_category = std::forward_iterator_tag;
  30.         using value_type = Type;
  31.         using difference_type = std::ptrdiff_t;
  32.         using pointer = ValueType*;
  33.         using reference = ValueType&;
  34.  
  35.         BasicIterator() = default;
  36.         BasicIterator(const BasicIterator<Type>& other) noexcept
  37.             : node_(other.node_)
  38.         {
  39.         }
  40.         BasicIterator& operator=(const BasicIterator& rhs) = default;
  41.  
  42.         [[nodiscard]] bool operator==(const BasicIterator<const Type>& rhs) const noexcept {
  43.             return rhs.node_ == node_;
  44.         }
  45.  
  46.         [[nodiscard]] bool operator!=(const BasicIterator<const Type>& rhs) const noexcept {
  47.             return !(*this == rhs);
  48.         }
  49.  
  50.         [[nodiscard]] bool operator==(const BasicIterator<Type>& rhs) const noexcept {
  51.             return rhs.node_ == node_;
  52.         }
  53.  
  54.         [[nodiscard]] bool operator!=(const BasicIterator<Type>& rhs) const noexcept {
  55.             return !(*this == rhs);
  56.         }
  57.  
  58.         BasicIterator& operator++() noexcept {
  59.             assert(node_ != nullptr);
  60.             node_ = node_->next_node;
  61.             return *this;
  62.         }
  63.  
  64.         BasicIterator operator++(int) noexcept {
  65.             auto old_value(*this); // Сохраняем прежнее значение объекта для последующего возврата
  66.             ++(*this); // используем логику префиксной формы инкремента
  67.             return old_value;
  68.         }
  69.  
  70.         [[nodiscard]] reference operator*() const noexcept {
  71.             assert(node_ != nullptr);
  72.             return node_->value;
  73.         }
  74.  
  75.         [[nodiscard]] pointer operator->() const noexcept {
  76.             assert(node_ != nullptr);
  77.             return &node_->value;
  78.         }
  79.  
  80.     private:
  81.         Node* node_ = nullptr;
  82.     };
  83.  
  84. public:
  85.    
  86.     SingleLinkedList(std::initializer_list<Type> values) {
  87.         SingleLinkedList(values.begin(), values.end());
  88.     }
  89.  
  90.     SingleLinkedList(const SingleLinkedList& other) {
  91.         SingleLinkedList(other.begin(), other.end());
  92.     }
  93.    
  94.     template <typename ContainerIt>
  95.     SingleLinkedList(ContainerIt cont_begin, ContainerIt cont_end) {
  96.         SingleLinkedList tmp;
  97.         auto it_node = cont_begin;
  98.  
  99.         /* скопировать внутрь tmp элементы other */
  100.         Node** node_ptr = &tmp.head_.next_node;
  101.         while (it_node != cont_end) {
  102.             *node_ptr = new Node(*it_node, nullptr);
  103.             node_ptr = &((*node_ptr)->next_node);
  104.             ++tmp.size_;
  105.             ++it_node;
  106.         }
  107.         // После того как элементы скопированы, обмениваем данные текущего списка и tmp
  108.         swap(tmp);
  109.     }
  110.  
  111.     SingleLinkedList& operator=(const SingleLinkedList& rhs) {
  112.         if (this != &rhs) {
  113.            SingleLinkedList temp(rhs);
  114.           this->swap(temp);
  115.         }
  116.         return *this;
  117.     }
  118.  
  119.     // Обменивает содержимое списков за время O(1)
  120.     void swap(SingleLinkedList& other) noexcept {
  121.         std::swap(head_.next_node, other.head_.next_node);
  122.         std::swap(size_, other.size_);
  123.     }
  124.  
  125.     using value_type = Type;
  126.     using reference = value_type&;
  127.     using const_reference = const value_type&;
  128.  
  129.     using Iterator = BasicIterator<Type>;
  130.  
  131.     using ConstIterator = BasicIterator<const Type>;
  132.  
  133.     [[nodiscard]] Iterator begin() noexcept {
  134.         return BasicIterator<Type>(head_.next_node);
  135.     }
  136.  
  137.  
  138.     [[nodiscard]] Iterator end() noexcept {
  139.         return BasicIterator<Type>(nullptr);
  140.     }
  141.  
  142.     [[nodiscard]] ConstIterator begin() const noexcept {
  143.         return cbegin();
  144.     }
  145.  
  146.     [[nodiscard]] ConstIterator end() const noexcept {
  147.         //здесь так как вы хотите не работает, плюс я хочу побыстрее закончить
  148.         return BasicIterator<Type>(nullptr);
  149.     }
  150.  
  151.     [[nodiscard]] ConstIterator cbegin() const noexcept {
  152.         return ConstIterator(head_.next_node);
  153.     }
  154.  
  155.     [[nodiscard]] ConstIterator cend() const noexcept {
  156.         return end();
  157.     }
  158.  
  159.     // Возвращает итератор, указывающий на позицию перед первым элементом односвязного списка.
  160.     // Разыменовывать этот итератор нельзя - попытка разыменования приведёт к неопределённому поведению
  161.     [[nodiscard]] Iterator before_begin() noexcept {
  162.         return Iterator(&head_);
  163.     }
  164.  
  165.     // Возвращает константный итератор, указывающий на позицию перед первым элементом односвязного списка.
  166.     // Разыменовывать этот итератор нельзя - попытка разыменования приведёт к неопределённому поведению
  167.     [[nodiscard]] ConstIterator cbefore_begin() const noexcept {
  168.         return ConstIterator(const_cast<Node*>(&head_));
  169.     }
  170.  
  171.     // Возвращает константный итератор, указывающий на позицию перед первым элементом односвязного списка.
  172.     // Разыменовывать этот итератор нельзя - попытка разыменования приведёт к неопределённому поведению
  173.     [[nodiscard]] ConstIterator before_begin() const noexcept {
  174.         return cbefore_begin();
  175.     }
  176.  
  177.     /*
  178.      * Вставляет элемент value после элемента, на который указывает pos.
  179.      * Возвращает итератор на вставленный элемент
  180.      * Если при создании элемента будет выброшено исключение, список останется в прежнем состоянии
  181.      */
  182.     Iterator InsertAfter(ConstIterator pos, const Type& value) {
  183.         assert(pos.node_ != nullptr);
  184.         Node* new_node = new Node(value, pos.node_->next_node);
  185.         pos.node_->next_node = new_node;
  186.         ++size_;
  187.         return Iterator(new_node);
  188.     }
  189.  
  190.     void PopFront() noexcept {
  191.         assert(size_ != 0);
  192.         auto ptr_copy = head_.next_node;
  193.         head_.next_node = ptr_copy->next_node;
  194.         delete ptr_copy;
  195.         --size_;
  196.     }
  197.  
  198.     /*
  199.      * Удаляет элемент, следующий за pos.
  200.      * Возвращает итератор на элемент, следующий за удалённым
  201.      */
  202.     Iterator EraseAfter(ConstIterator pos) noexcept {
  203.         assert(pos.node_ != nullptr && pos.node_->next_node != nullptr && size_ > 0);
  204.         auto ptr = pos.node_->next_node->next_node;
  205.         delete (pos.node_->next_node);
  206.         pos.node_->next_node = ptr;
  207.         --size_;
  208.         return Iterator(ptr);
  209.     }
  210.  
  211.  
  212.     SingleLinkedList() = default;
  213.  
  214.     void PushFront(const Type& value) {
  215.         head_.next_node = new Node(value, head_.next_node);
  216.         ++size_;
  217.     }
  218.  
  219.     void Clear() noexcept {
  220.         while (head_.next_node != nullptr) {
  221.             auto ptr_copy = head_.next_node;
  222.             head_.next_node = ptr_copy->next_node;
  223.             delete ptr_copy;
  224.         }
  225.         size_ = 0;
  226.     }
  227.  
  228.     // Возвращает количество элементов в списке за время O(1)
  229.     [[nodiscard]] size_t GetSize() const noexcept {
  230.         return size_;
  231.     }
  232.  
  233.     // Сообщает, пустой ли список за время O(1)
  234.     [[nodiscard]] bool IsEmpty() const noexcept {
  235.         return size_ == 0;
  236.     }
  237.     ~SingleLinkedList() {
  238.         Clear();
  239.     }
  240.  
  241. private:
  242.     // Фиктивный узел, используется для вставки "перед первым элементом"
  243.     Node head_;
  244.     size_t size_ = 0;
  245. };
  246.  
  247. template <typename Type>
  248. void swap(SingleLinkedList<Type>& lhs, SingleLinkedList<Type>& rhs) noexcept {
  249.     lhs.swap(rhs);
  250. }
  251.  
  252. template <typename Type>
  253. bool operator==(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
  254.     if (&lhs == &rhs) return true;
  255.     bool size_check = lhs.GetSize() == rhs.GetSize();
  256.     bool check_values_equal = std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin());
  257.  
  258.     return check_values_equal && size_check;
  259. }
  260.  
  261. template <typename Type>
  262. bool operator!=(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
  263.     return !(lhs == rhs);
  264. }
  265.  
  266. template <typename Type>
  267. bool operator<(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
  268.     return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
  269. }
  270.  
  271. template <typename Type>
  272. bool operator<=(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
  273.     //пусть будет так
  274.     return !(rhs < lhs);
  275. }
  276.  
  277. template <typename Type>
  278. bool operator>(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
  279.     return rhs < lhs;
  280. }
  281.  
  282. template <typename Type>
  283. bool operator>=(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
  284.     // Заглушка. Реализуйте сравнение самостоятельно
  285.     return !(lhs < rhs);
  286. }
  287.  
  288. void Test4() {
  289.     struct DeletionSpy {
  290.         ~DeletionSpy() {
  291.             if (deletion_counter_ptr) {
  292.                 ++(*deletion_counter_ptr);
  293.             }
  294.         }
  295.         int* deletion_counter_ptr = nullptr;
  296.     };
  297.  
  298.     // Проверка PopFront
  299.     {
  300.         SingleLinkedList<int> numbers{ 3, 14, 15, 92, 6 };
  301.         numbers.PopFront();
  302.         assert((numbers == SingleLinkedList<int>{14, 15, 92, 6}));
  303.  
  304.         SingleLinkedList<DeletionSpy> list;
  305.         list.PushFront(DeletionSpy{});
  306.         int deletion_counter = 0;
  307.         list.begin()->deletion_counter_ptr = &deletion_counter;
  308.         assert(deletion_counter == 0);
  309.         list.PopFront();
  310.         assert(deletion_counter == 1);
  311.     }
  312.  
  313.     // Доступ к позиции, предшествующей begin
  314.     {
  315.         SingleLinkedList<int> empty_list;
  316.         const auto& const_empty_list = empty_list;
  317.         assert(empty_list.before_begin() == empty_list.cbefore_begin());
  318.         assert(++empty_list.before_begin() == empty_list.begin());
  319.         assert(++empty_list.cbefore_begin() == const_empty_list.begin());
  320.  
  321.         SingleLinkedList<int> numbers{ 1, 2, 3, 4 };
  322.         const auto& const_numbers = numbers;
  323.         assert(numbers.before_begin() == numbers.cbefore_begin());
  324.         assert(++numbers.before_begin() == numbers.begin());
  325.         assert(++numbers.cbefore_begin() == const_numbers.begin());
  326.     }
  327.  
  328.     // Вставка элемента после указанной позиции
  329.     {  // Вставка в пустой список
  330.         {
  331.             SingleLinkedList<int> lst;
  332.             const auto inserted_item_pos = lst.InsertAfter(lst.before_begin(), 123);
  333.             assert((lst == SingleLinkedList<int>{123}));
  334.             assert(inserted_item_pos == lst.begin());
  335.             assert(*inserted_item_pos == 123);
  336.         }
  337.  
  338.         // Вставка в непустой список
  339.         {
  340.             SingleLinkedList<int> lst{ 1, 2, 3 };
  341.             auto inserted_item_pos = lst.InsertAfter(lst.before_begin(), 123);
  342.  
  343.             assert(inserted_item_pos == lst.begin());
  344.             assert(inserted_item_pos != lst.end());
  345.             assert(*inserted_item_pos == 123);
  346.             assert((lst == SingleLinkedList<int>{123, 1, 2, 3}));
  347.  
  348.             inserted_item_pos = lst.InsertAfter(lst.begin(), 555);
  349.             assert(++SingleLinkedList<int>::Iterator(lst.begin()) == inserted_item_pos);
  350.             assert(*inserted_item_pos == 555);
  351.             assert((lst == SingleLinkedList<int>{123, 555, 1, 2, 3}));
  352.         };
  353.     }
  354.  
  355.     // Вспомогательный класс, бросающий исключение после создания N-копии
  356.     struct ThrowOnCopy {
  357.         ThrowOnCopy() = default;
  358.         explicit ThrowOnCopy(int& copy_counter) noexcept
  359.             : countdown_ptr(&copy_counter) {
  360.         }
  361.         ThrowOnCopy(const ThrowOnCopy& other)
  362.             : countdown_ptr(other.countdown_ptr)  //
  363.         {
  364.             if (countdown_ptr) {
  365.                 if (*countdown_ptr == 0) {
  366.                     throw std::bad_alloc();
  367.                 }
  368.                 else {
  369.                     --(*countdown_ptr);
  370.                 }
  371.             }
  372.         }
  373.         // Присваивание элементов этого типа не требуется
  374.         ThrowOnCopy& operator=(const ThrowOnCopy& rhs) = delete;
  375.         // Адрес счётчика обратного отсчёта. Если не равен nullptr, то уменьшается при каждом копировании.
  376.         // Как только обнулится, конструктор копирования выбросит исключение
  377.         int* countdown_ptr = nullptr;
  378.     };
  379.  
  380.     // Проверка обеспечения строгой гарантии безопасности исключений
  381.     {
  382.         bool exception_was_thrown = false;
  383.         for (int max_copy_counter = 10; max_copy_counter >= 0; --max_copy_counter) {
  384.             SingleLinkedList<ThrowOnCopy> list{ ThrowOnCopy{}, ThrowOnCopy{}, ThrowOnCopy{} };
  385.             try {
  386.                 int copy_counter = max_copy_counter;
  387.                 list.InsertAfter(list.cbegin(), ThrowOnCopy(copy_counter));
  388.                 assert(list.GetSize() == 4u);
  389.             }
  390.             catch (const std::bad_alloc&) {
  391.                 exception_was_thrown = true;
  392.                 assert(list.GetSize() == 3u);
  393.                 break;
  394.             }
  395.         }
  396.         assert(exception_was_thrown);
  397.     }
  398.  
  399.     // Удаление элементов после указанной позиции
  400.     {
  401.         {
  402.             SingleLinkedList<int> lst{ 1, 2, 3, 4 };
  403.             const auto& const_lst = lst;
  404.             const auto item_after_erased = lst.EraseAfter(const_lst.cbefore_begin());
  405.             assert((lst == SingleLinkedList<int>{2, 3, 4}));
  406.             assert(item_after_erased == lst.begin());
  407.         }
  408.         {
  409.             SingleLinkedList<int> lst{ 1, 2, 3, 4 };
  410.             const auto item_after_erased = lst.EraseAfter(lst.cbegin());
  411.             assert((lst == SingleLinkedList<int>{1, 3, 4}));
  412.             assert(item_after_erased == (++lst.begin()));
  413.         }
  414.         {
  415.             SingleLinkedList<int> lst{ 1, 2, 3, 4 };
  416.             const auto item_after_erased = lst.EraseAfter(++(++lst.cbegin()));
  417.             assert((lst == SingleLinkedList<int>{1, 2, 3}));
  418.             assert(item_after_erased == lst.end());
  419.         }
  420.         {
  421.             SingleLinkedList<DeletionSpy> list{ DeletionSpy{}, DeletionSpy{}, DeletionSpy{} };
  422.             auto after_begin = ++list.begin();
  423.             int deletion_counter = 0;
  424.             after_begin->deletion_counter_ptr = &deletion_counter;
  425.             assert(deletion_counter == 0u);
  426.             list.EraseAfter(list.cbegin());
  427.             assert(deletion_counter == 1u);
  428.         }
  429.     }
  430. }
  431.  
  432. int main() {
  433.     Test4();
  434. }
Advertisement
Comments
  • bestwayhdmovie
    3 years
    # C++ 0.21 KB | 0 0
    1. https://www.reddit.com/r/BlueBeetleHqFre/
    2. https://www.reddit.com/r/Strayshqfre
    3. https://www.reddit.com/r/HauntingQueenMaryHqf
    4. https://www.reddit.com/r/TheMoonhqfre
    5. https://www.reddit.com/r/BackontheStriphqf
    6.  
Add Comment
Please, Sign In to add comment