Подсчет уникальных слов в файле?Хорошая альтернатива линейного поиска? - PullRequest
1 голос
/ 23 августа 2010

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

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

А также я должен использовать язык C ...

Ответы [ 7 ]

5 голосов
/ 23 августа 2010

Вы можете поместить все слова в три , а затем подсчитать количество слов после обработки всего файла.

4 голосов
/ 23 августа 2010

Двоичные поисковые деревья прекрасно работают для строк.

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

3 голосов
/ 23 августа 2010

Вы считаете количество уникальных слов в файле?

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

1 голос
/ 23 августа 2010

Если вам нужно что-то простое и легкодоступное, тогда man tsearch для простого бинарного дерева поиска. Но это простое двоичное дерево поиска, не сбалансированное.

В зависимости от количества уникальных слов может быть также доступен простой массив C + realloc () + qsort () + bsearch () . Это то, что я использую, когда мне нужен быстрый поиск без излишеств в простом переносимом языке C. (В противном случае, если это возможно, я выбираю C ++ и std :: map / std :: set.)

Более продвинутые параметры часто зависят от платформы (например, glib в Linux).

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

1 голос
/ 23 августа 2010

Первым обновлением вашего алгоритма может быть сортировка списка, поэтому линейный поиск может быть быстрее (вы будете искать только до тех пор, пока не найдете один элемент больше своего), но это все еще наивное решение.

Лучшими подходами являются деревья бинарного поиска, а еще лучше - дерево префиксов (или три, уже упоминавшееся в другом ответе).

В «Языке программирования C» от ​​K & R у вас есть точный пример того, чем вы являетесьнаходясь в поиске.Первый пример «структур данных с автореференцией» (6.5) представляет собой двоичное дерево поиска, используемое для подсчета вхождений каждого слова в строке.(Вам не нужно считать: P)

структура выглядит примерно так:

struct tnode {
        char *word;
        struct tnode *left;
        struct tnode *right;
};

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

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

Извините за мой плохой английский, и поправьте меня, если я был не прав с чем-то, что я сказал, я очень noob с C: p

РЕДАКТИРОВАТЬ: Я могу 'Я не могу добавлять комментарии к другим ответам, но я прочитал комментарий от OP, говорящий: «Список не отсортирован, поэтому я не могу использовать бинарный поиск».Бессмысленно использовать бинарный поиск в связанном списке.Зачем?Бинарный поиск эффективен, когда доступ к случайному элементу быстрый, как в массиве.В двойном связанном списке ваш худший доступ будет n / 2. Однако вы можете поместить в список много указателей (доступ к ключевым элементам), но это плохое решение.

1 голос
/ 23 августа 2010

Если вы работаете в системе UNIX, вы можете использовать семейство функций bsearch() или hsearch() вместо линейного поиска.

1 голос
/ 23 августа 2010

Я помещаю слова в связанный список и просто выполняю линейный поиск в нем.
Если проверить, присутствует ли слово W, вы просматриваете весь список, то это, безусловно,долго.O (n ^ 2), где n - размер списка.

Простейшим способом, вероятно, является хеш.Это легко реализовать самостоятельно (в отличие от некоторых древовидных структур), и даже C должен иметь несколько библиотек для этого.Вы получите O (n) сложность.

edit Некоторые реализации хеш-таблиц C
http://en.wikipedia.org/wiki/Hash_table#Independent_packages

...