Реализация односвязного списка
Ниже приведён код, реализующий односвязный список.
Каждый элемент списка (list item) хранит пару (key, value) и указатель на следующий элемент списка.
Если следующего элемента нет, то указатель равен значению
NULL
.
Ниже показан пример работы с программой. Зелёным цветов выделен текст, который выводит программа,
а чёрным текст, который вводит пользователь.
ADD 1 1
ADD 2 2
ADD 3 3
PRINT
Size=3
(3,3) -> (2,2) -> (1,1) -> NULL
DEL 3
PRINT
Size=2
(2,2) -> (1,1) -> NULL
ADD 10 10
ADD 11 11
ADD 0 0
FIND 2
Value = 2
PRINT
Size=5
(0,0) -> (11,11) -> (10,10) -> (2,2) -> (1,1) -> NULL
ADD 2 222
PRINT
Size=5
(0,0) -> (11,11) -> (10,10) -> (2,222) -> (1,1) -> NULL
/*
Usage:
ADD
DEL
FIND
PRINT
*/
#include <stdio.h>
#include <string.h>
#include <malloc.h>
typedef int mkey_t; // Тип ключа
typedef int value_t; // Тип значения
struct li {
mkey_t key;
value_t value;
struct li* next;
};
struct list {
struct li *first;
int size;
};
struct list *new_list(void) {
struct list *res = (struct list*) malloc(sizeof(struct list));
res->first = NULL;
res->size = 0;
return res;
}
struct li* new_list_item(void) {
struct li *res = (struct li*) malloc(sizeof(struct li));
res->next = 0;
return res;
}
void delete_items(struct li* it) {
if ( it ) {
if ( it->next ) {
delete_items(it->next);
}
free( it );
}
}
void delete_list(struct list *l) {
if ( l ) {
delete_items( l->first );
free ( l );
}
}
/* Добавляет элемент (key, value) в начало списка l
* Возвращает 1, если удалось добавить элемент (память под элемент была успешно выделена)
*/
int insert_item( struct list *l, mkey_t key, value_t value ) {
struct li *it = new_list_item();
if ( it == NULL ) return 0;
it->key = key;
it->value = value;
it->next = l->first;
l->first = it;
l->size++;
return 1;
}
/* Добавляет элементы (key, value) в начало списка l только в том случае,
* если список l не содержит элемента с ключём key.
* Возвращает 1, если удалось добавить элемент (память под элемент была успешно выделена)
* или обновить значение value.
*/
int insert_item_uniq( struct list *l, mkey_t key, value_t value ) {
if ( l ) {
struct li *it;
for ( it = l->first; it != NULL; it = it->next ) {
if (it->key == key) {
it->value = value;
return 1;
}
}
return insert_item(l, key, value);
} else {
return 0;
}
}
/* Удаляет элемент (key, *).
* Возвращает 1, если элемент с указанным ключём был найден в списке l.
*/
int delete_item( struct list *l, mkey_t key ) {
struct li *it, *prev_it = 0;
for ( it = l->first; it != NULL; prev_it = it, it = it->next ) {
if ( it->key == key ) {
if ( prev_it != 0 )
prev_it->next = it->next;
else
l->first = it->next;
free( it );
l->size--;
return 1;
}
}
return 0;
}
/* Второй вариант реализации удаления элемента из списка
*/
/*
int delete_item2( struct list *l, mkey_t key ) {
struct li **it = &(l->first);
for ( ; (*it) != NULL; it = &( (*it)->next) ) {
if ( (*it)->key == key ) {
struct li *tmp = *it;
*it = (*it)->next ;
free( tmp );
return 1;
}
}
return 0;
}
*/
/*
*
*/
void print_list ( struct list *l ) {
struct li *it;
printf( "Size=%d\n", l->size );
for ( it = l->first; it != NULL; it = it->next ) {
printf("(%d,%d) -> ", it->key, it->value);
}
printf( "NULL\n" );
}
int find_item( struct list *l, mkey_t key, value_t *value) {
struct li *it;
for ( it = l->first; it != NULL; it = it->next ) {
if ( it->key == key ) {
*value = it->value;
return 1;
}
}
return 0;
}
int main()
{
char cmd[1024];
struct list *l = new_list();
while (1) {
fgets( cmd, sizeof(cmd), stdin );
if ( strncmp( cmd, "ADD", 3 ) == 0 ) {
mkey_t key;
value_t value;
if( sscanf(cmd + 3, "%d%d", &key, &value) == 2 ) {
insert_item_uniq(l, key, value );
} else {
printf("Bad arguments: %s\n", cmd+3);
printf("Usage: ADD <key> <value>\n");
}
} else if ( strncmp( cmd, "DEL", 3 ) == 0 ) {
mkey_t key;
sscanf(cmd + 3, "%d", &key );
delete_item( l, key );
} else if ( strncmp( cmd, "PRINT", 5) == 0 ) {
print_list( l );
} else if ( strncmp( cmd, "FIND", 4) == 0 ) {
mkey_t key;
value_t value;
sscanf( cmd + 4, "%d", &key );
if ( find_item( l, key, &value ) ) {
printf("Value = %d\n", value);
} else {
printf("Not found\n");
}
}
}
return 0;
}
Задача. Модифицируйте данный код так, чтобы он решал задачу "Телефонная книжка",
а именно,сделайте тип ключа равным
char* и внесите изменения в строчки
сравнения ключей, а также в функцию
new_list_item создания нового элемента списка. Добавьте
к функции
new_list_item аргументы
key,
value.