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

[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]

Список переменных, используемых в качестве индексов, вместе с диапазонами их предполагаемых значений полезен при решении вопроса, не выходит ли индекс за предписанные пределы. В данном случае значения всех индексов заключены в пределах от 1 до М-1 или от 1 до NUMUN и числа М и NUMUN ограничены сверху числом 100 и снизу числом 0. Индекс не может принимать значение О благодаря двум последним операторам:

IF (NUMUN .NE. 0)GO TO 200 RETURN

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

NUMUN = М-1 (в начале программы)

NUMUN = NUMUN-1 (около конца программы)

Поскольку величина М объявлена как целая переменная, а подпрограмма CHECK определяет М как целую переменную со значениями между 2 и 100, мы можем быть в достаточной степени уверены, что программа не зациклится, так как значение NUMUN никогда не будет равно 0.

Что касается поиска чего-нибудь, что может привести к ошибке подпрограммы PRIM, можно задаться вопросом: могла бы подпрограмма когда-нибудь выбрать ребро с весом 1 ООО ООО? И если да, то что бы это значило?

Что касается проверки подпрограммы PRIM на конкретных данных, то рассмотрим: (1) сеть, у которой значения С(/, J) или М неправильные; (2) сеть с М=2 и M=lbO вершинами; (3) несколько маленьких сетей, для которых можно проверить ОДМВ вручную; (4) сеть со всеми равньми значениями С(/, J); (5) сеть, в которой С(/, /)< <С(/, J+1) для /=1, . . . , М-1 и /</. Чтобы проверить, что все операторы выполнялись, и для проверки эффективности реализации исследуем профиль исполнения подпрограммы PRIM.

Числа слева от операторов в программе на рис. 4.1.7 показывают, сколько раз выполняется каждый из них при вызове подпрограммы PRIM для отыскания ОДМВ в случайно сгенерированной сети с 50 вершинами. Использованная нами программа построения профилей не указывала количества выполнений операторов GOTO 300 и GOTO 400. Однако, зная, что Л+В=1225 и С--Ь=1225, мы можем вычислить, что они исполнялись соответственно 1225-151 = 1074 и 1225-122= = 1103 раз.

Этот профиль не только показывает, что каждый оператор был выполнен хотя бы однажды, но и подтверждает наш анализ сложности, проведенный в предыдущем разделе. Например, если M=50, то М{М-1)/2 =25(49)=1225. Этот профиль также показывает, что про-



грамма проводит основную часть своего времени, выполняя шесть операторов 1225 раз. Следовательно, именно на этих операторах нам следует сосредоточить внимание при попытках улучшить реализацию.

Внимательное изучение циклов DO 300 и DO 400 обнаруживает два места, в которых можно достичь экономии времени выполнения. Во-первых, не обязательно выполнять цикл DO 300 непосредственно после цикла DO 100. Можно было бы непосредственно после 100 CONTINUE вставить оператор GO ТО 350, где 350 - метка оператора, непосредственно следующего за 300 CONTINUE, т. е.

300 CONTINUE 350 К=1

Поскольку такое изменение подпрограммы PRIM устранило бы первое выполнение цикла DO 300-(М-1) операторов (ценой добавления одного оператора) - и так как оно не приводит к неоправданному усложнению логики, его стоит сделать. Во-вторых, цикл DO 400 (с необходимыми предосторожностями) можно было бы преобразовать.к виду DO 400 1=2, NUMUN. Это позволило бы избавиться от 1 = 1, так же как и от М-1 сравнений LIGHT (1) с самим собой, от М-1 выполнений оператора GO ТО 400 и от М-1 выполнений CONTINUE, т. е. не выполнялось бы 3 (М-1)+1 операторов. Однако при NUMUN= = 1 не следует выполнять этот цикл DO. Такого выполнения можно избежать, заменив в конце программы строки

ГР (NUMUN .NE. 0) GO TO 200

RETURN

следующими операторами:

IF (NUMUN .GE 2) GO TO 200

J = UNCHSN(1)

JK=C(J, NEXT) IF (UGHT(1) .LE. JK) GO TO 500

VERTEX(1) = NEXT

LIGHT(1)=JK SOO EDGES=EDGES+1 FROM(EDGES)=J T0(EDGES)=VERTEX(1) C0ST(EDGES) = LIGHT(1) WEIGHT = WE1GHT+UGHT(1) RCTURN END

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

Таким образом, общая экономия в результате этих изменений составит 5(М-l)~l-f3(M-1)+Ц-16=8М+8 операторов. По сравнению с верхней границей 5-1-15М-14 числа выполнений операторов в подпрограмме PRIM экономия 8М+8 операторов составит при-



близительно 14% для M=10, 6% для М=25, 3% для М=50 и 1% для М = 100.

На рис. 4.2.1 дан пересмотренный вариант подпрограммы PRIM с учетом сделанных замечаний. Кратности выполнения операторов для той же случайной сети, что и на рис. 4.1.7, дают экономию 3% по сравнению с первоначальным вариантом. Однако это улучшение не следует рассматривать слишком серьезно, так как оно не обязательно приводит к такому же проценту уменьшения времени выполнения. Действительная экономия времени при выполнении зависит от конкретного компилятора и степени оптимизации.

SUBROUTINE FRlH(C,H,FFCM,TO,C0ET,WErGHT)

с эта годпрогранма находит остовное дерево нининадь»

С ного БЕСА (одмв) во взвешенной связной сети g . ис-

С годьзуя адг0р*1тм р.прима (BELU SYSTEM TECH.J. 36

с (ноябрь 1957), 1339-1401). данная реализация явля-

с ется-модификацией программы в.кивина и М.УИТНИ

С (сомн.асм (апрель 1972), АЛГи,>итм 422). i С

с й« ФОРМАЛЬНЫЕ параметры С

с Cd.J) бес ребра , соединявшего вершины Г И J ,

С где ).LE.C(I,J).LE;999999. если ребро

С отсутствует , то C(I,J) =. 1 оос ссо .

С произвольному большому числу.

. с М ВЕРШИНЫ в G ПРОНУМЕРОВАНЫ 1„..,Н,

с ГДЕ 2.le.m.ue.100

с FMMd) J-epEEPO б одмв соединяет вершину FROHtl)

С т0(1) С вершиной т0{1) при цене COSKU

С СОЗТ(Г)

с weight ОБЩИЙ SEC ОДМВ

с ВНУТРЕННИЕ ПЕРЕМЕННЫЕ С

с EDGES ТЕКУЩЕЕ ЧИСЛО РЕБЕР Б СЛИВ

С LIGKTdJ НАИМЕНЬШИЙ БЕС ре6ра ИЗ VERTEXd) К

С UNC)eN(l)

С «ЕХТ ОЧЕРЕДНАЯ ВЕРШИНА , 11РИС0ЕАИНЯЕ{1АП К ОДНВ

с шин число НЕБЙРАННЫХ ВЕРШИВ

с UNCKNlIl ПАССИВ НЕВЫБРАННЫХ ЕЕРШИ»

с VIRTEXtlJ ВЕРШИНЫ ЧАСТИЧНОГО ОДНВ , ЕЛИЙМЙШИЕ К ЕЕР-

С ШИНЕ UNCHSNd) .

Рис. 4.2.1. Подпрограмма PRIM после внесения изменений.



[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.0012