/**
 * @file                  single_linked_list.c
 * @author            libra
 * @date                  2016年2月24日
 * @version            初稿
*/
#include <stdlib.h>
#include <string.h>
#include "single_linked_list.h"

/**
 *@brief:         list_init
 *@details:        Initializes the linked list specified by list. This operation must  be called for a linked list before the list can be used with any other operation.
 *              Thedestroyargument provides a way to free dynamically allocated data when  list_destroy is called. For example, if the list contains data dynamically allocated
 *              usingmalloc, destroyshould be set to free to free the data as the linked list is destroyed. For structured data containing several dynamically allocated members,
 *              destroyshould be set to a user-defined function that callsfree for each dynamically allocated member as well as for the structure itself.
 *              For a linked list containing data that should not be freed, destroyshould be set to NULL.
 *@param[in][out]       List *list
 *@param[in]              void (*destroy)(void *data)
 *@retval:               None
 */
void list_init(List *list, void (*destroy)(void *data))
{
    /*Initialize the list.*/
    list->size = 0;

    list->destroy = destroy;

    list->head = NULL;

    list->tail = NULL;

    return;
}

/**
 *@brief:         list_destroy
 *@details:        Destroys the linked list specified bylist. No other operations are permitted after calling list_destroy unless list_init is called again.
 *              The list_destroyoperation removes all elements from a linked list and calls the function passed asdestroyto list_init once for each element as it is removed,
 *              provided destroywas not set to NULL.
 *@param[in][out]    List *list
 *@retval:        None
 */
void list_destroy(List *list)
{
    void               *data;
    /*Remove each element.*/
    while (list_size(list) > 0)
    {
        if (list_rem_next(list, NULL, (void **)&data) == 0 && list->destroy != NULL)
        {
            /*Call a user-defined function to free dynamically allocated data.*/
            list->destroy(data);
        }
    }

    /*No operations are allowed now, but clear the structure as a precaution.*/
    memset(list, 0, sizeof(List));
    return;
}

/**
 *@brief:          list_ins_next
 *@details:         Inserts an element just after elementin the linked list specified bylist.Ifelementis NULL, the new element is inserted at the head of the list.
 *               The new element contains a pointer todata, so the memory referenced by data should remain valid as long as the element remains in the list.
 *               It is the responsibility of the caller to manage the storage associated with data.
 *@param[in][out] List *list
 *@param[in][out] ListElmt *element
 *@param[in]      const void *data
 *@retval:          0 if inserting the element is successful, or –1 otherwise.
 */
int list_ins_next(List *list, ListElmt *element, const void *data)
{

    ListElmt           *new_element;
    /*Allocate storage for the element.*/
    if ((new_element = (ListElmt *)malloc(sizeof(ListElmt))) == NULL)
    {
        return -1;
    }

    /*Insert the element into the list.*/
    new_element->data = (void *)data;

    if (element == NULL)
    {
        /*Handle insertion at the head of the list.*/
        if (list_size(list) == 0)
        {
            list->tail = new_element;
        }

        new_element->next = list->head;

        list->head = new_element;
    }
    else
    {
        /* Handle insertion somewhere other than at the head. */
        if (element->next == NULL)
        {
            list->tail = new_element;
        }

        new_element->next = element->next;

        element->next = new_element;
    }
    /*Adjust the size of the list to account for the inserted element.*/
    list->size++;
    return 0;
}

/**
 *@brief:         list_rem_next
 *@details:        Removes the element just afterelementfrom the linked list specified by list.Ifelementis NULL, the element at the head of the list is removed.
 *              Upon return,datapoints to the data stored in the element that was removed. It is
 *              the responsibility of the caller to manage the storage associated with the data.
 *@param[in][out] List *list
 *@param[in][out] ListElmt *element
 *@param[out]     void **data

 *@retval:        0 if removing the element is successful, or –1 otherwise.
 */
int list_rem_next(List *list, ListElmt *element, void **data)
{
    ListElmt           *old_element;
    /*Do not allow removal from an empty list.*/
    if (list_size(list) == 0)
    {
        return -1;
    }

    /* Remove the element from the list.*/
    if (element == NULL)
    {
        /*Handle removal from the head of the list.*/
        *data = list->head->data;

        old_element = list->head;

        list->head = list->head->next;

        if (list_size(list) == 1)
        {
            list->tail = NULL;
        }
    }
    else
    {
        /*Handle removal from somewhere other than the head.*/
        if (element->next == NULL)
        {
            return -1;
        }


        *data = element->next->data;

        old_element = element->next;

        element->next = element->next->next;
        if (element->next == NULL)
        {
            list->tail = element;
        }
            
    }
    /*Free the storage allocated by the abstract data type. */
    free(old_element);
    /*Adjust the size of the list to account for the removed element.*/
    list->size--;
    return 0;
}
View Code

 

