Skip to content

Commit 00a69ad

Browse files
authored
Refactor connectNodes with helper functions
Refactor connectNodes to use helper functions for detaching and inserting nodes, improving readability and maintainability.
1 parent ae60cfc commit 00a69ad

File tree

1 file changed

+48
-40
lines changed

1 file changed

+48
-40
lines changed

src/4_Lists/list.cpp

Lines changed: 48 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -81,49 +81,57 @@ std::unique_ptr<List::Node> *List::ownerAt(unsigned int index) {
8181
return owner;
8282
}
8383

84-
void List::connectNodes(unsigned int index1, unsigned int index2) {
85-
if (index1 == index2 || index1 >= count || index2 >= count) {
86-
throw std::out_of_range{"Index out of range!"};
87-
}
88-
89-
if (index1 < index2) {
90-
auto *owner1 = ownerAt(index1);
91-
auto *owner2 = ownerAt(index2);
92-
if (!owner1 || !owner2) {
93-
throw std::out_of_range{"Index out of range!"};
94-
}
95-
Node *node1 = owner1->get();
96-
Node *node2 = owner2->get();
97-
if (!node1 || !node2) {
98-
throw std::out_of_range{"Index out of range!"};
84+
void List::connectNodes(unsigned int index1, unsigned int index2)
85+
{
86+
if (index1 == index2 || index1 >= count || index2 >= count) {
87+
throw std::out_of_range{"Index out of range!"};
9988
}
100-
if (node1->next.get() == node2) {
101-
return;
102-
}
103-
auto moving = std::move(*owner2);
104-
*owner2 = std::move(moving->next);
105-
moving->next = std::move(node1->next);
106-
node1->next = std::move(moving);
107-
return;
108-
}
10989

110-
auto *owner2 = ownerAt(index2);
111-
if (!owner2) {
112-
throw std::out_of_range{"Index out of range!"};
113-
}
114-
auto moving = std::move(*owner2);
115-
*owner2 = std::move(moving->next);
90+
auto requireOwner = [&](unsigned int idx) {
91+
if (auto* o = ownerAt(idx)) return o;
92+
throw std::out_of_range{"Index out of range!"};
93+
};
94+
95+
auto detachAt = [&](unsigned int idx) -> std::unique_ptr<Node> {
96+
auto* owner = requireOwner(idx); // owner points to the unique_ptr that owns node idx
97+
auto moving = std::move(*owner); // take node idx
98+
*owner = std::move(moving->next); // owner now owns the remainder
99+
moving->next = nullptr; // optional: make it explicit it's detached
100+
return moving;
101+
};
102+
103+
auto insertAfter = [&](unsigned int idx, std::unique_ptr<Node> moving) {
104+
auto* owner = requireOwner(idx);
105+
Node* node = owner->get();
106+
if (!node) throw std::out_of_range{"Index out of range!"};
107+
108+
moving->next = std::move(node->next);
109+
node->next = std::move(moving);
110+
};
111+
112+
// - if index1 < index2: move node at index2 after node at index1, unless already adjacent
113+
// - else: move node at index2 after node at (index1 - 1)
114+
if (index1 < index2) {
115+
auto* owner1 = requireOwner(index1);
116+
auto* owner2 = requireOwner(index2);
117+
118+
Node* node1 = owner1->get();
119+
Node* node2 = owner2->get();
120+
if (!node1 || !node2) throw std::out_of_range{"Index out of range!"};
121+
122+
if (node1->next.get() == node2) {
123+
return; // already connected in desired way
124+
}
125+
126+
insertAfter(index1, detachAt(index2));
127+
return;
128+
}
116129

117-
auto *owner1 = ownerAt(index1 - 1);
118-
if (!owner1) {
119-
throw std::out_of_range{"Index out of range!"};
120-
}
121-
Node *node1 = owner1->get();
122-
if (!node1) {
123-
throw std::out_of_range{"Index out of range!"};
124-
}
125-
moving->next = std::move(node1->next);
126-
node1->next = std::move(moving);
130+
// index1 > index2
131+
if (index1 == 0) { // defensive: would underflow (even though bounds might already prevent it)
132+
throw std::out_of_range{"Index out of range!"};
133+
}
134+
insertAfter(index1 - 1, detachAt(index2));
127135
}
128136

129137
void List::print() const {

0 commit comments

Comments
 (0)