Thanks for all the feedback, I optimized the code here.
Here I'm Writing a very simple Queue of struct Nodes with only these methods get_front()
, get_back()
, pop_front()
, push_back()
, print
. I hope using namespace std;
is okay, I will note it should not be used this way in production and I am only using the approach to write my code as quickly as possible so I can have more time to test and refactor while I discuss the code with my interviewer.
This is not for production and is to be treated as code that could be used in an interview or a quick and dirty prototype. I'm really curious about the approach I've taken here to keep track of the size, empty status, and back and front pointers, and use of only previous in my Node struct instead of next and previous pointers. I felt having both was not needed and previous makes more sense for a queue.
I'd like to know also if my member functions for the Queue have any edge cases I am not catching and any improvements I can make to run time efficiency. Anyway I can simplify this code further with c++11 features, shorter variable names or any other suggestions would be appreciated too.
Lastly if you optionally would like to share the memory/space complexity for my code that would be a huge help! I have noted some examples in the member data of my Node struct.
#include <iostream>
using namespace std;
struct Node
{
int data; // 4 bytes for primatives
Node* previous; // 8 bytes for pointers
Node(int data) : data(data), previous(nullptr) { }
};
struct Queue
{
Node* queue;
int size;
bool is_empty;
Node* front;
Node* back;
Queue() : queue(nullptr), size(0), is_empty(true), front(nullptr), back(nullptr) { }
string get_front() {
if (front == nullptr) {
return "empty";
}
else {
return to_string(front->data);
}
}
string get_back() {
if (back == nullptr) {
return "empty";
}
else {
return to_string(back->data);
}
}
void push_back(int data, Node* current) {
if (current->previous == nullptr) {
Node* n = new Node(data);
current->previous = n;
back = n;
}
else {
push_back(data, current->previous);
}
}
void push_back(int data) {
if (is_empty) {
queue = new Node(data);
back = queue;
front = queue;
is_empty = false;
}
else {
push_back(data, queue);
}
size++;
}
void pop_front() {
size--;
if (front->previous == nullptr) {
front = nullptr;
back = nullptr;
delete queue;
is_empty = true;
}
else {
Node* dangling = front;
front = front->previous;
delete dangling;
}
}
void print(Node* current, string queue_string) {
if (current->previous == nullptr) {
queue_string = to_string(current->data) + " " + queue_string;
cout << queue_string << endl;
}
else {
queue_string = to_string(current->data) + " " + queue_string;
print(current->previous, queue_string);
}
}
void print() {
if (is_empty) {
cout << "_____________\n\n";
cout << "_____________\n";
}
else {
cout << "_____________\n";
print(front, "");
cout << "_____________\n";
}
}
};
int main()
{
Queue queue;
queue.push_back(9);
queue.push_back(8);
queue.push_back(7);
queue.push_back(6);
queue.push_back(5);
queue.print();
cout << "front " << queue.get_front() << endl;
cout << "back " << queue.get_back() << endl;
cout << "size " << to_string(queue.size) << endl;
cout << boolalpha << "queue empty status is " << queue.is_empty << endl;
queue.pop_front();
queue.pop_front();
queue.pop_front();
queue.print();
cout << "front " << queue.get_front() << endl;
cout << "back " << queue.get_back() << endl;
cout << "size " << to_string(queue.size) << endl;
cout << "queue empty status is " << queue.is_empty << endl;
queue.pop_front();
queue.pop_front();
queue.print();
cout << "front " << queue.get_front() << endl;
cout << "back " << queue.get_back() << endl;
cout << "size " << to_string(queue.size) << endl;
cout << "queue empty status is " << queue.is_empty << endl;
}