Ну, в моем случае я использую поле для хранения размера списка, но это можно сделать и без него, вот моя реализация для очереди, я добавил несколько комментариев для ясности, может быть, вы найдете это полезным. и я добавил всего несколько функций, вы можете добавить больше, если хотите, это просто для запуска:)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
// make an alias for better readability
typedef char * String;
typedef struct node_struct {
String data;
struct node_struct *next;
} Node;
typedef struct queue_struct {
Node *head, *tail;
} Queue;
// create a new node, allocating the memory and copying the value...
Node * Node_create(String str) {
Node *node = (Node *)malloc(sizeof(Node));
if(node == NULL) return NULL;
node->data = (String)malloc(strlen(str) + 1);
if(node->data == NULL) return NULL;
strcpy(node->data, str);
node->next = NULL;
return node;
}
// delete the node
void Node_delete(Node *node) {
free(node->data);
free(node);
}
// create a new Queue and set the head and tail to NULL(empty)
Queue * Queue_create() {
Queue *queue = (Queue *)malloc(sizeof(Queue));
if(queue == NULL) return NULL;
queue->head = queue->tail = NULL;
return queue;
}
// add a new node to the queue
bool Queue_push(Queue *q, String str) {
Node* node = Node_create(str);
if(node == NULL) return false;
// empty queue
if(q->head == NULL) {
q->head = q->tail = node;
// has only one element
}else if(q->head == q->tail) {
q->head->next = q->tail = node;
// has more than one element
}else {
q->tail->next = node;
q->tail = q->tail->next;
}
return true;
}
// print the elements of the queue
void Queue_print(Queue *q) {
Node *tmpNode = q->head;
printf("{");
// loop over the queue
while(tmpNode != NULL) {
printf("%s", tmpNode->data);
// don't print ',' if its the last element
tmpNode != q->tail && printf(", ");
tmpNode = tmpNode->next;
}
printf("}");
}
// get the size of the queue
int Queue_size(Queue *q) {
Node *tmpNode = q->head;
int size = 0;
while(tmpNode != NULL) {
tmpNode = tmpNode->next;
size++;
}
return size;
}
// remove the last element in the queue
String Queue_pop(Queue *q) {
String s = NULL;
// empty queue
if(q->head == NULL) return s;
// has one element
if(q->head == q->tail) {
s = q->head->data;
Node_delete(q->head);
q->head = q->tail = NULL;
// has two elements
}else if(q->head->next == q->tail) {
s = q->tail->data;
Node_delete(q->tail);
q->tail = q->head;
q->head->next = q->tail;
q->tail->next = NULL;
// has more than two
}else {
s = q->tail->data;
Node *tmpNode = q->head, *lastNode;
// loop over the queue and get the element before the last one
while(tmpNode != NULL) {
lastNode = tmpNode;
tmpNode = tmpNode->next;
// delete the last element and replace it with the previous element
if(tmpNode == q->tail) {
Node_delete(q->tail);
q->tail = lastNode;
q->tail->next = NULL;
return s;
}
}
}
return s;
}
// remove the first element in the queue
String Queue_shift(Queue *q) {
String s = NULL;
// empty queue
if(q->head == NULL) return NULL;
// has one element
if(q->head == q->tail) {
s = q->head->data;
Node_delete(q->head);
q->head = q->tail = NULL;
// has more than one
} else {
// just delete the first element and replace it with the next one
Node *tmpNode = q->head->next;
s = q->head->data;
Node_delete(q->head);
q->head = tmpNode;
}
return s;
}
// remove all the elements in the queue
void Queue_clear(Queue *q) {
Node *tmpNode = q->head;
for(int i = 0, n = Queue_size(q);i < n; i++) {
tmpNode = tmpNode->next;
// using the Queue_shift instead of Queue_pop because it's faster(low processing cost)
Queue_shift(q);
}
}
// remove all the elements in the queue and free the memory of the queue
void Queue_delete(Queue *q) {
Queue_clear(q);
free(q);
}
// check if the queue is empty
bool Queue_isEmpty(Queue *q) {
return q->head == NULL;
}
int main(void) {
Queue *a = Queue_create();
printf("Is empty: %s\n", Queue_isEmpty(a) ? "true" : "false");
Queue_push(a, "txt1");
printf("Size: %d\n", Queue_size(a));
printf("Is empty: %s\n", Queue_isEmpty(a) ? "true" : "false");
Queue_push(a, "txt2");
Queue_push(a, "txt3");
Queue_print(a);
Queue_shift(a);
printf("\nSize: %d\n", Queue_size(a));
Queue_pop(a);
Queue_push(a, "txt4");
Queue_push(a, "txt5");
printf("Size: %d\n", Queue_size(a));
Queue_print(a);
Queue_clear(a);
printf("\nSize: %d\n", Queue_size(a));
Queue_print(a);
Queue_push(a, "txt");
printf("\nSize: %d\n", Queue_size(a));
Queue_print(a);
Queue_delete(a);
return 0;
}
вывод
Is empty: true
Size: 1
Is empty: false
{txt1, txt2, txt3}
Size: 2
Size: 3
{txt2, txt4, txt5}
Size: 0
{}
Size: 1
{txt}
Хорошо, согласно вашему комментарию:
Я сейчас экспериментирую с вашей версией прямо сейчас, я хочу спросить, не хочу ли я использовать Queue * a = Queue_create (); в основной функции, но вместо этого я хочу сделать Queue * a = NULL; а затем выделите для него место в функции pu sh. Как бы вы это сделали?
Вы можете сделать это таким образом, обратите внимание, что вы все равно можете использовать другие функции таким же образом без каких-либо изменений. и даже вы все еще можете использовать Queue_create Directly как Queue *q = Queue_create();
как в первой части.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
// make an alias for better readability
typedef char * String;
typedef struct node_struct {
String data;
struct node_struct *next;
} Node;
typedef struct queue_struct {
Node *head, *tail;
} Queue;
// create a new node, allocating the memory and copying the value...
Node * Node_create(String str) {
Node *node = (Node *)malloc(sizeof(Node));
if(node == NULL) return NULL;
node->data = (String)malloc(strlen(str) + 1);
if(node->data == NULL) return NULL;
strcpy(node->data, str);
node->next = NULL;
return node;
}
// delete the node
void Node_delete(Node *node) {
free(node->data);
free(node);
}
// create a new Queue and set the head and tail to NULL(empty)
Queue * Queue_create() {
Queue *queue = (Queue *)malloc(sizeof(Queue));
if(queue == NULL) return NULL;
queue->head = queue->tail = NULL;
return queue;
}
// add a new node to the queue
bool Queue_push(Queue **q, String str) {
// if there is no allocated Queue then we need to allocate one using the Queue_create() we already have
if(*q == NULL) {
*q = Queue_create();
if(*q == NULL) return false;
}
Node* node = Node_create(str);
if(node == NULL) return false;
// empty queue
if((*q)->head == NULL) {
(*q)->head = (*q)->tail = node;
// has only one element
}else if((*q)->head == (*q)->tail) {
(*q)->head->next = (*q)->tail = node;
// has more than one element
}else {
(*q)->tail->next = node;
(*q)->tail = (*q)->tail->next;
}
return true;
}
// print the elements of the queue
void Queue_print(Queue *q) {
if(q != NULL) {
Node *tmpNode = q->head;
printf("{");
// loop over the queue
while(tmpNode != NULL) {
printf("%s", tmpNode->data);
// don't print ',' if its the last element
tmpNode != q->tail && printf(", ");
tmpNode = tmpNode->next;
}
printf("}");
}
}
// get the size of the queue
int Queue_size(Queue *q) {
if(q == NULL) return 0;
Node *tmpNode = q->head;
int size = 0;
while(tmpNode != NULL) {
tmpNode = tmpNode->next;
size++;
}
return size;
}
// remove the last element in the queue
String Queue_pop(Queue *q) {
if(q == NULL) return NULL;
String s = NULL;
// empty queue
if(q->head == NULL) return s;
// has one element
if(q->head == q->tail) {
s = q->head->data;
Node_delete(q->head);
q->head = q->tail = NULL;
// has two elements
}else if(q->head->next == q->tail) {
s = q->tail->data;
Node_delete(q->tail);
q->tail = q->head;
q->head->next = q->tail;
q->tail->next = NULL;
// has more than two
}else {
s = q->tail->data;
Node *tmpNode = q->head, *lastNode;
// loop over the queue and get the element before the last one
while(tmpNode != NULL) {
lastNode = tmpNode;
tmpNode = tmpNode->next;
// delete the last element and replace it with the previous element
if(tmpNode == q->tail) {
Node_delete(q->tail);
q->tail = lastNode;
q->tail->next = NULL;
return s;
}
}
}
return s;
}
// remove the first element in the queue
String Queue_shift(Queue *q) {
if(q == NULL) return NULL;
String s = NULL;
// empty queue
if(q->head == NULL) return NULL;
// has one element
if(q->head == q->tail) {
s = q->head->data;
Node_delete(q->head);
q->head = q->tail = NULL;
// has more than one
} else {
// just delete the first element and replace it with the next one
Node *tmpNode = q->head->next;
s = q->head->data;
Node_delete(q->head);
q->head = tmpNode;
}
return s;
}
// remove all the elements in the queue
void Queue_clear(Queue *q) {
if(q != NULL) {
Node *tmpNode = q->head;
for(int i = 0, n = Queue_size(q);i < n; i++) {
tmpNode = tmpNode->next;
// using the Queue_shift instead of Queue_pop because it's faster(low processing cost)
Queue_shift(q);
}
}
}
// remove all the elements in the queue and free the memory of the queue
void Queue_delete(Queue *q) {
if(q != NULL) {
Queue_clear(q);
free(q);
}
}
// check if the queue is empty
bool Queue_isEmpty(Queue *q) {
return q == NULL || q->head == NULL;
}
int main(void) {
Queue *a = NULL;
Queue_print(a);
printf("Is empty: %s\n", Queue_isEmpty(a) ? "true" : "false");
Queue_push(&a, "txt1");
printf("Size: %d\n", Queue_size(a));
printf("Is empty: %s\n", Queue_isEmpty(a) ? "true" : "false");
Queue_push(&a, "txt2");
Queue_push(&a, "txt3");
Queue_print(a);
Queue_shift(a);
printf("\nSize: %d\n", Queue_size(a));
Queue_pop(a);
Queue_push(&a, "txt4");
Queue_push(&a, "txt5");
printf("Size: %d\n", Queue_size(a));
Queue_print(a);
Queue_clear(a);
printf("\nSize: %d\n", Queue_size(a));
Queue_print(a);
Queue_push(&a, "txt");
printf("\nSize: %d\n", Queue_size(a));
Queue_print(a);
Queue_delete(a);
return 0;
}
output
Is empty: true
Size: 1
Is empty: false
{txt1, txt2, txt3}
Size: 2
Size: 3
{txt2, txt4, txt5}
Size: 0
{}
Size: 1
{txt}