📄 list.c
字号:
moved++; } /* assert no overflows */ assert (source->nodecount - moved <= source->nodecount); assert (dest->nodecount + moved >= dest->nodecount); /* assert no weirdness */ assert (moved <= source->nodecount); source->nodecount -= moved; dest->nodecount += moved; /* assert list sanity */ assert (list_verify(source)); assert (list_verify(dest));}void list_merge(list_t *dest, list_t *sour, int compare (const void *, const void *)){ lnode_t *dn, *sn, *tn; lnode_t *d_nil = list_nil(dest), *s_nil = list_nil(sour); /* Nothing to do if source and destination list are the same. */ if (dest == sour) return; /* overflow check */ assert (list_count(sour) + list_count(dest) >= list_count(sour)); /* lists must be sorted */ assert (list_is_sorted(sour, compare)); assert (list_is_sorted(dest, compare)); dn = list_first_priv(dest); sn = list_first_priv(sour); while (dn != d_nil && sn != s_nil) { if (compare(lnode_get(dn), lnode_get(sn)) >= 0) { tn = lnode_next(sn); list_delete(sour, sn); list_ins_before(dest, sn, dn); sn = tn; } else { dn = lnode_next(dn); } } if (dn != d_nil) return; if (sn != s_nil) list_transfer(dest, sour, sn);}void list_sort(list_t *list, int compare(const void *, const void *)){ list_t extra; listcount_t middle; lnode_t *node; if (list_count(list) > 1) { middle = list_count(list) / 2; node = list_first_priv(list); list_init(&extra, list_count(list) - middle); while (middle--) node = lnode_next(node); list_transfer(&extra, list, node); list_sort(list, compare); list_sort(&extra, compare); list_merge(list, &extra, compare); } assert (list_is_sorted(list, compare));}lnode_t *list_find(list_t *list, const void *key, int compare(const void *, const void *)){ lnode_t *node; for (node = list_first_priv(list); node != list_nil(list); node = node->next) { if (compare(lnode_get(node), key) == 0) return node; } return 0;}/* * Return 1 if the list is in sorted order, 0 otherwise */int list_is_sorted(list_t *list, int compare(const void *, const void *)){ lnode_t *node, *next, *nil; next = nil = list_nil(list); node = list_first_priv(list); if (node != nil) next = lnode_next(node); for (; next != nil; node = next, next = lnode_next(next)) { if (compare(lnode_get(node), lnode_get(next)) > 0) return 0; } return 1;}/* * Get rid of macro functions definitions so they don't interfere * with the actual definitions */#undef list_isempty#undef list_isfull#undef lnode_pool_isempty#undef list_append#undef list_prepend#undef list_first#undef list_last#undef list_next#undef list_prev#undef list_count#undef list_del_first#undef list_del_last#undef lnode_put#undef lnode_get/* * Return 1 if the list is empty, 0 otherwise */int list_isempty(list_t *list){ return list->nodecount == 0;}/* * Return 1 if the list is full, 0 otherwise * Permitted only on bounded lists. */int list_isfull(list_t *list){ return list->nodecount == list->maxcount;}/* * Check if the node pool is empty. */int lnode_pool_isempty(lnodepool_t *pool){ return (pool->fre == NULL);}/* * Add the given node at the end of the list */void list_append(list_t *list, lnode_t *node){ list_ins_before(list, node, &list->nilnode);}/* * Add the given node at the beginning of the list. */void list_prepend(list_t *list, lnode_t *node){ list_ins_after(list, node, &list->nilnode);}/* * Retrieve the first node of the list */lnode_t *list_first(list_t *list){ if (list->nilnode.next == &list->nilnode) return NULL; return list->nilnode.next;}/* * Retrieve the last node of the list */lnode_t *list_last(list_t *list){ if (list->nilnode.prev == &list->nilnode) return NULL; return list->nilnode.prev;}/* * Retrieve the count of nodes in the list */listcount_t list_count(list_t *list){ return list->nodecount;}/* * Remove the first node from the list and return it. */lnode_t *list_del_first(list_t *list){ return list_delete(list, list->nilnode.next);}/* * Remove the last node from the list and return it. */lnode_t *list_del_last(list_t *list){ return list_delete(list, list->nilnode.prev);}/* * Associate a data item with the given node. */void lnode_put(lnode_t *lnode, void *data){ lnode->data = data;}/* * Retrieve the data item associated with the node. */void *lnode_get(lnode_t *lnode){ return lnode->data;}/* * Retrieve the node's successor. If there is no successor, * NULL is returned. */lnode_t *list_next(list_t *list, lnode_t *lnode){ assert (list_contains(list, lnode)); if (lnode->next == list_nil(list)) return NULL; return lnode->next;}/* * Retrieve the node's predecessor. See comment for lnode_next(). */lnode_t *list_prev(list_t *list, lnode_t *lnode){ assert (list_contains(list, lnode)); if (lnode->prev == list_nil(list)) return NULL; return lnode->prev;}/* * Return 1 if the lnode is in some list, otherwise return 0. */int lnode_is_in_a_list(lnode_t *lnode){ return (lnode->next != NULL || lnode->prev != NULL);}int list_verify(list_t *list){ lnode_t *node = list_first_priv(list), *nil = list_nil(list); listcount_t count = list_count(list); if (node->prev != nil) return 0; if (count > list->maxcount) return 0; while (node != nil && count--) { if (node->next->prev != node) return 0; node = node->next; } if (count != 0 || node != nil) return 0; return 1;}#ifdef KAZLIB_TEST_MAIN#include <stdio.h>#include <string.h>#include <ctype.h>#include <stdarg.h>typedef char input_t[256];static int tokenize(char *string, ...){ char **tokptr; va_list arglist; int tokcount = 0; va_start(arglist, string); tokptr = va_arg(arglist, char **); while (tokptr) { while (*string && isspace((unsigned char) *string)) string++; if (!*string) break; *tokptr = string; while (*string && !isspace((unsigned char) *string)) string++; tokptr = va_arg(arglist, char **); tokcount++; if (!*string) break; *string++ = 0; } va_end(arglist); return tokcount;}static int comparef(const void *key1, const void *key2){ return strcmp(key1, key2);}static char *dupstring(char *str){ int sz = strlen(str) + 1; char *new = malloc(sz); if (new) memcpy(new, str, sz); return new;}int main(void){ input_t in; list_t *l = list_create(LISTCOUNT_T_MAX); lnode_t *ln; char *tok1, *val; int prompt = 0; char *help = "a <val> append value to list\n" "d <val> delete value from list\n" "l <val> lookup value in list\n" "s sort list\n" "c show number of entries\n" "t dump whole list\n" "p turn prompt on\n" "q quit"; if (!l) puts("list_create failed"); for (;;) { if (prompt) putchar('>'); fflush(stdout); if (!fgets(in, sizeof(input_t), stdin)) break; switch(in[0]) { case '?': puts(help); break; case 'a': if (tokenize(in+1, &tok1, (char **) 0) != 1) { puts("what?"); break; } val = dupstring(tok1); ln = lnode_create(val); if (!val || !ln) { puts("allocation failure"); if (ln) lnode_destroy(ln); free(val); break; } list_append(l, ln); break; case 'd': if (tokenize(in+1, &tok1, (char **) 0) != 1) { puts("what?"); break; } ln = list_find(l, tok1, comparef); if (!ln) { puts("list_find failed"); break; } list_delete(l, ln); val = lnode_get(ln); lnode_destroy(ln); free(val); break; case 'l': if (tokenize(in+1, &tok1, (char **) 0) != 1) { puts("what?"); break; } ln = list_find(l, tok1, comparef); if (!ln) puts("list_find failed"); else puts("found"); break; case 's': list_sort(l, comparef); break; case 'c': printf("%lu\n", (unsigned long) list_count(l)); break; case 't': for (ln = list_first(l); ln != 0; ln = list_next(l, ln)) puts(lnode_get(ln)); break; case 'q': exit(0); break; case '\0': break; case 'p': prompt = 1; break; default: putchar('?'); putchar('\n'); break; } } return 0;}#endif /* defined TEST_MAIN */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -