Advertisement
chevengur

СПРИНТ № 8 | Санитайзеры и другие инструменты поиска ошибок | Урок 9: Исправляем список

May 25th, 2024 (edited)
757
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.11 KB | None | 0 0
  1. main.cpp
  2.  
  3. #include "list.h"
  4. #include <cassert>
  5. #include <vector>
  6.  
  7. using namespace std;
  8.  
  9. template <class Type>
  10. auto MakeInsertingFunction(vector<SingleLinkedList<Type>>& lists, int x) {
  11.     return [&](const Type& value) {
  12.         lists.at(x).PushFront(value);
  13.         };
  14. }
  15.  
  16. template <class T>
  17. void InsertRange(int from, int to, T push_function) {
  18.     for (int i = from; i < to; ++i) {
  19.         push_function(i);
  20.     }
  21. }
  22.  
  23. int main() {
  24.  
  25.     vector<SingleLinkedList<int>> lists_a(10);
  26.  
  27.     auto push_to_2a = MakeInsertingFunction(lists_a, 2);
  28.     auto push_to_5a = MakeInsertingFunction(lists_a, 5);
  29.     auto push_to_7a = MakeInsertingFunction(lists_a, 7);
  30.  
  31.     InsertRange(10, 12, push_to_2a);
  32.     InsertRange(12, 14, push_to_5a);
  33.     InsertRange(14, 16, push_to_7a);
  34.  
  35.     assert(lists_a[2] == SingleLinkedList<int>({ 11, 10 }));
  36.     assert(lists_a[5] == SingleLinkedList<int>({ 13, 12 }));
  37.     assert(lists_a[7] == SingleLinkedList<int>({ 15, 14 }));
  38.  
  39.     vector<SingleLinkedList<int>> lists_b = lists_a;
  40.  
  41.     auto push_to_2b = MakeInsertingFunction(lists_b, 2);
  42.     auto push_to_5b = MakeInsertingFunction(lists_b, 5);
  43.     auto push_to_7b = MakeInsertingFunction(lists_b, 7);
  44.  
  45.     InsertRange(20, 22, push_to_2b);
  46.     InsertRange(22, 24, push_to_5b);
  47.     InsertRange(24, 26, push_to_7b);
  48.  
  49.     assert(lists_b[2] == SingleLinkedList<int>({ 21, 20, 11, 10 }));
  50.     assert(lists_b[5] == SingleLinkedList<int>({ 23, 22, 13, 12 }));
  51.     assert(lists_b[7] == SingleLinkedList<int>({ 25, 24, 15, 14 }));
  52.  
  53.     lists_a[2].PopFront();
  54.     lists_a[5].InsertAfter(lists_a[5].begin(), 100);
  55.     lists_b[5].EraseAfter(next(lists_b[5].begin()));
  56.     lists_b[7].Clear();
  57.  
  58.     assert(lists_a[2] == SingleLinkedList<int>({ 10 }));
  59.     assert(lists_a[5] == SingleLinkedList<int>({ 13, 100, 12 }));
  60.     assert(lists_b[5] == SingleLinkedList<int>({ 23, 22, 12 }));
  61.     assert(lists_b[7] == SingleLinkedList<int>());
  62. }
  63.  
  64. ==================================================================================================================================
  65. list.h
  66.  
  67. #pragma once
  68.  
  69. #include <cassert>
  70. #include <cstddef>
  71. #include <iterator>
  72.  
  73. template <typename Type>
  74. class SingleLinkedList {
  75.  
  76.     struct Node {
  77.         Node() = default;
  78.         Node(const Type& val, Node* next) : value(val), next_node(next) {}
  79.         Type value{};
  80.         Node* next_node = nullptr;
  81.     };
  82.  
  83.  
  84.     template <typename ValueType>
  85.     class BasicIterator {
  86.  
  87.         friend class SingleLinkedList;
  88.  
  89.         explicit BasicIterator(Node* node) : node_(node) {}
  90.  
  91.     public:
  92.  
  93.         using iterator_category = std::forward_iterator_tag;
  94.         using value_type = Type;
  95.         using difference_type = std::ptrdiff_t;
  96.         using pointer = ValueType*;
  97.         using reference = ValueType&;
  98.  
  99.         BasicIterator() = default;
  100.  
  101.         BasicIterator(const BasicIterator<Type>& other) noexcept : node_(other.node_) {}
  102.  
  103.         BasicIterator& operator=(const BasicIterator& rhs) = default;
  104.  
  105.         [[nodiscard]] bool operator==(const BasicIterator<const Type>& rhs) const noexcept {
  106.             return this->node_ == rhs.node_;
  107.         }
  108.  
  109.         [[nodiscard]] bool operator==(const BasicIterator<Type>& rhs) const noexcept {
  110.             return this->node_ == rhs.node_;
  111.         }
  112.        
  113.         [[nodiscard]] bool operator!=(const BasicIterator<const Type>& rhs) const noexcept {
  114.             return node_ != rhs.node_;
  115.         }
  116.  
  117.         [[nodiscard]] bool operator!=(const BasicIterator<Type>& rhs) const noexcept {
  118.             return node_ != rhs.node_;
  119.         }
  120.  
  121.         BasicIterator& operator++() noexcept {
  122.             assert(node_ != nullptr);
  123.             node_ = node_->next_node;
  124.             return *this;
  125.         }
  126.  
  127.         BasicIterator operator++(int) noexcept {
  128.             auto this_copy(*this);
  129.             ++(*this);
  130.             return this_copy;
  131.         }
  132.  
  133.         [[nodiscard]] reference operator*() const noexcept {
  134.             assert(node_ != nullptr);
  135.             return node_->value;
  136.         }
  137.  
  138.         [[nodiscard]] pointer operator->() const noexcept {
  139.             assert(node_ != nullptr);
  140.             return &node_->value;
  141.         }
  142.  
  143.     private:
  144.         Node* node_ = nullptr;
  145.     };
  146.  
  147. public:
  148.     using value_type = Type;
  149.     using reference = value_type&;
  150.     using const_reference = const value_type&;
  151.  
  152.     using Iterator = BasicIterator<Type>;
  153.     using ConstIterator = BasicIterator<const Type>;
  154.  
  155.     SingleLinkedList() = default;
  156.  
  157.     SingleLinkedList(std::initializer_list<Type> values) {
  158.         Assign(values.begin(), values.end());
  159.     }
  160.    
  161.     SingleLinkedList(const SingleLinkedList& val) {
  162.         Assign(val.begin(), val.end());
  163.     }
  164.    
  165.     SingleLinkedList& operator=(const SingleLinkedList& helper) {
  166.         if (&helper != this) {
  167.             if(!helper.IsEmpty()){
  168.                 auto helper_copy(helper);
  169.                 swap(helper_copy);
  170.             }else{
  171.                 Clear();
  172.             }
  173.         }
  174.         return *this;
  175.     }
  176.  
  177.     ~SingleLinkedList() {
  178.         Clear();
  179.     }
  180.  
  181.     [[nodiscard]] Iterator begin() noexcept {
  182.         return Iterator{head_.next_node};
  183.     }
  184.  
  185.     [[nodiscard]] Iterator end() noexcept {
  186.         return Iterator{nullptr};
  187.     }
  188.  
  189.     [[nodiscard]] ConstIterator begin() const noexcept {
  190.         return cbegin();
  191.     }
  192.  
  193.     [[nodiscard]] ConstIterator end() const noexcept {
  194.         return ConstIterator{nullptr};
  195.     }
  196.  
  197.     [[nodiscard]] ConstIterator cbegin() const noexcept {
  198.         return ConstIterator{head_.next_node};
  199.     }
  200.  
  201.     [[nodiscard]] ConstIterator cend() const noexcept {
  202.         return ConstIterator{nullptr};
  203.     }
  204.  
  205.     [[nodiscard]] Iterator before_begin() noexcept {
  206.         return Iterator{&head_};
  207.     }
  208.  
  209.     [[nodiscard]] ConstIterator cbefore_begin() const noexcept {
  210.         return ConstIterator{const_cast<Node*>(&head_)};
  211.     }
  212.  
  213.     [[nodiscard]] ConstIterator before_begin() const noexcept {
  214.         return cbefore_begin();
  215.     }
  216.  
  217.     [[nodiscard]] size_t GetSize() const noexcept {
  218.         return size_;
  219.     }
  220.  
  221.     [[nodiscard]] bool IsEmpty() const noexcept {
  222.         return GetSize() == 0;
  223.     }
  224.  
  225.     void PushFront(const Type& value) {
  226.         head_.next_node = new Node(value, head_.next_node);
  227.  
  228.         ++size_;
  229.     }
  230.  
  231.     Iterator InsertAfter(ConstIterator pos, const Type& value) {
  232.         assert(pos.node_);
  233.  
  234.         pos.node_->next_node = new Node(value, pos.node_->next_node);
  235.  
  236.         ++size_;
  237.         return Iterator{pos.node_->next_node};
  238.     }
  239.  
  240.     void PopFront() noexcept {
  241.         assert(!IsEmpty());
  242.         --size_;
  243.         Node* helper = head_.next_node->next_node;
  244.         delete head_.next_node;
  245.         head_.next_node = helper;
  246.     }
  247.  
  248.     Iterator EraseAfter(ConstIterator pos) noexcept {
  249.         assert(!IsEmpty());
  250.         --size_;
  251.         Node* helper = pos.node_->next_node->next_node;
  252.         delete pos.node_->next_node;
  253.         pos.node_->next_node = helper;
  254.         return Iterator{pos.node_->next_node};
  255.     }
  256.  
  257.     void Clear() noexcept {
  258.  
  259.         while (head_.next_node != nullptr) {
  260.             Node* new_head = head_.next_node->next_node;
  261.             delete head_.next_node;
  262.             head_.next_node = new_head;
  263.         }
  264.         size_ = 0;
  265.     }
  266.  
  267.     void swap(SingleLinkedList& other) noexcept {
  268.         std::swap(head_.next_node, other.head_.next_node);
  269.         std::swap(size_, other.size_);
  270.     }
  271.  
  272. private:
  273.     template <typename InputIterator>
  274.     void Assign(InputIterator from, InputIterator to) {
  275.  
  276.         SingleLinkedList<Type> tmp;
  277.  
  278.         Node** node_ptr = &tmp.head_.next_node;
  279.         while (from != to) {
  280.  
  281.             assert(*node_ptr == nullptr);
  282.  
  283.             *node_ptr = new Node(*from, nullptr);
  284.             ++tmp.size_;
  285.  
  286.  
  287.             node_ptr = &((*node_ptr)->next_node);
  288.  
  289.             ++from;
  290.         }
  291.         swap(tmp);
  292.     }
  293.  
  294.     Node head_;
  295.     size_t size_ = 0;
  296. };
  297.  
  298. template <typename Type>
  299. void swap(SingleLinkedList<Type>& lhs, SingleLinkedList<Type>& rhs) noexcept {
  300.     lhs.swap(rhs);
  301. }
  302.  
  303. template <typename Type>
  304. bool operator==(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
  305.     return (&lhs == &rhs)
  306.         || (lhs.GetSize() == rhs.GetSize()
  307.             && std::equal(lhs.begin(), lhs.end(), rhs.begin()));
  308. }
  309.  
  310. template <typename Type>
  311. bool operator!=(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
  312.     return !(lhs == rhs);
  313. }
  314.  
  315. template <typename Type>
  316. bool operator<(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
  317.     return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
  318. }
  319.  
  320. template <typename Type>
  321. bool operator<=(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
  322.     return !(rhs < lhs);
  323. }
  324.  
  325. template <typename Type>
  326. bool operator>(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
  327.     return (rhs < lhs);
  328. }
  329.  
  330. template <typename Type>
  331. bool operator>=(const SingleLinkedList<Type>& lhs, const SingleLinkedList<Type>& rhs) {
  332.     return !(lhs < rhs);
  333. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement