Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
курсач гофаров 5 вариант.doc
Скачиваний:
18
Добавлен:
03.05.2019
Размер:
608.77 Кб
Скачать

2.Пример выполнения курсовой работы.

2.1.Задание.

Пусть заданы параметры ГМ:

  1. Формат слова ГМ параметр в диапазоне 8..255 бит;

  2. Число регистров общего назначения 4;

  3. Форматы команд ГМ: RRрегистр-регистр, RSрегистр-память, SIпамять-непосредственный операнд;

  4. Количество операндов в команде 1,2,3;

  5. Команды ГМ для обязательной реализации:

1)команда чтения слова из памяти;

2)команда записи слова в память;

3)команда сравнения двух слов;

Задача. Создать отсортированный линейный односвязный список из n элементов (узлов).

2.2.Анализ задачи и разработка алгоритма.

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

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

TYPE u=^uzl;

uzl= RECORD

inf :Word; {информационное поле}

link :u; {указательное поле }

END;

VAR h:u; {указатель на голову (начало) списка}

Рис.1. Описание структуры узла списка на Паскале.

Следует отметить, что указательное поле содержит адрес следующего узла, голова списка h (head) – адрес первого узла (указательное поле называют еще ссылочным полем, а ее значение ссылкой). Указатель, кроме того, может иметь значение nil (ссылка «в никуда» ) и при обработке списков интерпретируется как признак конца списка. Графическая модель списка приведена на рис.2:

h - голова списка nil - признак конца списка

Рис.2. Односвязный линейный список.

Учитывая динамические свойства списка, он обычно формируется и обрабатывается в динамической памяти. Наиболее распространенными операциями со списком являются:

  • создание списка;

  • прохождение списка;

  • сортировка списка;

  • добавление нового узла;

  • удаление заданного узла;

  • и др.

В дальнейшем нас будет интересовать задача создания отсортированного списка. Для ознакомления с алгоритмом решения данной задачи сначала составим программу-прототип на языке Паскаль с тем, чтобы упростить разработку программы для ГМ. При написании программы на Паскале будем пользоваться приемами, характерными для программирования на Ассемблере (например, пользоваться оператором goto и т.п.), чтобы структура прототипа наиболее полно соответствовала программе ГМ. Ниже приведена указанная программа на Паскале.

Program Prototip1; { программа создания отсортированного списка }

Uses Crt;

Label 1;

Const kuz=10; { кол-во узлов }

Type u=^uzl;

uzl = Record { структура узла }

i :Word; { поле inf }

l :u; { поле link }

End;

Var h,p,t,s :u; { переменные для указателей }

R0,R1,R2 :Word; { рабочие переменные }

Begin

Randomize;

ClrScr; { очистка экрана }

R1:=0; { R1 сч. цикла := 0 }

R2:=kuz; { к-во узлов -> R2 }

h:=Nil; { h – голова списка, вначале список пустой }

{------------- Цикл создания узлов списка ------------- }

Repeat

R0:=Random(100); { взяли очередной inf -> R0 }

New(s); { создали новый узел, его адрес в s }

s^.i:=R0; { inf -> в новый узел }

t:=h; { t - указатель на текущий узел }

p:=Nil; { p - указатель на предыдущий узел}

{ Цикл поиска и вставки узла в надлежащее место списка }

While t <> Nil Do { пока не достигнут конец списка }

If t^.i > R0 { поиск места вставки }

Then { если место вставки найдено }

If p = Nil { и если р не успел измениться,то}

Then Begin { вставка в начало списка }

s^.l := t; { соответствующая }

h := s; { коммутация узлов }

Goto 1; { alles с этим вариантом }

End

Else Begin { вставка в середину списка }

s^.l := t; { соответствующая }

p^.l := s; { коммутация узлов }

Goto 1; { alles }

End

Else Begin { место вставки не найдено и переход к след. узлу }

p := t; { предыдущий становится текущим, }

t := t^.l; { а текущий - следующим }

End;

{ конец цикла While }

If p=Nil Then Begin { вставка в пустой список }

h:=s; { соответствующая }

s^.l:=Nil; { коммутация узлов}

End

Else Begin { вставка в конец списка }

p^.l:=s; { соответствующая }

s^.l:=Nil; { коммутация узлов}

End;

1: R1:=R1+1; { увеличение счетчика цикла }

Until R2 <= R1; { If счетчик < kuz Then на начало цикла}

