Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
курсач ооп.doc
Скачиваний:
2
Добавлен:
01.07.2025
Размер:
133 Кб
Скачать
☆

Пример квадродерева.

  Рис. 3: (a) первый этап разбиения (b) второй этап разбиния  (c) третий этап разбиения (d) изображение полностью разбито

На каждом этапе построения квадродерева изображение разбивается на четыре квадранта и каждому присваивается одно из следующих значений

  • 1) белый --> квадрант полностью белый. Обозначается белым квадратом.

  • 2) черный --> квадрант полностью черный. Обозначается черным квадратом.

  • 3) серый --> квадрант - смесь черного и белого. Обозначается белым кругом.

На нулевом этапе полному изображению (рисунок 1a) сопоставляется корневой узел дерева. Далее четырем равновеликим квадрантам первого этапа разбиения (рисунок 3a) ставятся в соответствие дочерние узлы первого уровня. В показанном на рисунках частном случае северо-западный NW-квадрант обозначен белым квадратом, а остальные три - серыми кругами (рисунок 4). На очередном этапе серые квадранты снова подвергаются разбиению (на рисунке 3b для простоты показано лишь разбиение SW-квадранта). Как видно по рисунку 3b SW-квадрант на этом этапе содержит два белых, один черный и один серый подквадранты. Они представлены в дереве на рисунке 4. узлами второго уровня. Единственный серый квадрант снова разбивается. В данном случае это разбиение является последним, т.к. ни один из получившихся в результате подквадрантов не оказался серым (один белый и три черных). Подобным же образом обрабатываются и остальные квадранты изображения всех уровней. Окончательный вид квадродерева показан на рисунке 4.

  Рис. 4: Окончательный вид квадродерева

 

Результаты.

program Project1;

uses Crt;

const

XMAX = 6;

YMAX = 6;

type

TMatrix = array[1..XMAX, 1..YMAX] of Byte;

PQTree = ^TQTree;

TQTree = object

Name: string;

NW, NE, SW, SE: PQTree;

constructor Create(TreeName: string);

procedure ScanMatrix(M: TMatrix; X1, Y1, X2, Y2: Integer);

procedure View(Pad: Integer);

destructor Destroy;

end;

var

M1, M2: TMatrix;

T1, T2: PQTree;

procedure FillMatrix(var M: TMatrix);

var

x, y: Integer;

begin

Randomize;

for x := 1 to XMAX do

for y := 1 to YMAX do

if Random(6) > 0 then

M[x, y] := 1

else

M[x, y] := 0;

end;

procedure WriteMatrix(M: TMatrix);

var

x, y: Integer;

begin

for x := 1 to XMAX do

begin

for y := 1 to YMAX do

Write(M[x, y], ' ');

WriteLn;

end;

end;

constructor TQTree.Create(TreeName: string);

begin

Self.Name := TreeName;

Self.NW := nil;

Self.NE := nil;

Self.SW := nil;

Self.SE := nil;

end;

procedure TQTree.ScanMatrix(M: TMatrix; X1, Y1, X2, Y2: Integer);

var

x, y: Integer;

Finded1, Finded2: Boolean;

dx, dy: Integer;

TmpX1, TmpY1, TmpX2, TmpY2: Integer;

begin

Finded1 := False;

Finded2 := False;

for x := X1 to X2 do

for y := Y1 to Y2 do

begin

if M[x, y] = 0 then

Finded1 := True;

if M[x, y] = 1 then

Finded2 := True;

if Finded1 and Finded2 then

begin

dx := (X2 - X1) div 2;

dy := (Y2 - Y1) div 2;

{NW}

TmpX1 := X1;

TmpX2 := X1 + dx;

TmpY1 := Y1;

TmpY2 := Y1 + dy;

Self.NW := New(PQTree, Create('NW'));

Self.NW^.ScanMatrix(M, TmpX1, TmpY1, TmpX2, TmpY2);

{NE}

TmpX1 := X1 + dx + 1;

TmpX2 := X2;

TmpY1 := Y1;

TmpY2 := Y1 + dy;

Self.NE := New(PQTree, Create('NE'));

Self.NE^.ScanMatrix(M, TmpX1, TmpY1, TmpX2, TmpY2);

{SW}

TmpX1 := X1;

TmpX2 := X1 + dx;

TmpY1 := Y1 + dy + 1;

TmpY2 := Y2;

Self.SW := New(PQTree, Create('SW'));

Self.SW^.ScanMatrix(M, TmpX1, TmpY1, TmpX2, TmpY2);

{SE}

TmpX1 := X1 + dx + 1;

TmpX2 := X2;

TmpY1 := Y1 + dy + 1;

TmpY2 := Y2;

Self.SE := New(PQTree, Create('SE'));

Self.SE^.ScanMatrix(M, TmpX1, TmpY1, TmpX2, TmpY2);

Break;

end;

end;

end;

procedure TQTree.View(Pad: Integer);

var

i: Integer;

begin

if @Self <> nil then

begin

Self.NE^.View(Pad + 3);

Self.NW^.View(Pad + 3);

for i := 1 to Pad do

Write('-');

WriteLn(Self.Name);

Self.SW^.View(Pad + 3);

Self.SE^.View(Pad + 3);

end;

end;

destructor TQTree.Destroy;

begin

if @Self <> nil then

begin

if Self.NW <> nil then

Dispose(Self.NW, Destroy);

if Self.NE <> nil then

Dispose(Self.NE, Destroy);

if Self.SW <> nil then

Dispose(Self.SW, Destroy);

if Self.SE <> nil then

Dispose(Self.SE, Destroy);

end;

end;

begin

ClrScr;

FillMatrix(M1);

Writeln('Matrix 1: ');

WriteMatrix(M1);

FillMatrix(M2);

Writeln('Matrix 2: ');

WriteMatrix(M2);

T1 := New(PQTree, Create('Tree1'));

T2 := New(PQTree, Create('Tree2'));

T1^.ScanMatrix(M1, 1, 1, XMAX, YMAX);

T2^.ScanMatrix(M2, 1, 1, XMAX, YMAX);

ReadLn;

T1^.View(1);

Writeln;

ReadLn;

T2^.View(1);

ReadLn;

Dispose(T1, Destroy);

Dispose(T2, Destroy);

end.

Вывод.

Использование квадродерева продемонстрировано на классической задаче разбора бинарной матрицы N на M. Для примера в программе используется матрица 8 на 8, которая заполняется случайным образом. Сначала выводится матрица, потом выводятся данные по ходу формирования дерева, затем выводится само дерево.

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

Квадрант помечается цифрой 1 или цифрой 0, если он содержит только единицы или только нули соответственно. 

Пометки обозначают:

Root - корень,

NW - северо-запад, NE - северо-восток,

SW - юго-запад, SE - юго-восток. TQTree – класс

M1, M2: Tmatrix, T1, T2: PQTree – процедуры с помощью которых в классе создаются матрицы

В программе сделана процедура сканирования матрицы в виде метода класса. При выводе дерево как бы "лежит" на левом боку и выводится слева-направо, т.к. иначе визуализировать его в консоли затруднительно.

Рис. 5: Матрица 1,2

Рис. 6: Визуализация квадродерева по 1 матрице

Рис. 7: Визуализация квадродерева по 2 матрице

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]