/**
 * @file                single_linked_list.h
 * @author            libra
 * @date            2016年2月24日
 * @version            初稿
 * @par                版权所有 (C), 2013-2023, 天道酬勤
 * @par History:
 * 1.日    期:         2016年2月24日
 *   作    者:         libra
 *   修改内容:    创建文件
*/
#ifndef __SINGLE_LINKED_LIST_H__
#define __SINGLE_LINKED_LIST_H__


#ifdef __cplusplus
#if __cplusplus
extern "C"{
#endif
#endif /* __cplusplus */


/*
 *@brief:    ListElmt
 *@details: Define a structure for linked list elements.
 */
typedef struct ListElmt_
{
    void               *data; //!< 
    struct ListElmt_   *next; //!< 
} ListElmt;

/*
 *@brief:    ListElmt
 *@details: Define a structure for linked lists.
 */
typedef struct List_
{
    int                size                                         //!< 
    int                (*match)(const void *key1, const void *key2);//!< 
    void               (*destroy)(void *data);                      //!< 
    ListElmt           *head;                                       //!< 
    ListElmt           *tail;                                       //!< 
} List;

/*Public Interface*/
extern void list_destroy(List *list);
extern void list_init(List *list, void (*destroy)(void *data));
extern int list_ins_next(List *list, ListElmt *element, const void *data);
extern int list_rem_next(List *list, ListElmt *element, void **data);

#define list_size(list) ((list)->size)

#define list_head(list) ((list)->head)

#define list_tail(list) ((list)->tail)

#define list_is_head(list, element) ((element) == (list)->head ? 1 : 0)

#define list_is_tail(element) ((element)->next == NULL ? 1 : 0)

#define list_data(element) ((element)->data)

#define list_next(element) ((element)->next)


#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */


#endif /* __SINGLE_LINKED_LIST_H__ */
View Code
#include <string.h>
#include "single_linked_list.h"

/**
 *@brief:         print_list
 *@param[in]      const List *list  
 *@retval:        None
 */
static void print_list(const List *list)
{

    ListElmt *element;
    int *data;
    int i;

    /*Display the linked list.*/

    printf("List size is %d\n", list_size(list));

    i = 0;
    
    element = list_head(list);

    while (1)
    {

        data = list_data(element);
        
        printf("list[%03d]=%03d\n", i, *data);
        
        i++;
        
        if (list_is_tail(element))
        {
            break;
        }        
        else
        {
            element = list_next(element);
        }
    }

    return;

}

/**
 *@brief:         main
 *@param[in]    void  
 *@param[out]    无
 *@retval:        
 */
int main(void)
{


    List   list;
    ListElmt   *element;
    int *data;
    int i;
    
    /* Initialize the linked list. */
    list_init(&list, free);
    
    /* Perform some linked list operations.*/
    element = list_head(&list);
    for (i = 10; i > 0; i--)
    {
        if ((data = (int *)malloc(sizeof(int))) == NULL)
        {
            return;
        }        
        *data = i;
        if (list_ins_next(&list, NULL, data) != 0)
        {
            return;
        }    
    }
    print_list(&list);

    element = list_head(&list);
    for (i = 0; i < 7; i++)
    {
        element = list_next(element);
    }
    data = list_data(element);    
    
    printf("Removing an element after the one containing %03d\n", *data);
    
    if (list_rem_next(&list, element, (void **)&data) != 0)
    {
        return;
    }    
    print_list(&list);
    
    printf("Inserting 011 at the tail of the list\n");
    *data = 11;    
    if (list_ins_next(&list, list_tail(&list), data) != 0)
    {
        return;
    }
    print_list(&list);

    printf("Removing an element after the first element\n");
    element = list_head(&list);
    if (list_rem_next(&list, element, (void **)&data) != 0)
    {
        return;
    }
    print_list(&list);

    printf("Inserting 012 at the head of the list\n");
    *data = 12;
    if (list_ins_next(&list, NULL, data) != 0)
    {
        return;    
    }
    print_list(&list);

    printf("Iterating and removing the fourth element\n");
    element = list_head(&list);
    element = list_next(element);
    element = list_next(element);
    if (list_rem_next(&list, element, (void **)&data) != 0)
    {
        return;
    }
    print_list(&list);

    printf("Inserting 013 after the first element\n");
    *data = 13;
    if (list_ins_next(&list, list_head(&list), data) != 0)
    {
        return;
    }
    print_list(&list);

    i = list_is_head(&list, list_head(&list));
    printf( "Testing list_is_head...Value=%d (1=OK)\n", i);
    i = list_is_head(&list, list_tail(&list));
    printf( "Testing list_is_head...Value=%d (0=OK)\n", i);
    i = list_is_tail(list_tail(&list));
    printf( "Testing list_is_tail...Value=%d (1=OK)\n", i);
    i = list_is_tail(list_head(&list));
    printf( "Testing list_is_tail...Value=%d (0=OK)\n", i);

    /*Destroy the linked list.*/

    printf("Destroying the list\n");
    list_destroy(&list);
}

 

posted on 2017-07-20 11:08  陌鉎こ城sHi  阅读(173)  评论(0编辑  收藏  举报