链表中的键是什么?

时间:2017-02-05 11:06:18

标签: c data-structures linked-list

这是C中的链表实现。

https://www.tutorialspoint.com/data_structures_algorithms/linked_list_program_in_c.htm

struct node {
   int data;
   int key;
   struct node *next;
};

链表中的键是什么?在我看来,关键是节点的另一个数据。有钥匙有什么意义?

2 个答案:

答案 0 :(得分:2)

它没有特殊用途(在链接列表实现的情况下)只是它被赋予了名称key并存储了int。正如你所说的那样,另一段数据与特定的实现相关(也许)。

变量名称似乎误导了我们它是一个关键或类似的东西,但事实并非如此。我们可以为其命名abcdata2或您能想到的任何可读名称。

正如 greenshade 所指出的,它用于使用链表建模字典。

答案 1 :(得分:1)

链表是一种类似链的数据结构,其中链中的每个“节点”包含一些数据,并且可选地链接到下一个节点,或者如果它是最后一个节点则根本不包含任何内容。用图形表示:

 ________             ________
|        |           |        |
| Node A |---------->| Node B |--+
|________|           |________|  |
|        |           |        |  |
|   1    |           |   2    |  |
|________|           |________|  |
                                 |
                                 |
+--------------------------------+
|   _______
+->|        |
   | Node C |
   |________|
   |        |
   |   42   |
   |________|

列表中的第一个节点是A,最后一个ndoe是C.除最后一个节点外,所有节点都指向链中的下一个节点。概念本身我很简单。您可以使用以下代码在C中实现此链:

struct node
{
    int          data;
    struct node* next;
};

typedef struct node* linked_list;

struct node node_c = { 42, NULL };
struct node node_b = { 2, &node_c };
struct node node_a = { 1, &node_b };

现在,您可能已经注意到,您描述的数据结构与此有点不同。具体地说,每个节点都有一个名为key的额外字段。这很可能是为了实现地图和链表的低效并置,这将作为一种效率低下的字典。我提到它效率低下(这不是开玩笑,在实践中不要这样做)?这很可能是原始代码试图做的事情:

struct node
{
    int          key;
    int          data;
    struct node* next;
};

typedef struct node* map;

map map_insert
(
    map* the_map,
    int  key,
    int  data
)
{
    map previous_node = NULL;
    map current_node = *the_map;

    while( current_node != NULL && current_node->key < key )
    {
        previous_node = current_node;
        current_node = current_node->next;
    }

    map target_node;
    if( current_node == NULL )
    {
        assert( target_node = malloc( sizeof( struct node ) ) );

        target_node->key = key;
        target_node->next = NULL;
    } else if( current_node->key > key )
    {
        assert( target_node = malloc( sizeof( struct node ) ) );

        target_node->key = key;
        target_node->next = current_node;
    } else
    {
        target_node = current_node;
    }

    if( previous_node != NULL )
    {
        previous_node->next = target_node;
    } else
    {
        *the_map = target_node;
    }

    target_node->data = data;
}


int* map_find
(
    map* the_map,
    int  key
)
{
    map current_node = *the_map;
    while( current_node != NULL && current_node->key < key )
    {
        current_node = current_node->next;
    }

    return current_node != NULL && current_node->key == key ? &current_node->data : NULL;
}


void map_remove
(
    map* the_map,
    int  key
)
{
    map previous_node = NULL;
    map current_node = *the_map;

    while( current_node != NULL && current_node->key < key )
    {
        previous_node = current_node;
        current_node = current_node->next;
    }

    if( current_node == NULL || current_node->key > key )
    {
        return;
    }

    map next_node = current_node->next;
    free( current_node );

    if( previous_node != NULL )
    {
        previous_node->next = next_node;
    } else
    {
        *the_map = next_node;
    }
}


void map_new
(
    map* the_map
)
{
    *the_map = NULL;
}


void map_free
(
    map* the_map
)
{
    map current_node = *the_map;
    while( current_node != NULL )
    {
        map next_node = current_node->next;
        free( current_node );
        current_node = next_node;
    }

    *the_map = NULL;
}


void do_pass
(
    map*     the_map,
    unsigned pass
)
{
    printf( "-- PASS %u --\n", pass );

    map current_node = *the_map;
    while( current_node != NULL )
    {
        printf( "%d -> %d\n", current_node->key, current_node->data );
        current_node = current_node->next;
    }
}


int main()
{
    map my_map;
    map_new( &my_map );

    map_insert( &my_map, 0, 1 );
    map_insert( &my_map, 1, 2 );
    map_insert( &my_map, 2, 42 );
    do_pass( &my_map, 1 );

    map_insert( &my_map, 2, 3 );
    map_remove( &my_map, 0 );
    do_pass( &my_map, 2 );

    *map_find( &my_map, 1 ) = 5;
    do_pass( &my_map, 3 );

    map_free( &my_map );
}

输出:

-- PASS 1 --
0 -> 1
1 -> 2
2 -> 42
-- PASS 2 --
1 -> 2
2 -> 3
-- PASS 3 --
1 -> 5
2 -> 3