Вопрос о Случае Переключателя Таблицы переходов

@about8: там существует довольно серьезная ошибка.

Zam obj1 = new Zam("foo", "bar", "baz");
Zam obj2 = new Zam("fo", "obar", "baz");

тот же хэш-код

Вы, вероятно, хотите что-то как

public int hashCode() {
    return (getFoo().hashCode() + getBar().hashCode()).toString().hashCode();

(можно ли получить хэш-код непосредственно от интервала в Java в эти дни? Я думаю, что это делает некоторый автокастинг.. если это так, пропустите toString, это ужасно.)

20
задан Brock Woolf 3 December 2009 в 05:25
поделиться

5 ответов

Таблица переходов - это абстрактная структура, используемая для управления передачей ] в другое место. Goto, continue и break похожи, за исключением того, что они всегда передаются в определенное место, а не в одну возможность из многих. В частности, этот поток управления отличается от вызова функции. (Статья в Википедии о таблицах веток связана. )

Оператор переключения описывает, как писать таблицы переходов на C / C ++. Предоставляется только ограниченная форма (можно включать только целые типы), чтобы упростить и ускорить реализацию в этом общем случае. (Как эффективно реализовать таблицы переходов изучалось гораздо больше для интегральных типов, чем для общего случая.) Классическим примером является Устройство Даффа .

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


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

Компилятор может выбирать метод поиска для каждого оператора switch, и нет никакой гарантии, что вы получить одну конкретную реализацию; однако параметры компилятора, такие как оптимизация по скорости и оптимизация по размеру, должны быть приняты во внимание.

Вам следует изучить изучение структур данных , чтобы справиться с различными требованиями сложности, налагаемыми их. Вкратце, если под «словарем» вы подразумеваете сбалансированное двоичное дерево, то это O (log n); а хеш-таблица зависит от ее хеш-функции и стратегии конфликтов. В конкретном случае операторов switch, поскольку компилятор имеет полную информацию, он может сгенерировать идеальную хеш-функцию , что означает поиск O (1). Однако не заблудитесь, просто взглянув на общую алгоритмическую сложность: она скрывает важные факторы.

20
ответ дан 30 November 2019 в 00:35
поделиться

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

switch (i) {
   case 1: printf("case 1"); break;
   case 2: printf("case 2"); break;
   case 3: printf("case 3"); break;
}

, он может генерировать код, примерно эквивалентный примерно такому:

void case1() { printf("case 1"); }
void case2() { printf("case 2"); }
void case3() { printf("case 3"); }

typedef void (*pfunc)(void);

pfunc functions[3] = {case1, case2, case3};

if ((unsigned)i<3)    
    functions[i]();

Это имеет сложность O (K). Типичная хеш-таблица также имеет примерно O (K) ожидаемую сложность, хотя в худшем случае обычно O (N). Таблица переходов обычно работает быстрее, но обычно она будет использоваться только в том случае, если таблица будет достаточно плотной, тогда как хеш-таблица / словарь работает достаточно хорошо, даже когда случаев будет довольно мало.

4
ответ дан 30 November 2019 в 00:35
поделиться

Предположим, у вас есть массив процедур:

void fa() { 
 printf("a\n");
}

...

void fz() { 
 printf("it's z!\n");
}



typedef void (*F)();
F table[26]={fa,fb,...,fz};

Предположим, вы принимаете символ (из az) ввода от пользователя и запускаете fc:

char c;
switch(c) {
   case 'a': fa();break;
   case 'b': fb();break;
   ...
   case 'z': fz();break;       
   default: exit(-1);
}

В идеале это должно быть заменено чем-то вроде :

if (c<'a' || c>'z') exit(-1);
else (*table[c-'a'])();

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

Компилятор будет делать это для произвольного кода, не обязательно только для вызовов функций, и будет делать это, сохраняя адрес для перехода to (по сути, goto). C не поддерживает напрямую какие-либо вычисляемые goto (индексацию в таблицу или что-то еще), но инструкции ЦП для этого довольно просты.

3
ответ дан 30 November 2019 в 00:35
поделиться

Компиляция для оператора switch может принимать разные формы в зависимости от случая. Если случаи расположены близко друг к другу, это не проблема: используйте таблицу переходов. Если случаи сильно различаются, используйте if (case == value) или используйте карту. Или компилятор может использовать комбинацию: острова таблиц переходов, определяемые проверками if диапазонов таблиц переходов.

2
ответ дан 30 November 2019 в 00:35
поделиться

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

int (* functions [10]) (); / * Массив из 10 указателей функций * /

Насколько я понимаю, это используется с таким выражением case: каждое условие case _ будет индексом в этом массиве, например:

switch( a ) {
    case 1:  // (*functions[1])() // Call function containing actions in case of 1
        ...  
    case 2:  // (*functions[2])() // Call function containing actions in case of 2
        ...

Каждый case, преобразуется в простые функции [a]. Это означает, что доступ к функциям [9] осуществляется так же быстро, как и к функциям [1]. Давая вам время O (1), о котором вы упомянули.

Очевидно, что если у вас есть случай 1 и случай 4907, это не будет хорошим методом, и упомянутые вами методы хеш-таблицы / словаря могут пригодиться .

1
ответ дан 30 November 2019 в 00:35
поделиться