Algorithm fine solution _c language Chain List _ single link list (interface definition + type implementation)

Source: Internet
Author: User
Tags data structures int size

A linked list can be said to be one of the most basic data structures. A list is a group of elements that are grouped or linked in a particular order and are useful when maintaining a collection of data. This is similar to our common array. However, in many cases, a linked list has an advantage over arrays. In particular, the linked list is more efficient when inserting and deleting operations are performed. A linked list needs to be dynamically opened up to storage space, which is allocated when the program is running. Since the size of the data in many applications is not determined at compile time, the characteristic of this dynamic allocation space is also an advantage of the linked list. introduction of single linked list

A single linked list (referred to as a list) is composed of elements that are linked to each other by a pointer. Each element contains two parts: a data member and a pointer called next. By taking the structure of this two member, set the next pointer for each element to the element behind it (see Figure 1). The next pointer to the last element is set to NULL, which simply represents the end of the list. The element at the beginning of the list is "header", and the element that is not at the end of the list is called the tail.

To access an element in a linked list, start at the head of the list and iterate through the next pointer from one element to another until you find the element that you want. In a single linked list, you can only traverse in one Direction: From beginning to end, because each element does not maintain a link to its previous element.

Conceptually, the list can be imagined as a series of successive elements. However, since these elements are dynamically allocated (called malloc in the C language), it is important to remember that these elements are often actually scattered in the memory space (see Figure 2). The link between an element and an element is only to ensure that all elements can be accessed. With this kind of thinking, we will see the need to be particularly careful when maintaining link information between elements. If we lose a link incorrectly, then all elements in the future will not be accessible from this location. "How weak your weakness is, how strong your strength is," is very useful for describing the characteristics of a linked list.


definition of a single linked list interface

List_init

void List_init (List *list,void (*destroy) (void *data));

return value is not

describes initializing the linked list specified by the list.

The function must be invoked before any other action is done on the linked list. When List_destroy is invoked, the destroy parameter provides a way to release dynamically allocated data. For example, if the list contains data that is dynamically allocated with malloc, the destroy should be set to free to release the data when the list is destroyed. For structured data that contains several dynamically assigned members, destroy should be set up as a user-defined destructor, freeing data by calling free on each dynamically assigned member and on the structure itself. If the list contains data that should not be freed, destroy should be set to null.

Degree of Complexity O (1)


List_destroy

void List_destroy (list *list);

return value is not

describes destroying the linked list specified by the parameter list.

No other operations are allowed to execute after the call to List_destroy, unless the list_init is called again. List_destroy removes all elements from the linked list, and if the argument passed to List_init destroy is not NULL, the function is called once for each element in the linked list.

complexity O (n), n represents the number of elements in a linked list


List_ins_next

int List_ins_next (list *list,listelmt *element,const void *data);

The return value returns 0 if the insertion element succeeds, or 1.

describes inserting a new element after the element in the list that is specified in the lists.

If element is set to NULL, the new element is inserted into the head of the list. The new element contains a pointer to data, so as long as the element is still in the list, the memory space referenced by data should remain legitimate. Managing the storage space referenced by data is the responsibility of the caller.

Degree of Complexity O (1)


List_rem_next

int List_rem_next (list *list,listelmt *element,void **data);

Returns a value that returns 0 if the removal element succeeds, or 1.

describes removing the element that is behind the element in the list that is specified by lists.

If the element is set to NULL, the chain header element is removed. When the call is returned, data points to the datastore stored in the removed element. The caller is responsible for managing the storage space referenced by data.

Degree of Complexity O (1)


List_size

int list_size (const list *list);

returns the number of elements in the value list.

Description This is a macro that calculates the number of elements in the list specified by the parameter list.

Degree of Complexity O (1)


List_head

LISTELMT *list_head (const list *list);

The return value points to a pointer to the header element in the linked list.

describes this as a macro that returns a pointer to the header element in the list specified by the parameter list.

Degree of Complexity O (1)


List_tail

LISTELMT *list_tail (const list *list);

The return value points to a pointer to the tail element in the linked list.

describes this as a macro that returns a pointer to the tail element in the list specified by the parameter list. Degree of Complexity O (1)


List_is_head

int List_is_head (const LISTELMT *element);

Returns a value that returns 1 if the element specified by the elements is a linked header node, or 1.

describes a macro that is used to determine whether an element specified by a component is a linked list header node in a linked list.

Degree of Complexity O (1)


List_is_tail

int List_is_tail (const LISTELMT *element);

Returns a value that returns 1 if the element specified by the elements is a linked header node, or 1.

describes a macro that is used to determine whether the element specified by the elements is a linked list trailing node. Degree of Complexity O (1)


List_data

void *list_data (const LISTELMT *element);

returns the data saved in a value node.

describes this as a macro that returns the data saved in a linked list node element specified by the element.

Degree of Complexity O (1)


List_next

LISTEMLT *list_next (const LISTELMT *element);

The return value returns the next node of the node specified by the element.

describes this as a macro that returns the next node in a list of nodes specified by the element.

Degree of Complexity O (1) realization and analysis of single linked list

