shushus

Спринт 7. Вставка и удаление в произвольной позиции.

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