C структур данных

62
2

Существует ли структура данных C, эквивалентная следующей структуре python?


 data = {'X': 1, 'Y': 2}

В принципе, я хочу структуру, в которой я могу дать ей предварительно определенную строку и получить ее с целым числом.

спросил(а) 2021-01-25T19:02:40+03:00 4 месяца, 3 недели назад
1
Решение
124

Структура данных, которую вы ищете, называется "хэш-таблицей" (или "хэш-картой" ). Вы можете найти исходный код для здесь.


Хэш-таблица является изменчивым отображением целого числа (обычно полученного из строки) в другое значение, как и dict из Python, которое создает ваш образец кода.

Он называется "хэш-таблицей", потому что он выполняет хеш-функцию в строке, чтобы вернуть целочисленный результат, а затем напрямую использует эту integer, чтобы указать адрес ваших желаемых данных.


Эта система чрезвычайно быстро обеспечивает доступ и изменение вашей информации, даже если у вас ее тонны. Это также означает, что данные неупорядочены, потому что хеш-функция возвращает равномерно случайный результат и ставит ваши данные непредсказуемыми по всей карте (в идеальном мире).

ответил(а) 2021-01-25T19:02:40+03:00 4 месяца, 3 недели назад
88

Также обратите внимание, что если вы делаете быстрый одноразовый хеш, например, два или три статических хэша для некоторого поиска: посмотрите gperf, который генерирует идеальную хэш-функцию и генерирует простой код для этого хэша.

ответил(а) 2021-01-25T19:02:40+03:00 4 месяца, 3 недели назад
77

Там ничего не встроено в язык или стандартную библиотеку, но, в зависимости от ваших требований, существует несколько способов сделать это.


Если набор данных останется относительно небольшим, самым простым решением будет, вероятно, просто создать массив структур по строкам:


typedef struct {
char *key;
int val;
} tElement;

затем используйте последовательный поиск, чтобы просмотреть их. Имеют функции, которые вставляют ключи, удаляют ключи и просматривают ключи, поэтому, если вам нужно изменить их в будущем, сам API не изменится. Псевдо-код:


def init:
create g.key[100] as string
create g.val[100] as integer
set g.size to 0
def add (key,val):
if lookup(key) != not_found:
return already_exists
if g.size == 100:
return no_space
g.key[g.size] = key
g.val[g.size] = val
g.size = g.size + 1
return okay
def del (key):
pos = lookup (key)
if pos == not_found:
return no_such_key
if pos < g.size - 1:
g.key[pos] = g.key[g.size-1]
g.val[pos] = g.val[g.size-1]
g.size = g.size - 1
def find (key):
for pos goes from 0 to g.size-1:
if g.key[pos] == key:
return pos
return not_found

Вставка означает, что она еще не существует, а затем просто привязывает элемент к концу (вы сохраните отдельную переменную размера для структуры). Удаление означает поиск элемента, а затем просто переписывание его последним используемым элементом и уменьшение переменной размера.


Теперь это не самый эффективный метод в мире, но вам нужно иметь в виду, что это обычно имеет значение только в том случае, когда ваш набор данных становится намного больше. Разница между двоичным деревом или хэшем и последовательным поиском не имеет значения, например, для 20 записей. Я даже использовал сортировку пузырьков для небольших наборов данных, где более эффективный был недоступен. Это потому, что он быстро ускоряет кодирование и производительность не имеет значения.


Отступая оттуда, вы можете удалить фиксированный верхний размер, используя связанный список. Поиск по-прежнему относительно неэффективен, так как вы делаете его последовательно, но те же предостережения применяются, как и для решения массива выше. Стоимость удаления верхней границы - небольшое штраф за вставку и удаление.


Если вы хотите немного повысить производительность и нефиксированный верхний предел, вы можете использовать двоичное дерево для хранения элементов. Это избавляет от последовательного поиска при поиске ключей и подходит для нескольких более крупных наборов данных.


Если вы не знаете, насколько большой будет ваш набор данных, я считаю это абсолютным минимумом.


Хеш, вероятно, следующий шаг оттуда. Это выполняет функцию в строке, чтобы получить номер ведра (обычно рассматривается как некоторый тип массива). Это O (1) поиск, но цель состоит в том, чтобы иметь хеш-функцию, которая выделяет только один элемент для каждого ведра, поэтому для получения значения не требуется никакой дополнительной обработки.


Вырожденный случай "всех элементов в одном ковше" ничем не отличается от массива или связанного списка.


Для максимальной производительности и при условии, что ключи фиксированы и известны заранее, вы можете фактически создать собственную функцию хэширования на основе самих ключей.


Зная ключи впереди, у вас есть дополнительная информация, которая позволяет полностью оптимизировать функцию хэширования для генерации фактического значения, поэтому вы даже не включаете ведра - значение, генерируемое хеширующей функцией, может быть самим желаемым значением чем ведро, чтобы получить значение.


Мне пришлось недавно собрать один из них для преобразования текстовых месяцев ( "Январь" и т.д.) в числовые числа. Вы можете увидеть процесс here.


Я упоминаю эту возможность из-за вашего комментария "предварительно заданной строки". Если ваши ключи ограничены "X" и "Y" (как в вашем примере), и вы используете набор символов со смежными символами {W,X,Y} (который даже охватывает EBCDIC, а также ASCII, хотя не обязательно разрешается использование каждого эзотерического набора символов по ISO), простейшей функцией хэширования было бы:


char *s = "X";
int val = *s - 'W';

Обратите внимание, что это плохо работает, если вы кормите плохие данные. Они идеальны для того, когда данные, как известно, ограничены определенными значениями. Стоимость проверки данных может часто накапливать сохранение, заданное заранее оптимизированной хэш-функцией, подобной этой.

ответил(а) 2021-01-25T19:02:40+03:00 4 месяца, 3 недели назад
77

Вышеуказанная структура данных является типом dict.


В C/С++ paralance хэш-карта должна быть эквивалентной, Google для реализации hashmap.

ответил(а) 2021-01-25T19:02:40+03:00 4 месяца, 3 недели назад
62

C не имеет классов сбора. С++ имеет std:: map.


Вы можете попробовать выполнить поиск реализаций C, например. http://elliottback.com/wp/hashmap-implementation-in-c/

ответил(а) 2021-01-25T19:02:40+03:00 4 месяца, 3 недели назад
63

A 'trie' или 'hasmap' должны делать. Простейшей реализацией является массив struct { char * s; int i}; пар.


Отметьте 'trie' в 'include/nscript.h' и 'src/trie.c' здесь: http://github.com/nikki93/nscript. Измените тип 'trie_info' на 'int'.

ответил(а) 2021-01-25T19:02:40+03:00 4 месяца, 3 недели назад
62

Попробуйте Trie для строк или Tree of some sort для типов integer/pointer (или все, что можно сравнить как "меньше" или "больше, чем" другой ключ). Википедия имеет достаточно хорошие статьи по обоим, и они могут быть реализованы в C.

ответил(а) 2021-01-25T19:02:40+03:00 4 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема