符号表之List 实现


本人属菜鸟,如有错误请指正

接口定义在list.h 里, 内容如下

#ifndef _LIST_H_H_
#define _LIST_H_H_


typedef struct List* List_t;

/** @defgroup List
 *  MY LIST 
 *  @{
 */
/** @} */

#ifdef __cplusplus
extern "C" {
#endif

    /**@ingroup List
    *@brief List_new creates a new List structure with no bindings within it. 
    *@return List_t If not enough memory is available, it will return a NULL pointer, else it 
    *will return a pointer to the Structure.
    */
    List_t List_new( void );

    /**@ingroup List
    *@brief List_free frees all the memory occupied by the symbol table. 
    *@param [in] oList  the symbol table pointed to by oList,including all 
    *the allocated structure fields, bindings, and buckets (if applicable).
    */
    void List_free( List_t oList );

    /**@ingroup List
    *@brief List_getLength return the total number of bindings within oList.
    */
    int List_getLength( List_t oList );

    /**@ingroup List
    *@brief List_put creates a binding consisting of pcKey and pvValue, inserts it into the symbol table. 
    *@param [in] oList  the symbol table pointed to by oList
    *@param [in] pcKey  the key of binding 
    *@param [in] pvValue  the value of binding
    *@return int If a pcKey isn’t already in the symbol table pointed to by oList,inserts it 
    *into the symbol table and returns 1. If not enough memory is available or pcKey already is in the List, 
    *the function will leave oList unchanged and return 0.
    */
    int List_put( List_t oList, const char* pcKey, const void* pvValue );

    /**@ingroup List
    *@brief List_replace replaces the binding’s old value with pvValue and returns an opaque pointer to the old value.
    *@param [in] oList  the symbol table pointed to by oList
    *@param [in] pcKey  the key of binding 
    *@param [in] pvValue  the value of binding
    *@return void* If successful, the function replaces the binding’s old value with pvValue and returns 
    *an opaque pointer to the old value. If the binding with pcKey is not found, the function leaves oList 
    *unchanged and returns a NULL pointer. 
    */
    void* List_replace( List_t oList, const char* pcKey, const void* pvValue );

    /**@ingroup List
    *@brief List_replace searches through oList to locate the binding with pcKey. 
    *In all cases, oList is unchanged.
    *@param [in] oList  the symbol table pointed to by oList
    *@param [in] pcKey  the key of binding 
    *@return int If successful, returns 1. else returns 0.
    */
    int List_contains( List_t oList, const char* pcKey );

    /**@ingroup List
    *@brief List_get gets the binding’s value. 
    *In all cases, oList is unchanged.
    *@param [in] oList  the symbol table pointed to by oList
    *@param [in] pcKey  the key of binding 
    *@return void* If successful, the function returns the binding’s value. If not found, 
    *the function leaves returns a NULL pointer.
    */
    void* List_get( List_t oList, const char* pcKey );

    /**@ingroup List
    *@brief List_remove removes the binding from oList.
    *List_remove searches through oList to locate the binding with pcKey. If successful,
    *the function removes the binding from oList and returns an opaque pointer to the binding’s old value. 
    *If the binding is not found, the function will return a NULL pointer.
    *@param [in] oList  the symbol table pointed to by oList
    *@param [in] pcKey  the key of binding 
    */
    void* List_remove( List_t oList, const char* pcKey );

    /**@ingroup List
    *@brief List_map iterates through the entire List and applies pfApply on each binding. 
    *pfApply takes a third parameter that is passed in from the map function.
    */
    void List_map( List_t oList,
                       void ( *pfApply )( const char* pcKey, const void* pvValue, void* pvExtra ),
                       const void* pvExtra
                     );

#ifdef __cplusplus
}
#endif

#endif //_LIST_H_H_



list.cpp  实现


#include "list.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

/* ListNode to identify the data unit under processing */
typedef struct ListNode
{
    char*        key;      // Current node key
    void*        value; // Pointer to the value which binds to the key
    struct ListNode* next; // Next node
} ListNode;

/* List to collect the list data  */
typedef struct List
{
    struct ListNode*      head_node;
    struct ListNode*      tail_node;
    unsigned long  uiNodeLength; // The length of linked list
} List;



/*
* Use calloc to allocate the memory,
* because it will initialize all memory bits to zero.
*/
static void* MyAlloc ( unsigned long size )
{
    void* tmp;

    tmp = ( void* ) calloc ( size, sizeof ( char ) );
    assert( tmp );

    return tmp;
}

List_t List_new( void )
{
    return ( List_t ) MyAlloc ( sizeof ( List ) );
}


void List_free( List_t oList )
{
    assert ( oList );

    ListNode* temp = oList->head_node;

    while ( temp )
    {
        oList->head_node = oList->head_node->next;

        if ( temp->key )
        {
            free ( temp->key );
        }

        free ( temp );

        temp =  oList->head_node;
    }

    free ( oList );

    oList = NULL;
}

int List_getLength( List_t oList )
{
    return oList->uiNodeLength;
}



/**
*Local function, if find out the pcKey return the ListNode*,
*other return NULL
*/
static  ListNode* List_getKey( List_t oList,
                                   const char* pcKey )
{
    assert ( oList );
    assert ( pcKey );

    if ( 0 == strlen( pcKey ) )
    {
        return NULL;
    }

    ListNode* temp = oList->head_node;

    while ( temp )
    {
        if ( 0 == strcmp ( pcKey, temp->key ) )
        {
            return temp;
        }

        temp =  temp->next;
    }
    return NULL;
}

int List_put( List_t oList, const char* pcKey,
                  const void* pvValue )
{
    assert ( oList );
    assert ( pcKey );
    assert ( pvValue );

    if ( 0 == strlen( pcKey ) )
    {
        return 0;
    }

    if ( List_getKey( oList, pcKey ) )
    {
        return 0;
    }
    else
    {
        ListNode* new_node = ( ListNode* )MyAlloc ( sizeof( ListNode ) );
        if ( NULL == new_node )
        {
            return 0;
        }

        char* key = ( char* ) MyAlloc ( strlen ( pcKey ) + 1 );
        if ( NULL == key )
        {
            free( new_node );
            return 0;
        }

        new_node->key = key;
        strcpy ( new_node->key, pcKey );
        new_node->value = ( void* )pvValue; //????

        if ( 0 == oList->uiNodeLength )   // The list is empty
        {
            oList->head_node = new_node;
            oList->tail_node = new_node;
            oList->uiNodeLength = 1;

            return 1;
        }

        if ( 1 == oList->uiNodeLength )// Only one key-value in list
        {
            oList->head_node->next = new_node;
            oList->tail_node = new_node;
            oList->uiNodeLength = 2;

            return 1;
        }
        else     // More than one key-value in list
        {
            oList->tail_node->next = new_node;
            oList->tail_node = new_node;
            oList->uiNodeLength += 1;

            return 1;

        }
    }
}

int List_contains( List_t oList, const char* pcKey )
{
    assert ( oList );
    assert ( pcKey );
    if ( List_getKey( oList, pcKey ) )
    {
        return 1;
    }

    return 0;
}

void* List_get( List_t oList, const char* pcKey )
{
    assert ( oList );
    assert ( pcKey );
    ListNode* temp = List_getKey( oList, pcKey );

    if ( temp )
    {
        return temp->value;
    }

    return NULL;
}


void List_map( List_t oList,
                   void ( *pfApply )( const char* pcKey,
                                      const void* pvValue, void* pvExtra ),
                   const void* pvExtra )
{
    assert ( oList );
    assert ( pfApply );
    assert ( pvExtra );

    ListNode* temp = oList->head_node;

    while ( temp )
    {
        assert ( temp->key );
        assert ( temp->value );
        pfApply( temp->key, temp->value, ( void* )pvExtra );
        temp =  temp->next;
    }
    return;
}



void* List_replace( List_t oList, const char* pcKey,
                        const void* pvValue )
{
    assert ( oList );
    assert ( pcKey );

    void* value = NULL;
    ListNode* temp = List_getKey( oList, pcKey );
    if ( temp )
    {
        value = temp->value;
        temp->value = ( void* )pvValue;
    }

    return value;
}

void* List_remove( List_t oList, const char* pcKey )
{
    assert ( oList );
    assert ( pcKey );

    void* value = NULL;
    ListNode* temp = oList->head_node;
    ListNode* pre_node = NULL;

    /*
    *The key-value maybe has been removed
    *or has not been inserted successfully
    */
    if ( NULL == temp )
    {
        return NULL;
    }

    if ( 0 == strlen( pcKey ) )
    {
        return NULL;
    }

    // Head node is the node which need to be removed
    if ( 0 == strcmp ( pcKey, temp->key ) )
    {
        value = temp->value;
        oList->head_node = temp->next;
        free ( temp->key );
        free ( temp );
        oList->uiNodeLength = oList->uiNodeLength - 1;
        return value;
    }

    while ( 1 )
    {
        pre_node = temp;
        temp = temp->next;
        if ( NULL == temp )
        {
            return NULL;
        }
        if ( 0 == strcmp ( pcKey, temp->key ) )   // Find it
        {
            pre_node->next = temp->next;
            value = temp->value;
            free ( temp->key );
            free ( temp );
            oList->uiNodeLength = oList->uiNodeLength - 1;
            return value;
        }
    }
    return NULL;

}



测试代码如下:

#include "list.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdarg.h>


// You can enlarge the value of LOOPS,LOOPS0 and LOOPS1 to perform pressure test
#define LOOPS 1
#define LOOPS0 1
#define LOOPS1 100

#define ARRAY_SIZE 7

#define PRINT_ERROR(...) fprintf(stderr, __VA_ARGS__)
#define MY_ASSERT(value)  if(!(value)) { PRINT_ERROR("\"%s\" failed at %s:%d %s \n",\
                                                         #value,__FILE__,__LINE__,__FUNCTION__);}


#define BINDINGS_LOG

#define UNUSED(x) (void)x


static unsigned long      g_BindingsCount; // Count the bindings
static FILE*   g_out_file = NULL; // For bindings into log



static int gTest = 10;
// Store the keys
static const char* kArrayString[ARRAY_SIZE] = {"Hello", "TTTT",
                                               "Parallel", "Serial", "MyProject",
                                               "Good Luck", "222222@qq.com"
                                              };


static   void InitLog( const char* file_name )
{
#ifdef BINDINGS_LOG
    MY_ASSERT( file_name );
    if ( g_out_file == NULL )
    {
        g_out_file = fopen( file_name, "w" );
    }

    if ( g_out_file == NULL )
    {
        printf( "Create %s failed\n", file_name );
    }
    printf( "Bindings were written into %s, please check it for details.\n", file_name );
#endif
    return ;
}

static   void  LogMessage( const char* format, ... )
{
    va_list ap;
    va_start( ap, format );
#ifdef BINDINGS_LOG
    vfprintf( g_out_file, format, ap );
    fflush( g_out_file );
#else
    vfprintf( stderr, format, ap );
#endif
    va_end( ap );
}

static   void CloseLog()
{
#ifdef BINDINGS_LOG
    if ( g_out_file )
    {
        fclose( g_out_file );
        g_out_file = NULL;
    }
#endif
    return ;
}



static List_t HelpFunc( void )
{
    int i = 0;
    List_t mList = List_new();
    MY_ASSERT( mList );
    MY_ASSERT( 0 == List_getLength( mList ) );
    for ( i = 0; i < ARRAY_SIZE; ++i )
    {
        // Test List_put
        MY_ASSERT( 1 == List_put( mList, kArrayString[i], &gTest ) );
        MY_ASSERT( ( i + 1 ) == List_getLength( mList ) );
    }
    return mList;
}


void test_List_new_and_List_free()
{

    int i = 0;
    printf( "=======================================================\n" );

    for ( i = 0; i < LOOPS; ++i )
    {
        List_t mNew = List_new();
        MY_ASSERT( mNew );
        MY_ASSERT( 0 == List_getLength( mNew ) );
        List_free( mNew );
    }
    printf( "Test new and free, Done !! \n" );
    return ;
}

void test_List_put()
{
    int i = 0;
    int j = 0;
    char temp[100];
    char* testString = "GoodBoy";
    printf( "=======================================================\n" );

    for ( i = 0; i < LOOPS0; ++i )
    {
        List_t mList0 = List_new();
        MY_ASSERT( mList0 );

        for ( j = 0; j < LOOPS1; ++j )
        {
            sprintf( temp, "%d", j );

            MY_ASSERT( 1 == List_put( mList0, ( const char* )&temp, &i ) );// Test List_put
            MY_ASSERT( 0 == List_put( mList0, ( const char* )&temp, &i ) );// put again
            MY_ASSERT( ( j + 1 ) == List_getLength( mList0 ) );
        }

        MY_ASSERT( ( LOOPS1 ) == List_getLength( mList0 ) );

        // Test List_put with NULL key
        MY_ASSERT( 0 == List_put( mList0, "", &i ) );
        MY_ASSERT( ( LOOPS1 ) == List_getLength( mList0 ) );


        /*
        *Simulate the complex scenes, the main purpose is to test stability.
        *Here I call List_replace/get/remove, may be more interfaces called here
        *is more preferably.
        */
        sprintf( temp, "%d", i );
        int* pResult = ( int* )List_replace( mList0, temp, testString ); // replace
        MY_ASSERT( pResult );
        MY_ASSERT( i == *pResult );
        char* result_string = ( char* )List_get( mList0, temp );
        MY_ASSERT( result_string );
        MY_ASSERT( 0 == strcmp( result_string, testString ) ); // check the result of replace
        MY_ASSERT( ( LOOPS1 ) == List_getLength( mList0 ) );

        if ( i < ( LOOPS1 - 1 ) ) // make sure i+1 is valid
        {
            sprintf( temp, "%d", i + 1 );
            pResult = ( int* )List_remove( mList0, temp );
            MY_ASSERT( pResult );
            MY_ASSERT( i == *pResult );
            MY_ASSERT( ( LOOPS1 - 1 ) == List_getLength( mList0 ) );
        }

        List_free( mList0 );

    }

    printf( "Test List_put, Done !! \n" );

    return ;
}

void test_List_contains()
{

    int i = 0;
    int j = 0;
    printf( "=======================================================\n" );

    for ( i = 0; i < LOOPS; ++i )
    {
        List_t mNew =  HelpFunc();
        MY_ASSERT( mNew );

        for ( j = 0; j < ARRAY_SIZE; ++j )
        {
            MY_ASSERT( 1 == List_contains( mNew, kArrayString[j] ) ); // Test List_contains
            MY_ASSERT( 0 == List_contains( mNew, "" ) ); // Test List_contains with NULL key
            MY_ASSERT( ARRAY_SIZE == List_getLength( mNew ) );
        }

        MY_ASSERT( 0 == List_contains( mNew, "Who" ) ); // Test List_contains

        List_free( mNew );
    }

    printf( "Test List_contains, Done !! \n" );
    return ;
}

void test_List_get()
{
    int i = 0;
    int j = 0;
    printf( "=======================================================\n" );

    for ( i = 0; i < LOOPS; ++i )
    {
        List_t mNew =  HelpFunc();
        MY_ASSERT( mNew );
        for ( j = 0; j < ARRAY_SIZE; ++j )
        {
            // Test  List_get
            int* pResult = ( int* )List_get( mNew, kArrayString[j] );
            MY_ASSERT( pResult );
            //MY_ASSERT( gTest == *pResult );
            // Test it with NULL key
            pResult = ( int* )List_get( mNew, "" );
            MY_ASSERT( NULL == pResult );

            MY_ASSERT( ARRAY_SIZE == List_getLength( mNew ) );
        }

        List_free( mNew );
    }

    printf( "Test List_get, Done !! \n" );
    return ;
}


void TestMapFunc1( const char* pcKey, const void* pvValue, void* pvExtra )
{
    MY_ASSERT( pcKey );
    MY_ASSERT( pvValue );
    int* pInt = ( int* )pvExtra;

    if ( *pInt > 0 ) // If *pInt > 0, print out the key and value(adress)
    {
        printf( "Key is  %s, the Value is %d \n", pcKey, *( int* )pvValue );
    }

    return ;
}

void TestMapFunc2( const char* pcKey, const void* pvValue, void* pvExtra )
{
    MY_ASSERT( pcKey );
    MY_ASSERT( pvValue );
    char* mString = ( char* )pvExtra;

    // If the two strings are equal(the *pvExtra and Key), print out the key and the value(adress)
    if ( 0 == strcmp( mString, pcKey ) )
    {
        printf( "Found out the Key, the Key is  %s, the Value is %d \n", pcKey, *( int* )pvValue );
    }

    return ;
}

void test_List_map()
{
    int i = 0;
    int j = 1;
    char* testString = "GoodBoy";
    printf( "=======================================================\n" );

    List_t mNew =  HelpFunc();
    MY_ASSERT( mNew );

    // Use TestMapFunc1 test
    printf( "test List_map with TestMapFunc1\n" );
    printf( "print out the key and the value(adress),\n" );
    List_map( mNew, TestMapFunc1, ( void* )&j ); // Test List_map
    printf( "\ntest List_map with TestMapFunc1\n" );
    printf( "print out nothing\n" );
    List_map( mNew, TestMapFunc1, ( void* )&i ); // Test List_map

    // Use TestMapFunc2 test
    printf( "\n\ntest List_map with TestMapFunc2----\n" );
    printf( "print out the key and the value(adress),\n" );
    List_map( mNew, TestMapFunc2, ( void* )kArrayString[5] ); // Test List_map
    printf( "\ntest List_map with TestMapFunc2-----\n" );
    printf( "print out nothing\n" );
    List_map( mNew, TestMapFunc2, ( void* )testString ); // Test List_map

    List_free( mNew );


    printf( "\nTest List_map, Done !! \n" );

    return ;
}

void test_List_replace()
{
    int j = 0;
    char* testString = "GoodBoy";
    printf( "=======================================================\n" );

    List_t mNew =  HelpFunc();
    MY_ASSERT( mNew );

    for ( j = 0; j < ARRAY_SIZE; ++j )
    {
        int* pResult = ( int* )List_replace( mNew, kArrayString[j], testString ); // Replace
        MY_ASSERT( pResult );
        MY_ASSERT( gTest == *pResult );
        char* result_string = ( char* )List_get( mNew, kArrayString[j] );
        MY_ASSERT( result_string );
        MY_ASSERT( 0 == strcmp( result_string, testString ) ); // Check the result of replace

        MY_ASSERT( ARRAY_SIZE == List_getLength( mNew ) );
    }

    // List_replace, pass the wrong key-value
    MY_ASSERT( 0 == List_replace( mNew, "Who", testString ) );
    MY_ASSERT( 0 == List_replace( mNew, "", testString ) );
    MY_ASSERT( ARRAY_SIZE == List_getLength( mNew ) );

    List_free( mNew );

    printf( "Test List_replace, Done !! \n" );
    return ;
}

void test_List_remove()
{
    int j = 0;
    printf( "=======================================================\n" );

    List_t mNew =  HelpFunc();
    MY_ASSERT( mNew );
    for ( j = 0; j < ARRAY_SIZE; ++j )
    {
        // List_remove, remove it from the head one by one
        int* pResult = ( int* )List_remove( mNew, kArrayString[j] );
        MY_ASSERT( pResult );
        MY_ASSERT( gTest == *pResult );
        MY_ASSERT( ( ARRAY_SIZE - j - 1 ) == List_getLength( mNew ) );
    }
    // List_remove, the key does not in the List
    MY_ASSERT( 0 == List_remove( mNew, kArrayString[0] ) );
    List_free( mNew );


    mNew =  HelpFunc();
    MY_ASSERT( mNew );
    for ( j = 0; j < ARRAY_SIZE; ++j )
    {
        // List_remove, remove it from the tail one by one
        int* pResult = ( int* )List_remove( mNew, kArrayString[ARRAY_SIZE - j - 1] );
        MY_ASSERT( pResult );
        MY_ASSERT( gTest == *pResult );
        MY_ASSERT( ( ARRAY_SIZE - j - 1 ) == List_getLength( mNew ) );
    }
    // List_remove, the key does not in the List
    MY_ASSERT( 0 == List_remove( mNew, kArrayString[0] ) );
    MY_ASSERT( 0 == List_remove( mNew, "" ) );
    List_free( mNew );


    mNew =  HelpFunc();
    MY_ASSERT( mNew );
    {

        // List_remove, remove it from middle
        int* pResult = ( int* )List_remove( mNew, kArrayString[3] );
        MY_ASSERT( pResult );
        MY_ASSERT( gTest == *pResult );
        MY_ASSERT( ( ARRAY_SIZE - 1 ) == List_getLength( mNew ) );
        // List_remove, the key does not in the List
        MY_ASSERT( 0 == List_remove( mNew, kArrayString[3] ) );
        MY_ASSERT( ( ARRAY_SIZE - 1 ) == List_getLength( mNew ) );

        // List_remove, remove it from middle
        pResult = ( int* )List_remove( mNew, kArrayString[2] );
        MY_ASSERT( pResult );
        MY_ASSERT( gTest == *pResult );
        MY_ASSERT( ( ARRAY_SIZE - 2 ) == List_getLength( mNew ) );
        // List_remove, the key does not in the List
        MY_ASSERT( 0 == List_remove( mNew, kArrayString[2] ) );
        MY_ASSERT( ( ARRAY_SIZE - 2 ) == List_getLength( mNew ) );

        // List_remove, remove it from head
        pResult = ( int* )List_remove( mNew, kArrayString[0] );
        MY_ASSERT( pResult );
        MY_ASSERT( gTest == *pResult );
        MY_ASSERT( ( ARRAY_SIZE - 3 ) == List_getLength( mNew ) );
        // List_remove, the key does not in the List
        MY_ASSERT( 0 == List_remove( mNew, kArrayString[0] ) );
        MY_ASSERT( ( ARRAY_SIZE - 3 ) == List_getLength( mNew ) );

        // List_remove, remove it from tail
        pResult = ( int* )List_remove( mNew, kArrayString[6] );
        MY_ASSERT( pResult );
        MY_ASSERT( gTest == *pResult );
        MY_ASSERT( ( ARRAY_SIZE - 4 ) == List_getLength( mNew ) );
        // List_remove, the key does not in the List
        MY_ASSERT( 0 == List_remove( mNew, kArrayString[6] ) );
        MY_ASSERT( ( ARRAY_SIZE - 4 ) == List_getLength( mNew ) );
    }
    List_free( mNew );

    printf( "Test List_remove, Done !! \n" );
    return ;
}



// Test the interfaces with a empty List
void test_List_empty()
{

    int i = 0;
    int j = 1;
    char* testString = "GoodBoy";
    printf( "=======================================================\n" );

    List_t mNew =  List_new();
    MY_ASSERT( mNew );

    MY_ASSERT( 0 == List_getLength( mNew ) );

    void* pResult = List_get( mNew, testString );
    MY_ASSERT( NULL == pResult );

    MY_ASSERT( 0 == List_contains( mNew, testString ) );

    pResult = List_replace( mNew, testString, "hello" ); // replace
    MY_ASSERT( NULL == pResult );

    pResult = List_remove( mNew, testString );
    MY_ASSERT( NULL == pResult );

    MY_ASSERT( 0 == List_getLength( mNew ) );

    // Use TestMapFunc1 test
    List_map( mNew, TestMapFunc1, ( void* )&j );
    List_map( mNew, TestMapFunc1, ( void* )&i );
    // Use TestMapFunc2 test
    List_map( mNew, TestMapFunc2, ( void* )kArrayString[2] );
    List_map( mNew, TestMapFunc2, ( void* )testString );

    MY_ASSERT( 0 == List_getLength( mNew ) );

    List_free( mNew );

    printf( "Test test_List_empty, Done !! \n" );

    return ;
}

void performance_test()
{
    int i = 0;
    int j = 0;
    int k = 0;
    int m = 0;
    int n = 0;
    int p = 0;// random number
    int table_length = -1;
    int outer_times = 1;
    int inner_loop_times = 65523;
    char temp[100];
    char* testString = "GoodBoy";
    clock_t start, finish;
    double duration;

    printf( "=======================================================\n" );
    /*
    *Try to insert 65523 random bindings into the List,
    *and almost the List interfaces will be used in the case.
    */
    printf( "This case is used to test the performance of List, \
	it will output the run time of each interface separately.\n" );


    srand( ( unsigned )time( NULL ) ); // random seed /

    List_t mList0 = List_new();
    MY_ASSERT( mList0 );
    for ( i = 0; i < outer_times; ++i )
    {

        start = clock();
        // test List_put
        for ( j = 0; j < inner_loop_times; ++j )
        {

            p = rand() % ( 65523 ) + 1; // p is a random number that between 1 and 65523

            sprintf( temp, "%d", p );

            table_length = List_getLength( mList0 );

            if ( List_put( mList0, ( const char* )&temp, &i ) )
            {
                MY_ASSERT( ( table_length + 1 ) == List_getLength( mList0 ) );
            }
            else
            {
                MY_ASSERT( table_length == List_getLength( mList0 ) );
            }
        }
        finish = clock();
        duration = ( double )( finish - start ) / CLOCKS_PER_SEC;
        printf( "Try to insert %d random bindings into the List, \n", inner_loop_times );
        printf( "and there are  %d bindings were inserted into the List. \n", List_getLength( mList0 ) );
        printf( "List_put costs \t %f seconds\n", duration );

        start = clock();
        // replace
        for ( k = 0; k < inner_loop_times; ++k )
        {
            p = rand() % ( 65523 ) + 1; // p is a random number that between 1 and 65523

            sprintf( temp, "%d", p );

            table_length = List_getLength( mList0 );

            if ( List_replace( mList0, temp, testString ) )
            {
                char* result_string = ( char* )List_get( mList0, temp );
                MY_ASSERT( result_string );
                MY_ASSERT( 0 == strcmp( result_string, testString ) ); // check the result of replace
                MY_ASSERT( table_length == List_getLength( mList0 ) );
            }
            else
            {
                MY_ASSERT( table_length == List_getLength( mList0 ) );
            }
        }
        finish = clock();
        duration = ( double )( finish - start ) / CLOCKS_PER_SEC;
        printf( "List_replace costs \t %f seconds\n", duration );

        start = clock();
        // get
        table_length = List_getLength( mList0 );
        for ( m = 0; m < inner_loop_times; ++m )
        {
            p = rand() % ( 65523 ) + 1; // p is a random number that between 1 and 65523

            sprintf( temp, "%d", p );

            List_get( mList0, temp );

            MY_ASSERT( table_length == List_getLength( mList0 ) );

        }
        finish = clock();
        duration = ( double )( finish - start ) / CLOCKS_PER_SEC;
        printf( "List_get costs \t %f seconds\n", duration );

        start = clock();

        // remove
        for ( n = 0; n < inner_loop_times; ++n )
        {
            p = rand() % ( 65523 ) + 1; // p is a random number that between 1 and 65523

            sprintf( temp, "%d", p );

            table_length = List_getLength( mList0 );

            if ( List_remove( mList0, temp )  )
            {
                MY_ASSERT( ( table_length - 1 ) == List_getLength( mList0 ) );
            }
            else
            {
                MY_ASSERT( table_length == List_getLength( mList0 ) );
            }
        }

        finish = clock();
        duration = ( double )( finish - start ) / CLOCKS_PER_SEC;
        printf( "List_remove costs \t %f seconds\n", duration );
    }

    List_free( mList0 );

    return ;
}


void run_test()
{
    test_List_new_and_List_free();
    test_List_put();
    test_List_contains();
    test_List_get();
    test_List_map();
    test_List_replace();
    test_List_remove();
    test_List_empty();

    return ;
}

int main( int argc, char* argv[] )
{
    UNUSED( argc );

    run_test();
    performance_test();

    printf( "\n\n" );
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是有符号大数的加减链表实现的 C 语言代码: ```c #include <stdio.h> #include <stdlib.h> /* 定义链表节点 */ typedef struct ListNode { int val; struct ListNode* next; } ListNode; /* 反转链表 */ ListNode* reverseList(ListNode* head) { ListNode* prev = NULL; ListNode* curr = head; while (curr) { ListNode* next = curr->next; curr->next = prev; prev = curr; curr = next; } return prev; } /* 删除链表头部的 0 */ ListNode* trimZero(ListNode* head) { while (head && head->val == 0) { ListNode* tmp = head; head = head->next; free(tmp); } return head; } /* 创建链表节点 */ ListNode* createNode(int val) { ListNode* node = (ListNode*)malloc(sizeof(ListNode)); node->val = val; node->next = NULL; return node; } /* 将数组转换为链表 */ ListNode* arrayToList(int* arr, int len) { ListNode* dummy = createNode(-1); ListNode* tail = dummy; for (int i = 0; i < len; i++) { ListNode* node = createNode(arr[i]); tail->next = node; tail = node; } return dummy->next; } /* 将链表转换为数组,并返回数组长度 */ int* listToArray(ListNode* head, int* len) { ListNode* curr = head; int count = 0; while (curr) { count++; curr = curr->next; } int* arr = (int*)malloc(sizeof(int) * count); curr = head; for (int i = 0; i < count; i++) { arr[i] = curr ? curr->val : 0; curr = curr ? curr->next : NULL; } *len = count; return arr; } /* 对链表进行加法运算 */ ListNode* add(ListNode* l1, ListNode* l2) { ListNode* dummy = createNode(-1); ListNode* tail = dummy; int carry = 0; while (l1 || l2) { int sum = (l1 ? l1->val : 0) + (l2 ? l2->val : 0) + carry; carry = sum / 10; ListNode* node = createNode(sum % 10); tail->next = node; tail = node; l1 = l1 ? l1->next : NULL; l2 = l2 ? l2->next : NULL; } if (carry) { ListNode* node = createNode(carry); tail->next = node; tail = node; } return dummy->next; } /* 对链表进行减法运算 */ ListNode* subtract(ListNode* l1, ListNode* l2) { ListNode* dummy = createNode(-1); ListNode* tail = dummy; int borrow = 0; while (l1 || l2) { int diff = (l1 ? l1->val : 0) - (l2 ? l2->val : 0) - borrow; if (diff < 0) { diff += 10; borrow = 1; } else { borrow = 0; } ListNode* node = createNode(diff); tail->next = node; tail = node; l1 = l1 ? l1->next : NULL; l2 = l2 ? l2->next : NULL; } return dummy->next; } /* 对有符号大数进行加法运算 */ ListNode* addBigNumber(ListNode* l1, ListNode* l2) { // 处理符号位 int sign1 = l1->val < 0 ? -1 : 1; int sign2 = l2->val < 0 ? -1 : 1; if (sign1 * sign2 == 1) { // 同号相加 l1->val = abs(l1->val); l2->val = abs(l2->val); ListNode* result = add(l1, l2); result = trimZero(result); if (result == NULL) { result = createNode(0); } result->val *= sign1; return result; } else { // 异号相减 l1->val = abs(l1->val); l2->val = abs(l2->val); ListNode* result = NULL; if (sign1 == -1) { // l1 < 0, l2 > 0 result = subtract(l2, l1); } else { // l1 > 0, l2 < 0 result = subtract(l1, l2); } result = trimZero(result); if (result == NULL) { result = createNode(0); } result->val *= sign1; return result; } } /* 主函数 */ int main() { int a[] = {1, 2, 3, 4, -5, 6, 7, 8, 9}; int b[] = {9, 8, 7, -6, 5, 4, 3, 2, 1, 0}; int len1 = sizeof(a) / sizeof(int); int len2 = sizeof(b) / sizeof(int); ListNode* l1 = arrayToList(a, len1); ListNode* l2 = arrayToList(b, len2); ListNode* result = addBigNumber(l1, l2); int len = 0; int* arr = listToArray(result, &len); printf("Result: "); for (int i = 0; i < len; i++) { printf("%d ", arr[i]); } printf("\n"); free(arr); return 0; } ``` 该代码实现了对有符号大数进行加减法运算的功能。其中,每一个链表节点表示一个数字(可能为正数或负数),符号位存储在链表头节点中。函数 `add` 和 `subtract` 分别实现了链表的加法和减法运算,函数 `addBigNumber` 判断两个数字的符号后,调用 `add` 或 `subtract` 进行相应的运算。最后,我们将结果从链表转换为数组并输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值