⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 list.c

📁 Hausdorff Distance for Image Recognition
💻 C
字号:
/* * *	$Header: /usr/u/wjr/src/ADT/RCS/list.c,v 1.19 1993/09/02 21:48:33 wjr Exp $ * * Copyright (c) 1990, 1991, 1992, 1993 Cornell University.  All Rights * Reserved. * * Copyright (c) 1991, 1992 Xerox Corporation.  All Rights Reserved. * * Use, reproduction and preparation of derivative works of this software is * permitted.  Any copy of this software or of any derivative work must * include both the above copyright notices of Cornell University and Xerox * Corporation and this paragraph.  This software is made available AS IS, and * XEROX CORPORATION DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE, AND NOTWITHSTANDING ANY OTHER PROVISION CONTAINED * HEREIN, ANY LIABILITY FOR DAMAGES RESULTING FROM THE SOFTWARE OR ITS USE IS * EXPRESSLY DISCLAIMED, WHETHER ARISING IN CONTRACT, TORT (INCLUDING * NEGLIGENCE) OR STRICT LIABILITY, EVEN IF XEROX CORPORATION IS ADVISED OF * THE POSSIBILITY OF SUCH DAMAGES. *//* * Xerox may use this code without restriction. */static char *rcsid = "@(#)$Header: /usr/u/wjr/src/ADT/RCS/list.c,v 1.19 1993/09/02 21:48:33 wjr Exp $";/* *	list.c - Yet Another List Module * * How many times have you seen this implemented? I know I've implemented it * a few too many times... * * This module handles generic lists. * * Exports: *	type List *	type ListNode * *	constant List NULLLIST *	constant ListNode NULLLISTNODE * *	List liNew(void) - create a new, empty list * *	void liFree(List l) - free list l * *	ListNode liFirst(List l) - return the first entry in list l * *	ListNode liNext(ListNode ln) - return the next entry after *		ln in whatever list ln is in * *	ListNode liAdd(List l, void *userdata) - append a node containing *		userdata to list l * *	void liRem(ListNode ln) - remove node ln from whatever list it *		is in * *	ListNode liRemAndNext(ListNode ln) - remove node ln from whatever list *		it is in, and return the ListNode which followed it. * *	void *liGet(ListNode ln) - return the userdata of node ln * *	ListNode liIsIn(List l, void *userdata) - search l for a node *		containing that userdata value * *	unsigned int liLen(List l) - return the length of l * *	void liApp(List l1, List l2) - append l2 to l1 * *	macro foreach(ln, l) - iterate over each node in a list * *	macro forafter(ln1, ln2) - iterate over each node in a list after *		a given node * * An object of type List is used as a handle on a list, which consists of *	multiple ListNodes. Each ListNode contains a void * *	field, which is used for whatever data the user wishes to attach *	to that node. It is standard C idiom that (void *) pointers can *	be cast to and from any other type of pointer without error or loss. * * liNew creates an empty list. If this is not possible, it returns NULLLIST. * * liFree frees the storage associated with a List and the ListNodes it *	contains. Note that it does not free the userdata; the user *	must do this before freeing the list structure * * liFirst returns the first entry of the given list. If the list is *	empty, it returns NULLLISTNODE. * * liNext returns the ListNode after the given one. A call to liFirst *	followed by multiple calls to liNext will return all entries *	in that list, in the order in which they were added. When liNext *	is called on the last entry of a list, it returns NULLLISTNODE. * * liAdd appends a node to the given list. The userdata pointer is *	stored in that node. If it is not possible to append to that *	list, it returns NULLLISTNODE. * * liRem removes a node from the list it is in. * * liRemAndNext removes a node from the list it is in, and returns the *	ListNode that followed it. If the ListNode was the last in its list, *	liRemAndNext returns NULLLISTNODE. * liGet gets the userdata associated with the given node. * * liIsIn searches the userdata fields of a list and returns where *	that field appeared in the list. This is the only routine which *	does anything to the userdata fields other than copy them. liIsIn *	compares them for equality. If the field does not appear in the list, *	it returns NULLLISTNODE. * * liLen counts the number of nodes which are on the given list. * * liApp appends the list l2 to the list l1. They must not be the same list. *	l2 becomes invalid after the call. * * foreach is a replacement for the C "for" construct which successively *	assigns ln to each node in l. * * forafter is a replacement for the C "for" construct which successively *	assigns ln1 to each node in the list containing ln2, starting with *	the successor of ln2 (liNext(ln2)). ln1 and ln2 may be the same *	variable. * * Note that all ListNodes must be part of some list. When a ListNode is * removed from a list, or when its list is freed, it becomes invalid. * When a List is freed, it becomes invalid. * Interleaving liAdd, liRem and liNext will produce undefined results. * If a List is modified, you must start at the beginning with liFirst * and scan through it; all ListNodes become invalid when the list is * modified. * However, since scanning through a list removing some of the entries is * a common operation, liRemAndNext has been provided. Scanning through * a list using liNext in the case than a node is not to be deleted, and * liRemAndNext in the case that it is is guaranteed to work. * */#include "misc.h"#include "list.h"#include "chunk.h"/* * This module uses the Chunk service to allocate and free ListNodes * efficiently. */static ListNode malloc_ln(void);static void free_ln(ListNode ln);static Chunk lnChunk = NULLCHUNK;ListliNew(void){    List newList;    if ((newList = (List)malloc(sizeof(* newList))) == NULL) {	return(NULLLIST);	}    newList->first = newList->last = NULLLISTNODE;    return(newList);    }voidliFree(List l){    ListNode ln, nextln;    assert(l != NULLLIST);    /* Free all the ListNodes this list owns */    for (ln = l->first; ln != NULLLISTNODE; ln = nextln) {	assert(ln->owner == l);	nextln = ln->next;	free_ln(ln);	}    /* and the List structure itself */    free((void *)l);    }ListNodeliFirst(List l){    assert(l != NULLLIST);    return(l->first);    }ListNodeliNext(ListNode ln){    assert(ln != NULLLISTNODE);    return(ln->next);    }ListNodeliAdd(List l, void *userdata){    ListNode newln;    assert(l != NULLLIST);    /* Get a new ListNode */    if ((newln = malloc_ln()) == NULL) {	return(NULLLISTNODE);	}    /* and fill it out */    newln->next = NULLLISTNODE;    newln->prev = l->last;    newln->owner = l;    newln->userdata = userdata;    /* Hook it in */    if (l->last != NULLLISTNODE) {	l->last->next = newln;	l->last = newln;	}    else {	assert(l->first == NULLLISTNODE);	l->first = l->last = newln;	}    return(newln);    }voidliRem(ListNode ln){    assert(ln != NULLLISTNODE);    assert(ln->owner != NULLLIST);    /* Unhook the ListNode */    if (ln->owner->first == ln) {	ln->owner->first = ln->next;	assert(ln->prev == NULLLISTNODE);	}    else {	ln->prev->next = ln->next;	}    if (ln->owner->last == ln) {	ln->owner->last = ln->prev;	assert(ln->next == NULLLISTNODE);	}    else {	ln->next->prev = ln->prev;	}    /* and get rid of it */    free_ln(ln);    return;    }ListNodeliRemAndNext(ListNode ln){    ListNode nextln;    assert(ln != NULLLISTNODE);    assert(ln->owner != NULLLIST);    nextln = ln->next;    liRem(ln);    return(nextln);    }void *liGet(ListNode ln){    assert(ln != NULLLISTNODE);    return(ln->userdata);    }ListNodeliIsIn(List l, void *userdata){    ListNode ln;    assert(l != NULLLIST);    for (ln = l->first; ln != NULLLISTNODE; ln = ln->next) {	if (ln->userdata == userdata) {	    return(ln);	    }	}    return(NULLLISTNODE);    }unsigned intliLen(List l){    unsigned int count = 0;    ListNode ln;    assert(l != NULLLIST);    for (ln = l->first; ln != NULLLISTNODE; ln = ln->next) {	count++;	}    return(count);    }voidliApp(List l1, List l2){    ListNode ln;    assert(l1 != NULLLIST);    assert(l2 != NULLLIST);    assert(l1 != l2);    /* Patch up the owners from l2 */    for (ln = l2->first; ln != NULLLISTNODE; ln = ln->next) {	assert(ln->owner == l2);	ln->owner = l1;	}    /* and hook l2 onto the end of l1 */    if (l1->last != NULLLISTNODE) {	assert(l1->last->next == NULLLISTNODE);	l1->last->next = l2->first;	if (l2->first != NULLLISTNODE) {	    assert(l2->first->prev == NULLLISTNODE);	    l2->first->prev = l1->last;	    assert(l2->last != NULLLISTNODE);	    l1->last = l2->last;	    }	}    else {	assert(l1->first == NULLLISTNODE);	l1->last = l2->last;	l1->first = l2->first;	}    /* The List l2 is now no longer valid. */    free((void *)l2);    return;    }/* * This routine gets a chunk of memory suitable for use as a ListNode. */static ListNodemalloc_ln(void){    ListNode ln;    /* Allocate the Chunk if it hasn't been already */    if (lnChunk == NULLCHUNK) {	lnChunk = chNew(sizeof(*ln));	if (lnChunk == NULLCHUNK) {	    return(NULLLISTNODE);	    }	}    ln = (ListNode)chAlloc(lnChunk);    return(ln);    }/* * This routine gets rid of a ListNode, previously allocated through * malloc_ln. */static voidfree_ln(ListNode ln){    assert(ln != NULLLISTNODE);    assert(lnChunk != NULLCHUNK);    chFree(lnChunk, (void *)ln);    return;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -