mirror of
https://github.com/lifegpc/c-utils.git
synced 2026-07-08 01:30:39 +08:00
Add LinkedQueue
This commit is contained in:
97
linked_queue.h
Normal file
97
linked_queue.h
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
#ifndef _UTIL_LINKED_QUEUE_H
|
||||||
|
#define _UTIL_LINKED_QUEUE_H
|
||||||
|
#include <functional>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct LinkedQueueNode {
|
||||||
|
T d;
|
||||||
|
struct LinkedQueueNode* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct LinkedQueue {
|
||||||
|
struct LinkedQueueNode<T>* front;
|
||||||
|
struct LinkedQueueNode<T>* rear;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
size_t linked_queue_length(struct LinkedQueue<T>& queue) {
|
||||||
|
if (!queue.front) return 0;
|
||||||
|
struct LinkedQueueNode<T>* node = queue.front;
|
||||||
|
size_t i = 1;
|
||||||
|
while (node->next) {
|
||||||
|
node = node->next;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void free_linked_queue(struct LinkedQueue<T>& queue, std::function<void(T)> free_func = std::function<void(T)>()) {
|
||||||
|
if (!queue.front) return;
|
||||||
|
struct LinkedQueueNode<T>* node = queue.front, *tmp = queue.front;
|
||||||
|
do {
|
||||||
|
tmp = node;
|
||||||
|
node = node->next;
|
||||||
|
if (free_func) {
|
||||||
|
free_func(tmp->d);
|
||||||
|
}
|
||||||
|
free(tmp);
|
||||||
|
} while (node);
|
||||||
|
queue.front = nullptr;
|
||||||
|
queue.rear = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, class F>
|
||||||
|
inline void free_linked_queue(struct LinkedQueue<T>& queue, F free_func) {
|
||||||
|
free_linked_queue(queue, std::function<void(T)>(free_func));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool linked_queue_push(struct LinkedQueue<T>& queue, T data) {
|
||||||
|
struct LinkedQueueNode<T>* node = (struct LinkedQueueNode<T>*)malloc(sizeof(struct LinkedQueueNode<T>));
|
||||||
|
if (!node) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
node->d = data;
|
||||||
|
node->next = nullptr;
|
||||||
|
if (queue.rear) {
|
||||||
|
queue.rear->next = node;
|
||||||
|
} else {
|
||||||
|
queue.front = node;
|
||||||
|
}
|
||||||
|
queue.rear = node;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool linked_queue_pop(struct LinkedQueue<T>& queue, T& data) {
|
||||||
|
if (!queue.front) return false;
|
||||||
|
data = queue.front->d;
|
||||||
|
struct LinkedQueueNode<T>* tmp = queue.front;
|
||||||
|
if (!tmp->next) {
|
||||||
|
queue.rear = nullptr;
|
||||||
|
}
|
||||||
|
queue.front = tmp->next;
|
||||||
|
free(tmp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename ...Args>
|
||||||
|
void linked_queue_iter(struct LinkedQueue<T>& queue, std::function<void(T, Args...)> callback, Args... args) {
|
||||||
|
if (!queue.front || !callback) return;
|
||||||
|
struct LinkedQueueNode<T>* node = queue.front;
|
||||||
|
do {
|
||||||
|
callback(node->d, args...);
|
||||||
|
node = node->next;
|
||||||
|
} while (node);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, class F, typename ...Args>
|
||||||
|
inline void linked_queue_iter(struct LinkedQueue<T>& queue, F callback, Args... args) {
|
||||||
|
linked_queue_iter(queue, std::function<void(T, Args...)>(callback), args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "circular_queue.h"
|
#include "circular_queue.h"
|
||||||
|
#include "linked_queue.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
TEST(Queue_Test, CircularQueue1) {
|
TEST(Queue_Test, CircularQueue1) {
|
||||||
@@ -81,3 +82,26 @@ TEST(Queue_Test, CircularQueue2) {
|
|||||||
EXPECT_EQ(text, "2,3,4,5");
|
EXPECT_EQ(text, "2,3,4,5");
|
||||||
free_circular_queue(queue);
|
free_circular_queue(queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Queue_Test, LinkedQueue1) {
|
||||||
|
struct LinkedQueue<int> queue;
|
||||||
|
queue.front = nullptr;
|
||||||
|
queue.rear = nullptr;
|
||||||
|
EXPECT_EQ(linked_queue_push(queue, 3), true);
|
||||||
|
EXPECT_EQ(linked_queue_push(queue, 4), true);
|
||||||
|
EXPECT_EQ(linked_queue_push(queue, 9), true);
|
||||||
|
int v;
|
||||||
|
EXPECT_EQ(linked_queue_pop(queue, v), true);
|
||||||
|
EXPECT_EQ(v, 3);
|
||||||
|
EXPECT_EQ(linked_queue_push(queue, 7), true);
|
||||||
|
EXPECT_EQ(linked_queue_length(queue), 3);
|
||||||
|
std::string text = "";
|
||||||
|
linked_queue_iter(queue, [&text](int ele) {
|
||||||
|
if (!text.empty()) {
|
||||||
|
text += ",";
|
||||||
|
}
|
||||||
|
text += std::to_string(ele);
|
||||||
|
});
|
||||||
|
EXPECT_EQ(text, "4,9,7");
|
||||||
|
free_linked_queue(queue);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user