The structure body LISTELMT represents a single element in a linked list (see Example 1), which has two members, the data members and pointer members described earlier.

The structure list represents the data structure of the linked list (see Example 1). This structure consists of 5 members: the size represents the number of elements in the list; match is not used by the list itself, but by a new type derived from the linked list data structure; Destroy is the destructor that is passed to the list_init after encapsulation; Head is a pointer to the element of the header in the list Tail is a pointer to the end node element in the linked list.

Example 1: Header file for a linked list abstract data type

/*list.h*/#ifndef list_h #define LIST_H #include <stdio.h>/*define a structure for linked list elements.*/Typede
    f struct Listelmt_ {void *data;
struct Listelmt_ *next;

} LISTELMT;
    /*define a structure for linked lists.*/typedef struct {int size;
    Int (*match) (const void *key1,const void *key2);
    void (*destroy) (void *data);
    LISTELMT *head;
LISTELMT *tail;

} List;
/*public interface*/void List_init (List *list,void (*destroy) (void *data));
void List_destroy (list *list);
int List_ins_next (list *list,listelmt *element,const void *data);
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)->data) #define LIST_NEXT (Element)->next) #endif//List_h 

List_init

List_init is used to initialize a linked list so that other actions can be performed (see Example 2).

Initializing a linked list is a simple operation, as long as the size member of the list is set to 0, the function pointer member destroy is set to the defined destructor, and the head and tail pointers are all set to NULL.

The complexity of the List_init is O (1), because all the steps in the initialization process can be completed in a constant amount of time.

Example 2: Implementation of linked list abstract data types

/*list.c*/#include <stdio.h> #include <string.h> #include "lish.h"/*list_init*/void List_init (list *list,
    void (*destroy) (void *data) {list->size = 0;
    List->destroy = Destroy;
    List->head = NULL;

    List->tail = NULL;
Return
    }/*list_destroy*/void List_destroy (list *list) {void *data; /*remove each element*/while (list_size (list) >0) {if (List_rem_next (List,null, (void *) &data) ==0 &A mp;& list->destroy!=null) {/*call a user-defined function to/free dynamically allocated data.*
        /List->destroy (data);
    } memset (List,0,sizeof (list));
Return
    
    }/*list_ins_next*/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 the ' the ' of the ' the '. */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 of the inserted element.
    
    * * list->size++;
return 0;
    
    }/*list_rem_next*/int List_rem_next (list *list,listelmt *element,void **data) {LISTELMT *old_element; /*do not allow removal from a 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, 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 datatype.*/free (old_element); /*adjust the size of the list account for the removed element.
    * * list->size--;
return 0;
 }
List_destroy

List_destroy is used to destroy a linked list (see Example 2), which means removing all elements from a linked list.

If the destroy parameter is not NULL when the List_init is invoked, the List_destroy is invoked once for each element being removed.

The run-time complexity of the List_destroy is O (n), and n represents the number of elements in the list, because the List_rem_next is O, and the list_rem_next is invoked once for each element.

List_ins_next

List_ins_next inserts an element after the element specified by the element parameter (see Example 2). The call points the data for the new element to data that is passed in by the user. The process of inserting new elements into a linked list is simple, but requires special care. There are two things to consider: inserting the head of a linked list and inserting a different location.

In general, to insert an element into a list, you need to point the new element's next pointer at the element after it, and then point the node next pointer before the new element position to the newly inserted element (see Figure 3). However, when you insert from the head of the list, there is no other node before the new element. So in this case, point the new element's next pointer to the head of the linked list, and then reset the head node pointer so that it points to the new element. Look back at the design of the front interface, when the incoming element is null to represent the new elements will be inserted into the head of the list. It is also important to note that whenever the inserted element is at the end of the list, the tail member of the linked list data structure must be reset to point to the new node. Finally, the size member with the number of nodes in the statistical list is updated.


List_rem_next

List_rem_next removes the node from the linked list after the element specified by it (see Example 2). What is removed is the node after the element, not the element itself. This call also takes into account two factors, removing the header node and removing the node from the rest of the location.

The removal operation is simple, but there are also a few details to be noted (see Figure 4). In general, removing an element from the list requires that the next node pointer to the first element of the removed target node point to the next element of the target node. However, when the target node being removed is the head pointer, there is no other element before the target node. Therefore, in this case, you only need to point the head member of the linked table to the next element of the target node. As with the insert operation, the header node of the linked list needs to be removed when the passed-in element is null. In addition, whenever the removed target node is the trailing node of the linked list, you must update the tail member in the data structure of the list to point to the new tail node, or you need to set the tail to null when the removal operation makes the entire list an empty list. Finally, update the size member of the linked list so that it is minus 1. When this call returns, data points to the field where the node has been removed.


The complexity of the List_rem_next is O (1) because all the removal steps are completed in a constant time. list_size, List_head, List_tail, List_is_tail, List_data and List_next

These macros implement some simple actions in some linked lists (see Example 1). In general, they provide the ability to quickly access and detect members in a list and LISTELMT structure.

The complexity of these operations is O (1), because accessing and detecting the members of a struct can be done in a constant time.

************************************

Please pay attention to the follow-up on the application of the list of detailed examples.

************************************

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.