#ifndef _UTIL_LINKED_LIST_H #define _UTIL_LINKED_LIST_H #include #include #include #include template struct LinkedList { T d; struct LinkedList* prev; struct LinkedList* next; }; template bool linked_list_append(struct LinkedList*& list, T* data = nullptr, struct LinkedList** tail = nullptr) { bool have_list = list; struct LinkedList* tmp = (struct LinkedList*)malloc(sizeof(LinkedList)); if (!tmp) return false; memset(tmp, 0, sizeof(LinkedList)); if (data) tmp->d = *data; else tmp->d = T(); if (!have_list) { list = tmp; } else { struct LinkedList* t = list; while (t->next) t = t->next; t->next = tmp; tmp->prev = t; } if (tail) *tail = tmp; return true; } template bool linked_list_append(struct LinkedList*& list, struct LinkedList** tail) { return linked_list_append(list, (T*)nullptr, tail); } template bool linked_list_append_head(struct LinkedList*& list, T* data = nullptr) { bool have_list = list; struct LinkedList* tmp = (struct LinkedList*)malloc(sizeof(LinkedList)); if (!tmp) return false; memset(tmp, 0, sizeof(LinkedList)); if (data) tmp->d = *data; else tmp->d = T(); if (have_list) { tmp->next = list; list->prev = tmp; } list = tmp; return true; } template bool linked_list_append_list(struct LinkedList*& list, struct LinkedList* list2, bool(*compare_func)(T, T, Args...) = nullptr, Args... args) { if (!list2) return true; struct LinkedList* t = list2; struct LinkedList* tail = linked_list_tail(list); if (!compare_func || !linked_list_have(list, t->d, compare_func, args...)) { if (!linked_list_append(list, &t->d)) return false; } while (t->next) { t = t->next; if (!compare_func || !linked_list_have(list, t->d, compare_func, args...)) { if (!linked_list_append(list, &t->d)) { if (tail == nullptr) { linked_list_clear(list); } else { if (tail->next) linked_list_clear(tail->next); } return false; } } } return true; } template void linked_list_clear(struct LinkedList*& list, void(*free_func)(T) = nullptr) { if (!list) return; struct LinkedList* t = list; struct LinkedList* tmp = nullptr; if (free_func) free_func(t->d); while (t->next) { tmp = t; t = t->next; free(tmp); if (free_func) free_func(t->d); } free(t); list = nullptr; } template size_t linked_list_count(struct LinkedList* list) { if (!list) return 0; struct LinkedList* t = list; size_t c = 1; while (t->next) { t = t->next; c += 1; } if (list->prev) { t = t->prev; c += 1; while (t->prev) { t = t->prev; c += 1; } } return c; } template bool linked_list_delete(struct LinkedList*& list, T data) { if (!list) return false; struct LinkedList* t = list; while (t->prev) { t = t->prev; } if (t->d == data) { if (t->prev) t->prev->next = t->next; if (t->next) t->next->prev = t->prev; if (t == list) { if (t->prev) { list = t->prev; } else if (t->next) { list = t->next; } else { list = nullptr; } } free(t); return true; } while (t->next) { t = t->next; if (t->d == data) { if (t->prev) t->prev->next = t->next; if (t->next) t->next->prev = t->prev; if (t == list) { if (t->prev) { list = t->prev; } else if (t->next) { list = t->next; } else { list = nullptr; } } free(t); return true; } } return false; } template bool linked_list_delete(struct LinkedList*& list, D data, bool(*is_same)(T, D)) { if (!list || !is_same) return false; struct LinkedList* t = list; while (t->prev) { t = t->prev; } if (is_same(t->d, data)) { if (t->prev) t->prev->next = t->next; if (t->next) t->next->prev = t->prev; if (t == list) { if (t->prev) { list = t->prev; } else if (t->next) { list = t->next; } else { list = nullptr; } } free(t); return true; } while (t->next) { t = t->next; if (is_same(t->d, data)) { if (t->prev) t->prev->next = t->next; if (t->next) t->next->prev = t->prev; if (t == list) { if (t->prev) { list = t->prev; } else if (t->next) { list = t->next; } else { list = nullptr; } } free(t); return true; } } return false; } template void linked_list_free_tail(struct LinkedList*& list, void(*free_func)(T) = nullptr) { if (!list) return; struct LinkedList* t = linked_list_tail(list); if (t == list) { linked_list_clear(list, free_func); } else { if (free_func) free_func(t->d); if (t->prev) { t->prev->next = nullptr; } free(t); } } template struct LinkedList* linked_list_get(struct LinkedList* list, D data, bool(*compare_func)(T, D, Args...), Args ... args) { if (!list || !compare_func) return nullptr; struct LinkedList* t = list; while (t->prev) { t = t->prev; } if (compare_func(t->d, data, args...)) return t; while (t->next) { t = t->next; if (compare_func(t->d, data, args...)) return t; } return nullptr; } template struct LinkedList* linked_list_get(struct LinkedList* list, size_t index) { if (!list) return nullptr; struct LinkedList* t = list; while (t->prev) { t = t->prev; } size_t n = 0; if (index == n) return t; while (t->next) { t = t->next; n++; if (index == n) return t; } return nullptr; } template bool linked_list_have(struct LinkedList* list, T data) { if (!list) return false; struct LinkedList* t = list; if (t->d == data) return true; while (t->next) { t = t->next; if (t->d == data) return true; } return false; } template bool linked_list_have(struct LinkedList* list, T data, bool(*compare_func)(T, T, Args...), Args... args) { if (!list || !compare_func) return false; struct LinkedList* t = list; if (compare_func(t->d, data, args...)) return true; while (t->next) { t = t->next; if (compare_func(t->d, data, args...)) return true; } return false; } template bool linked_list_have(struct LinkedList* list, D data, bool(*compare_func)(T, D, Args...), Args... args) { if (!list || !compare_func) return false; struct LinkedList* t = list; if (compare_func(t->d, data, args...)) return true; while (t->next) { t = t->next; if (compare_func(t->d, data, args...)) return true; } return false; } template struct LinkedList* linked_list_head(struct LinkedList* list) { if (!list) return nullptr; struct LinkedList* t = list; while (t->prev) { t = t->prev; } return t; } template void linked_list_iter(struct LinkedList* list, void(*callback)(size_t index, T data, Args... args), Args... args) { if (!list || !callback) return; size_t i = 0; struct LinkedList* t = list; callback(i, t->d, args...); while (t->next) { t = t->next; i++; callback(i, t->d, args...); } } template void linked_list_iter(struct LinkedList* list, void(*callback)(T data, Args... args), Args... args) { if (!list || !callback) return; struct LinkedList* t = list; callback(t->d, args...); while (t->next) { t = t->next; callback(t->d, args...); } } template D linked_list_iter(struct LinkedList* list, D(*callback)(T data, Args... args), D failed, Args... args) { if (!list || !callback) return failed; struct LinkedList* t = list; D re = callback(t->d, args...); if (re == failed) return re; while (t->next) { t = t->next; re = callback(t->d, args...); if (re == failed) return re; } return re; } template void linked_list_remove(struct LinkedList*& node, void(*free_func)(T) = nullptr) { if (!node) return; if (node->prev) { node->prev->next = node->next; } if (node->next) { node->next->prev = node->prev; } if (free_func) free_func(node->d); free(node); node = nullptr; } template void linked_list_remove_before(struct LinkedList* node, void(*free_func)(T) = nullptr) { if (!node) return; while (node->prev) { struct LinkedList* cur = node->prev; linked_list_remove(cur, free_func); } } template struct LinkedList* linked_list_tail(struct LinkedList* list) { if (!list) return nullptr; struct LinkedList* t = list; while (t->next) { t = t->next; } return t; } #endif