{ Прохождение и печать списка }

t:=h; { встали на начало списка }

Writeln(' отсортированный список');{ вывели заголовок }

While t<>Nil Do { цикл прохождения списка }

Begin Write( t^.i:3 ); { печать узла }

t:=t^.l; { переход к след. узлу }

End;

ReadKey; { ожидание нажатия клавиши }

End.

В программе реализуется следующей алгоритм создания отсортированного списка. Сначала список пустой и h=nil. Внешний цикл REPEAT UNTIL детерминированного типа управляет числом создаваемых узлов. При каждом повторении этого цикла в динамической памяти создается новый узел с адресом (указателем) s и в его информационное поле s^.i записывается очередное случайное число. Далее, с помощью итерационного цикла WHILE осуществляется поиск места вставки нового узла и его коммутация с соседними так, чтобы список сохранил свойство отсортированности. Отметим, что для коммутации необходимо знать указатель как на текущий узел (узел, перед которым вставляется новый), так и указатель на предыдущий (узел, после которого вставляется новый). Эти указатели обозначены соответственно t и p. Таким образом, при прохождении списка указатель p отстает на один шаг от t. Начальное значение p равно nil, а t равнво h. Следует иметь в виду 4 варианта вставки:

  • вставка в пустой список – в этом случае голове списка h присваивается значение указателя s нового узла, а в указательное поле этого узла записывается nil;

  • вставка в начало списка – распознается по сохранившемуся после начальной инициализации p=nil; в указательное поле нового узла записывается значение h (s^.l:=h), а новым значением головы списка становится s (h:=s);

  • вставка в середину списка – сводится к коммутации нового узла s с узлами p и t; сначала в ссылочное поле нового узла записывается ссылка (адрес) узла t (s^.l:=t), затем адрес s копируется в ссылочное поле узла p (p^.l:=s);

  • вставка в конец списка – распознается, когда список пройден до конца (t=nil), а место вставки в цикле WHILE не найдено; узел s коммутируется с последним узлом списка (с узлом p): в ссылочное поле p записывается адрес нового узла (p^.l:=s), а в ссылочное поле s – значение nil (s^.l:=nil).

После того, как создано заданное число узлов, следует выход из внешнего цикла. Далее список просматривается от начала к концу и информационное поле каждого текущего узла (t^.i) выводится на экран монитора. После нажатия любой клавиши программа завершает свою работу.

Следующим шагом разработки является адаптация полученной программы к структуре ГМ. При этом необходимо учитывать следующие обстоятельства:

  1. Будем считать, что ГМ имеет только статическую память. Поэтому список сформируем в массиве целых чисел Spis, в котором для каждого узла отводится два последовательных слова – первое для поля inf, второе для поля link. Причем, с целью упрощения задачи в качестве указателя в поле link будем использовать не абсолютный адрес, а смещение (индекс) соответствующего слова ГМ в Spis, т.е. указатели будут изменяться в диапазоне 0..2*kuz-1. Очевидно, что в данной постановке задачи параметр fw подразумевается равным 16.

  2. В программе на Паскале исходные данные для списка поставляются генератором случайных чисел. Поскольку природа происхождения данных для нашей задачи не имеет принципиального значения (лишь бы они носили случайный характер), мы можем в качестве них выбрать содержимое любой области памяти (например, объектный код самой программы сортировки списка). Для удобства обработки эти данные предварительно копируются в непрерывную область памяти Buf. Необходимый размер области Buf в битах определяется количеством узлов списка kuz и форматом слова fw ГМ: Vbuf=kuz*fw. В следующем варианте программы на Паскале исходные данные для списка берутся из области программы начиная с адреса переменной ih.

  3. В модифицированной программе на Паскале будем использовать только простейшие операторы, избегая сложных конструкций с тем, чтобы в ней проявились те операторы, которые легко преобразуются в команды ГМ.

Program Prototip2; { второй вариант программы сортировки списка }

Uses Crt;

Label Cycl1, While1, EndWhile, InsUz, NextUz, InsHead, InsMed,

EndCycl1, Empty, InsEnd, Wcycl, endPrn;

Const kuz=10; { кол-во узлов }

Niil=255; { код для Nil }

Var Buf :Array [0..kuz-1] Of Word; { буфер для исх. данных }

Spis :Array [0..2*kuz-1] Of Word; { обл-ть памяти для списка }

h,p,t,s :Word; { переменные для указателей }

R0,R1,R2,R3 :Word; { "регистры" ГМ }

Cnil :Word; { переменная для Nil }

ih :Word; {индекс для резервирования нового узла в Spis }

Begin

ClrScr; { очистка экрана }

Move(ih,Buf,SizeOf(Buf)); {заполнение Buf исходными данными}

R1 := 0;

R2 := kuz;

h := Niil;

Cnil := Niil;

ih := 0;

Cycl1: {------------- Цикл создания узлов списка ------------- }

R0 := Buf[R1]; { взяли очередной inf -> R0 }

s := ih; { New(s) - создали новый узел }

Inc(ih); { ih указ-т на следующий новый узел }

Inc(ih);

Spis[s] := R0; { s^.i:=R0; inf -> в новый узел }

t := h; { t - указатель на текущий узел }

p := Niil; { p - указатель на предыдущий узел }

While1: { Цикл поиска и вставки узла в список }

If t = Niil Then Goto EndWhile;

R3 := Spis[t]; { R3 := t^.i }

If R3 > R0 Then Goto InsUz; { поиск места вставки }

NextUz: { переход к след. узлу}

p := t; { предыдущий становится текущим }

Inc(t); { t:=t+1 для получения доступа в поле link}

t := Spis[t]; { t:=t^.l переход к след. узлу }

Goto While1;

InsUz: { Реализация различных вариантов вставки}

If p = Niil Then Goto InsHead;

InsMed: { вставка в середину }

Inc(p); { p:=p+1 для получения доступа в поле link }

R0 := Spis[p]; { R0 := p^.l }

Spis[p] := s; { p^.l := s }

Inc(s); { s:=s+1 для получения доступа в поле link }

Spis[s] := R0; { s^.l := R0 }

Goto EndCycl1;

InsHead: { вставка в начало списка }

h := s; { новое начало списка }

Inc(s); { s:=s+1 для получения доступа в поле link }

Spis[s] := t; { s^.l := t }

Goto EndCycl1;

EndWhile: { реализация других вариантов }

If p=Niil Then Goto Empty;

InsEnd: { вставка в конец списка}

Inc(p); { p:=p+1 для получения доступа в поле link }

Spis[p] := s; { p^.l := s}

Inc(s); { s:=s+1 для получения доступа в поле link }

Spis[s] := Niil; { s^.l := NIL }

Goto EndCycl1;

Empty: { вставка в пустой список }

h := s;

Inc(s); { s:=s+1 для получения доступа в поле link }

Spis[s] := Niil; { s^.l:=NIL }

EndCycl1:

Inc(R1); { увеличение счетчика цикла }

If R2 > R1 Then Goto Cycl1;{ If счетчик < kuz Then на начало цикла }

{----------- Прохождение и печать списка --------------------}

WriteLn(' Отсортированный список'); { вывод заголовка списка}

t := h; { встали на начало списка }

Wcycl: { цикл прохождения списка }

If t = Niil Then Goto endPrn;{ While t <> NIL Do}

Write(Spis[t]:3); { Печать узла}

Inc(t); { t:=t+1 для получения доступа в поле link}

t := Spis[t]; { t:=t^.l переход к след.. узлу }

Goto Wcycl;

endPRN:

ReadKey; { ждать нажатия клавиши}

End.

Результаты работы программы приведены на рис.3.

Отсортированный список

0 0 1 1 3 7 7 1191 6223 7432

Рис.3. Вывод программы Prototip2.

На рис.4. приведена структура области памяти Spis с узлами полученного списка. Информационные поля узлов выделены. По указательным полям, начиная с головы списка можно проследить ее связность.

инд. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

S pis 0 10 1 4 1 6 3 8 7 18 0 2 6223 16 1191 12 7432 255 7 14

h узел 0 узел 2 узел 3 узел 4 узел 5 узел 1 узел 8 узел 7 узел 9 узел 6

конец списка

Рис.4. Структура массива Spis со списком.

Как видно из приведенной программы, она в основном состоит из простейших операторов типа:

  • a:=b; где а – одиночная переменная или элемент массива;

b – тоже самое или константа, причем, и а и b

не могут быть одновременно элементами массива.

  • Goto metka;

  • If условие Then Goto metka;

  • Inc(a);

Остальные операторы описывают достаточно сложные действия и поэтому требуют особого внимания при разработке программы на ГМ. К ним относятся: ClrScr, Move, Write, Writeln, ReadKey.