Главная  Полное построение алгоритма 

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30] [31] [32] [33] [34] [35] [36] [37] [38] [39] [40] [41] [42] [43] [44] [45] [46] [47] [48] [49] [50] [51] [52] [53] [54] [55] [56] [57] [58] [59] [60] [61] [62] [63] [64] [65] [66] [67] [68] [69] [70] [71] [72] [73] [74] [75] [76] [ 77 ] [78] [79] [80] [81] [82] [83] [84] [85] [86] [87] [88] [89] [90] [91] [92] [93] [94] [95] [96] [97] [98] [99] [100] [101] [102] [103] [104] [105] [106] [107] [108] [109] [110] [111] [112] [113] [114] [115] [116] [117]

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

8 9 10 11 12 13 14 15

7 14 27 33 42 49 51 БЗ 67 70 77 в1

1 = 8

89 94 95 99

изт=1б1

7 14 27 33 42 49 51 tplRSTl t=4 tl

LAST=7

42 49 51

FIRSTst t tl AST=7 1 = 6

FIRST =LAST= 1 = 5, K=.Ks, ВОЗВРАТ

Рис. 5.2.2. Использование алгоритма BSEARCH для отыскания записи с ключом 42,

пути от корня к заданному ключу К равно числу сравнений, выполняемых алгоритмом BSEARCH при попытке отыскания /С.


А Л Л Л

Рис. 5.2.3. Представление файла с рис. Б.2.2 в виде двоичного дерева, построенного с помощью алгоритма BSEARCH,



представление упорядоченного файла в виде двоичного дерева оказывается полезным при анализе алгоритма BSEARCH. Для удобства предположим, что число N записей в файле таково, что iV=2*-1 при некотором положительном целом k. В этом случае двоичное дерево является полным, т. е. у каждой внутренней вершины есть как левый, так и правый преемники, дерево имеет высоту k-l, а число вершин на уровне i равно 2, при f=0, 1, . . ., k-l.

Вначале рассмотрим наихудший случай работы алгоритма BSEARCH. Очевидно, что число сравнений является первоочередным фактором, определяющим его сложность. Число сравнений, необходимых для отьюкания заданного ключа, на единицу превосходит уровень ключа в дереве. В худшем случае мы должны пройти дерево до конечной вершины, т. е. произвести k=logs{N-{-l) сравнений. Таким образом, алгоритм BSEARCH в худшем случае имеет сложность O(logaiV).

Вычисление среднего числа сравнений для успешного поиска будет несколько сложнее. Предположим, что все записи встречаются равновероятно. Пусть NCOMP (i) будет уровнем ключа Кг в двоичном дереве, увеличенньм на единицу. Тогда NCOMP(f) равно числу сравнений, необходимых для отыскания Ki. Среднее число сравнений равно

C = JiVCOMP(0. 1=1

Так как мы считаем двоичное дерево полным и N=2>-1, существует

2*-* вершин уровня k-l. Если обозначить через а сумму 2NC0MP(t),

1 = 1

то а является суммой первых N членов ряда

a=l+2-f 2 + 3-f З + 3-f 3-Ь...

1 + 2 (2) + 23) + 2М4) + • . + (/) + ...+ 2*-1 (k).

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

Пусть y=2z, тогда

Далее

S, (2г} l + 2z + i2zf + ... + (2)*-* igi. [{Sk(22)~l}z] = 2 {2z) + 2(3z) + ... + 2*-i (fe*-i).

почленно дифференцировали ряд {S,(2z)-1}г. Если вычислить



эту производную при 2=1 и прибавить 1, то мы получим а, т. е. G == 1 +-[{S,i(2z) - 1}z] при z == 1 (проверьте это).

Используя выражение для частичной суммы геометрической прогрессии в замкнутой форме, получим

0 = 1 + 2-1);

- а i+2*(fe l) l+(jV+l)[log,(Af+l) l] N+l, ,r, , ~1Г--N ~ N N

Таким образом, средняя сложность двоичного поиска равна 0{logz). Сопоставьте э1гот результат со средним числом сравнений NJ2 для алгоритма последовательного поиска (см. упр. 5.2.4).

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

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

Какие структуры данных мы будем использовать? Связанные списки - одна из возможных структур. В разд. 2.3 мы видели, что этот тип структуры данных позволяет эффективно производить вставление и удаление элементов. К сожалению, нелегко выполнять двоичный поиск в связанных списках.

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

В приведенной ниже таблице указаны 10 городов, упорядоченных по убыванию численности населения (йа 1970 г.). Числа в правом столбце показывают алфавитный порядок. Прочтем эти города в алфавитном порядке и запомним их в двоичном дереве в порядке возрастания численности населения.

Энн Арбор первый на входе, и он становится корнем дерева. Шар-лоттсвилль следующий, он сравнивается с корневой вершиной. Так как население Шарлоттсвилля меньше населения Энн Арбора, то Шарлоттсвилль становится левым преемником Энн Арбора. Каждый из последующих городов читается и сравнивается с корнем. Если его население меньше, чем у корня, он далее сравнивается с левым преемником корня; если больше, то с правым. Раньше или позже каждый город сравнивается с вершиной, не имеющей правого или левого преемника, и он становится новой конечной вершиной этого дерева. Пронумерованные фиктивные вершины будут использованы для обозначения недостающих преемников для городов, не имеющих



[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30] [31] [32] [33] [34] [35] [36] [37] [38] [39] [40] [41] [42] [43] [44] [45] [46] [47] [48] [49] [50] [51] [52] [53] [54] [55] [56] [57] [58] [59] [60] [61] [62] [63] [64] [65] [66] [67] [68] [69] [70] [71] [72] [73] [74] [75] [76] [ 77 ] [78] [79] [80] [81] [82] [83] [84] [85] [86] [87] [88] [89] [90] [91] [92] [93] [94] [95] [96] [97] [98] [99] [100] [101] [102] [103] [104] [105] [106] [107] [108] [109] [110] [111] [112] [113] [114] [115] [116] [117]

0.002