patterncMinor
Designing stack and queue from scratch in C
Viewed 0 times
scratchstackdesigningandfromqueue
Problem
As a beginner and curious guy I'm interested in implementing data structures and algorithms from scratch. Here's my implementation of Stack and Queue, the most fundamental data structures.
Are there are any mistakes/ memory leaks in the code that I have missed? How I can improve my implementation.
```
#include
#include
typedef struct NODE {
int data;
struct NODE *next_node;
} NODE;
NODE check_queue(NODE head);
NODE check_stack(NODE head);
void push_node(NODE **head, int value);
void enqueue_node(NODE head, int value, NODE tail);
int pop(NODE **s_head);
int dequeue(NODE **q_head);
void print_stack(NODE *head);
void print_queue(NODE *head);
void free_memory(NODE **head);
int main(){
NODE *Q_head = NULL;
NODE *Q_tail = NULL;
NODE *S_head = NULL;
/operations here/
return 0;
}
/----- check functions for queue and stack if empty-----------/
NODE check_queue(NODE head){
return head;
}
NODE check_stack(NODE head){
return head;
}
/--------------------------------------------------------------/
void push_node(NODE **head, int value){
NODE *cache;
cache = (NODE *) malloc(sizeof(NODE));
cache->data = value;
/first commit / allocate a new head/
if ((*head) == NULL) {
cache->next_node = NULL;
(head) = cache; /assign the cache to head head*/
}
else {
/point to the previous head/
cache->next_node = (*head);
(*head) = cache;
}
}
void enqueue_node(NODE head, int value, NODE tail) {
NODE *cache;
cache = (NODE *) malloc(sizeof(NODE));
cache->data = value;
cache->next_node = NULL;
if ((head) == NULL && (tail) == NULL) {
(head) = cache; /assign the cache to head*/
/now assign tail the job as a cachet head and extends the queue/
(tail) = (head);
}
else {
/now tail is the representative of head and extened the queue/
(*tail)->next_node = cache;
Are there are any mistakes/ memory leaks in the code that I have missed? How I can improve my implementation.
```
#include
#include
typedef struct NODE {
int data;
struct NODE *next_node;
} NODE;
NODE check_queue(NODE head);
NODE check_stack(NODE head);
void push_node(NODE **head, int value);
void enqueue_node(NODE head, int value, NODE tail);
int pop(NODE **s_head);
int dequeue(NODE **q_head);
void print_stack(NODE *head);
void print_queue(NODE *head);
void free_memory(NODE **head);
int main(){
NODE *Q_head = NULL;
NODE *Q_tail = NULL;
NODE *S_head = NULL;
/operations here/
return 0;
}
/----- check functions for queue and stack if empty-----------/
NODE check_queue(NODE head){
return head;
}
NODE check_stack(NODE head){
return head;
}
/--------------------------------------------------------------/
void push_node(NODE **head, int value){
NODE *cache;
cache = (NODE *) malloc(sizeof(NODE));
cache->data = value;
/first commit / allocate a new head/
if ((*head) == NULL) {
cache->next_node = NULL;
(head) = cache; /assign the cache to head head*/
}
else {
/point to the previous head/
cache->next_node = (*head);
(*head) = cache;
}
}
void enqueue_node(NODE head, int value, NODE tail) {
NODE *cache;
cache = (NODE *) malloc(sizeof(NODE));
cache->data = value;
cache->next_node = NULL;
if ((head) == NULL && (tail) == NULL) {
(head) = cache; /assign the cache to head*/
/now assign tail the job as a cachet head and extends the queue/
(tail) = (head);
}
else {
/now tail is the representative of head and extened the queue/
(*tail)->next_node = cache;
Solution
casting and malloc
Unnecessary casting is generally frowned upon.
can just be
Bug
You've got a bug in your dequeue function. It doesn't update tail, which means that if you empty the queue, then start adding to it again you get errors.
Results in:
naming
It's a little odd that your push/enqueue methods have have a
heads and tails
I'd rather see the head and tail of the queue wrapped up together in a queue structure. This means that you only have to pass one parameter (the queue) into your enqueue/dequeue. It also means that if you decide to change the way you implement the queue, your clients aren't impacted.
Are Queues Stacks?
As you've implemented it, it's possible to call stack functions on queue nodes and queue functions on stack nodes. Is this really desirable? If not, then making the change above to introduce a
Unnecessary casting is generally frowned upon.
malloc returns a void*, so you don't need to cast it when you're assigned it.cache = (NODE *) malloc(sizeof(NODE));can just be
cache = malloc(sizeof(NODE));Bug
You've got a bug in your dequeue function. It doesn't update tail, which means that if you empty the queue, then start adding to it again you get errors.
enqueue_node(&Q_head, 1, &Q_tail);
printf("%d\n", dequeue(&Q_head));
enqueue_node(&Q_head, 1, &Q_tail);
printf("%d\n", dequeue(&Q_head));Results in:
1
queue is empty ! ! !
-1naming
It's a little odd that your push/enqueue methods have have a
_node postfix, but your pop/dequeue methods don't. I'd pick one and stick to it.heads and tails
I'd rather see the head and tail of the queue wrapped up together in a queue structure. This means that you only have to pass one parameter (the queue) into your enqueue/dequeue. It also means that if you decide to change the way you implement the queue, your clients aren't impacted.
Are Queues Stacks?
As you've implemented it, it's possible to call stack functions on queue nodes and queue functions on stack nodes. Is this really desirable? If not, then making the change above to introduce a
QUEUE structure that wraps a QNODE head and QNODE tail would mean that you would at least have some level of type safety and the compiler would warn you if you tried to call dequeue on your stack.Code Snippets
cache = (NODE *) malloc(sizeof(NODE));cache = malloc(sizeof(NODE));enqueue_node(&Q_head, 1, &Q_tail);
printf("%d\n", dequeue(&Q_head));
enqueue_node(&Q_head, 1, &Q_tail);
printf("%d\n", dequeue(&Q_head));1
queue is empty ! ! !
-1Context
StackExchange Code Review Q#135539, answer score: 5
Revisions (0)
No revisions yet.