Skip to content

Commit 9d9a245

Browse files
committed
improved implementation
1 parent 1bfc0c4 commit 9d9a245

File tree

2 files changed

+67
-73
lines changed

2 files changed

+67
-73
lines changed
+37-45
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,92 @@
11
#include<iostream>
2-
using namespace std;
2+
#include<memory>
3+
#include<cassert>
34

45
namespace my {
6+
const char endl = '\n';
57
/**
6-
* parameterised type implementation using linked list
7-
* [value][next] -> [value][next] -> ... -> [value][next] -> [value][next]
8-
* (front Node) (intermediat Nodes) (rear Node) (dummy Node)
8+
* implementation using linked list
9+
* [value][next] -> [value][next] -> ... -> [value][next]
10+
* (front Node) (intermediat Nodes) (rear Node)
911
*/
1012
template<typename T>
1113
struct Node {
1214
/**
1315
* next: will store right Node address
1416
*/
1517
T value;
16-
Node<T>* next;
17-
Node(const T& V) : value(V), next(nullptr) { }
18+
std::shared_ptr<Node<T>> next;
19+
Node(const T& V) : value(V) { }
1820
};
1921

2022
template<typename T>
2123
class queue {
2224
private:
2325
/**
24-
* _front : points to left most node
25-
* count: keeps track of current number of elements present in queue excluding dummy Node
26-
* rear: points to most recent Node added into the queue, which is just left size of dummy Node
26+
* front_pointer: points to left most node
27+
* count: keeps track of current number of elements present in queue
28+
* rear_pointer: points to most recent Node added into the queue, which is right most Node
2729
*/
28-
Node<T>* _front;
29-
Node<T>* rear;
30+
std::shared_ptr<Node<T>> front_pointer;
31+
std::shared_ptr<Node<T>> rear_pointer;
3032
size_t count;
3133
public:
32-
queue() : _front(nullptr), rear(nullptr), count(0ULL) {
33-
_front = rear = new Node<T>(0); // creating a dummy Node
34-
}
34+
queue() : count(0ULL) { }
3535

3636
void push(const T& element) {
37-
Node<T>* new_node = new Node<T>(element); // create New Node
37+
auto new_node = std::make_shared<Node<T>>(element);
3838
if (count > 0) {
39-
new_node->next = rear->next; // make new Node point to dummy Node
40-
rear->next = new_node; // make rear Node point to new Node
41-
rear = new_node; // make rear Node's pointer to point to new Node
39+
new_node->next = front_pointer;
40+
front_pointer = new_node;
4241
} else {
43-
new_node->next = rear;
44-
rear = _front = new_node;
42+
rear_pointer = front_pointer = new_node;
4543
}
4644
count = count + 1;
4745
}
4846

4947
void dequeue() {
50-
if (count > 0) {
51-
Node<T>* buffer = _front;
52-
_front = _front->next;
48+
if (count > 1) {
49+
front_pointer = front_pointer->next;
50+
count = count - 1;
51+
} else if (count == 1) {
52+
front_pointer.reset();
53+
rear_pointer.reset();
5354
count = count - 1;
54-
delete buffer;
5555
}
56-
rear = (count != 0) ? rear : _front;
5756
}
5857

59-
T& front() const { return _front->value; }
60-
T const& front() const { return _front->value; }
58+
T& front() {
59+
assert(count > 0 && "calling front on an empty queue");
60+
return front_pointer->value;
61+
}
62+
63+
T const& front() const {
64+
assert(count > 0 && "calling front on an empty queue");
65+
return front_pointer->value;
66+
}
6167

6268
size_t size() const { return count; }
6369

6470
bool empty() const { return count == 0; }
6571

6672
~queue() {
67-
for (Node<T>* pointer = _front; pointer != nullptr;) {
68-
Node<T>* buffer = pointer;
69-
pointer = pointer->next;
70-
delete buffer;
73+
while (front_pointer.get() != nullptr) {
74+
front_pointer = front_pointer->next;
7175
}
7276
}
7377
};
7478
}
7579

7680
int main() {
7781
my::queue<int> Q;
78-
7982
Q.push(0);
80-
Q.push(1);
81-
Q.push(2);
8283
Q.push(3);
83-
cout << "count: " << Q.size() << endl;
84+
std::cout << "count: " << Q.size() << my::endl;
8485
Q.front() = 10;
8586

8687
while (Q.empty() != true) {
87-
cout << "element: " << Q.front() << endl;
88-
Q.dequeue();
89-
}
90-
91-
Q.push(3);
92-
Q.push(6);
93-
cout << "count: " << Q.size() << endl;
94-
while (Q.empty() != true) {
95-
cout << "element: " << Q.front() << endl;
88+
std::cout << "element: " << Q.front() << my::endl;
9689
Q.dequeue();
9790
}
9891
return 0;
9992
}
100-

contents/stacks_and_queues/code/c++/stack.cpp

+30-28
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,81 @@
11
#include<iostream>
2-
using namespace std;
2+
#include<cassert>
3+
#include<memory>
34

45
namespace my {
6+
const char endl = '\n';
57
/**
6-
*implementation using parameterised linked list
8+
* implementation using linked list
79
* [value][next] -> [value][next] -> ... -> [value][next]
8-
* (top Node) (intermediat Nodes) (dummy Node)
10+
* (top Node) (intermediat Nodes)
11+
* left most Node represents top element of stack
912
*/
1013
template<typename T>
1114
struct Node {
1215
/**
1316
* next: will store right Node address
1417
*/
1518
T value;
16-
Node<T>* next;
17-
Node(const T& V) : value(V), next(nullptr) { }
19+
std::unique_ptr<Node<T>> next;
20+
Node(const T& V) : value(V) { }
1821
};
1922

2023
template<typename T>
2124
class stack {
2225
private:
2326
/**
24-
* _top: points to left most node
25-
* count: keeps track of current number of elements present in stack excluding dummy Node
27+
* top_pointer: points to left most node
28+
* count: keeps track of current number of elements present in stack
2629
*/
27-
Node<T>* _top;
30+
std::unique_ptr<Node<T>> top_pointer;
2831
size_t count;
2932
public:
30-
stack() : _top(nullptr), count(0ULL) {
31-
_top = new Node<T>(0); // creating a dummy node
32-
}
33+
stack() : count(0ULL) { }
3334

3435
void push(const T& element) {
35-
Node<T>* buffer = new Node<T>(element);
36-
buffer->next = _top;
37-
_top = buffer;
36+
auto new_node = std::make_unique<Node<T>>(element);
37+
new_node->next = std::move(top_pointer);
38+
top_pointer = std::move(new_node);
3839
count = count + 1;
3940
}
4041

4142
void pop() {
4243
if (count > 0) {
43-
Node<T>* buffer = _top;
44-
_top = _top->next;
44+
top_pointer = std::move(top_pointer->next);
4545
count = count - 1;
46-
delete buffer;
4746
}
4847
}
4948

50-
T& top() const { return _top->value; }
51-
// returning reference can very usefull if someone wants to modify top element
49+
T& top() {
50+
assert(count > 0 and "calling top() on an empty stack");
51+
return top_pointer->value;
52+
}
53+
// returning mutable reference can very be usefull if someone wants to modify top element
54+
55+
T const& top() const {
56+
assert(count > 0 and "calling top() on an empty stack");
57+
return top_pointer->value;
58+
}
5259

5360
size_t size() const { return count; }
5461

5562
bool empty() const { return count == 0; }
5663

5764
~stack() {
58-
for (Node<T>* pointer = _top; pointer != nullptr;) {
59-
Node<T>* buffer = pointer;
60-
pointer = pointer->next;
61-
delete buffer;
65+
while (top_pointer.get() != nullptr) {
66+
top_pointer = std::move(top_pointer->next);
6267
}
6368
}
6469
};
6570
}
6671

6772
int main() {
6873
my::stack<int> S;
69-
S.push(0);
70-
S.push(1);
71-
S.push(2);
7274
S.push(3);
73-
cout << "size: " << S.size() << endl;
75+
std::cout << "size: " << S.size() << my::endl;
7476
S.top() = 10;
7577
while (S.empty() != true) {
76-
cout << "element: " << S.top() << endl;
78+
std::cout << "element: " << S.top() << my::endl;
7779
S.pop();
7880
}
7981
return 0;

0 commit comments

Comments
 (0)