Лабник по СПО
.pdfProcedure TSortThread.Execute;
Var I,J,T :Byte;
Begin
Case Box1 Of
1: Begin
QuickSort(1, 175)
End;
2:Begin
For I:=1 To 175 Do
For J:=175 DownTo I Do If Len2[I]>Len2[J] Then
Begin
T:=Len2[I];
Len2[I]:=Len2[J];
Len2[J]:=T;
m2X1:=Len2[J];
m2Y1:=J;
m2X2:=Len2[I];
m2Y2:=I;
If Terminated Then Exit; Synchronize(PaintLine2);
//Sleep(1)
End
End;
3:Begin
For I:=1 To 175 Do
For J:=174 DownTo I Do
//For I:=175 DownTo 1 Do
//For J:=1 To I-1 Do
If Len3[J]>Len3[J+1] Then
Begin
T:=Len3[J];
Len3[J]:=Len3[J+1];
Len3[J+1]:=T;
m3X1:=Len3[J];
231
PDF created with pdfFactory Pro trial version www.pdffactory.com
m3Y1:=J;
m3X2:=Len3[J+1];
m3Y2:=J+1;
If Terminated Then Exit;
Synchronize(PaintLine3); // Sleep(1)
End; fmSortTr3.BBRun.Enabled:=True; fm_SortTr3.BitBRepeat.Enabled:=True; fm_SortTr3.BBStop.Enabled:=False
End End End;
Кнопку Пуск после запуска потоков делаем недоступной. Чтобы восстановить доступность кнопки после завершения сортировки, её свойству Enabled присваиваем значение True после окончания самого медленного потока.
Создаём процедуру остановки сортировки.
Procedure TfmSortTr3.BBStopClick(Sender: TObject);
Begin
TS1.Suspend;
TS2.Suspend;
TS3.Suspend;
BBRun.Enabled:=True;
BitBRepeat.Enabled:=True;
BBStop.Enabled:=False
End;
Создаём процедуру продолжения сортировки.
Procedure TfmSortTr3.BitBRepeatClick(Sender: TObject);
Begin
TS1.Resume;
TS2.Resume;
TS3.Resume;
BBStop.Enabled:=True;
BBRun.Enabled:=False;
BitBRepeat.Enabled:=False
232
PDF created with pdfFactory Pro trial version www.pdffactory.com
End;
Создаём процедуру перерисовки линий.
Procedure TfmSortTr3.BitBPaintClick(Sender: TObject);
Var
J :Byte; CRP: TColor;
Begin
CRP:=Random(16777216);
For J:=1 To 175 Do
Begin
PaintBox1.Canvas.Pen.Color:=CRP;
PaintBox2.Canvas.Pen.Color:=CRP;
PaintBox3.Canvas.Pen.Color:=CRP;
PaintBox1.Canvas.MoveTo(0, J*2+1); PaintBox1.Canvas.LineTo(Len1[J],J*2+1); PaintBox2.Canvas.MoveTo(0, J*2+1); PaintBox2.Canvas.LineTo(Len2[J],J*2+1); PaintBox3.Canvas.MoveTo(0, J*2+1); PaintBox3.Canvas.LineTo(Len3[J],J*2+1)
End
End;
Кнопка Закрасить запускает процедуру отображения текущего состояния массива во время выполнения сортировки. Если прорисовку текущего состояния выполнить цветом, не совпадающим с исходным цветом, то будет видно, какая часть потока отсортирована.
Проверяем работу программы. Для улучшения наблюдаемости процессов сортировки можно снять комментарии с операторов задержки Sleep(1) во всех процедурах.
Реализация программы на языке С++
Написание текста проекта начнём с создания файлов потоков. Создаём три потока командами File → New ... . В диалоговом окне New Items выбираем вкладку New и объект Thread Object. В диалоговом окне ввода вводим название класса трех объектов
TNewThread1, TNewThread2, TNewThread3. Возникнут файлы с пустым описанием классов TNewThread1, TNewThread2, TNewThread3. Файлы сразу переименуем и введём
233
PDF created with pdfFactory Pro trial version www.pdffactory.com
ссылку на файлы, в которых расположены описания вновь созданных классов, в заголовочный файл главной формы.
#include "UnitTr1.h" #include "UnitTr2.h" #include "UnitTr3.h"
Ссылку на заголовочный файл главной формы введём во все новые файлы. В
заголовочном файле главной формы объявим переменные для обращения к потокам и хранения массивов.
public: // User declarations
__fastcall TfmSortTr3(TComponent* Owner); TNewThread1 *T1;
TNewThread2 *T2;
TNewThread3 *T3;
int Len1[175], Len2[175],Len3[175]; TEvent *stopEvent;
int StE;
В класс формы введена переменная stopEvent типа TEvent для принудительной остановки потоков до их естественного окончания. Если потоки не остановить, то оператор Close() не сможет закрыть форму. Чтобы ввести в программу объект типа TEvent, нужно добавить ссылку на файл библиотеки syncobjs.
#include <syncobjs.hpp>
В классе главной формы создаём объект stopEvent.
__fastcall TfmSortTr3::TfmSortTr3(TComponent* Owner) : TForm(Owner)
{this->stopEvent = new TEvent(0, true, false, 0);
}
В функции OnCreate главной формы инициализируем функцию получения случайных чисел.
void __fastcall TfmSortTr3::FormCreate (TObject *Sender)
{
Randomize;
}
Для отображения линий может быть применена функция LineTo(x,y) совместно с функцией MoveTo(x,y), переводящей курсор в исходную позицию, или функция
234
PDF created with pdfFactory Pro trial version www.pdffactory.com
Polyline(points,n), не требующая перевода курсора в исходную позицию, где points - массив точек, n - число линий. В случае рисования нескольких линий в одинаковых координатах удобнее использовать функцию Polyline, при рисовании в разных координатах проще применять функцию LineTo.
В функцию кнопки Пуск записываем операторы создания массивов чисел, рисования исходных массивов линий, длина которых равна этим числам, и создания и запуска потоков.
void __fastcall TfmSortTr3::bbRunClick (TObject *Sender)
{
stopEvent->ResetEvent(); int J;
TPoint points[2]; if (StE==0)
for (J=0;J<175 ;J=J+1)
{
PaintBox1->Canvas->Pen->Color = clBtnFace; PaintBox2->Canvas->Pen->Color = clBtnFace; PaintBox3->Canvas->Pen->Color = clBtnFace; points[0] = Point(0,J*2+1);
points[1] = Point(Len1[J],J*2+1); PaintBox1->Canvas->Polyline(points,1); PaintBox2->Canvas->Polyline(points,1); PaintBox3->Canvas->Polyline(points,1); Len1[J]=random(250); Len2[J]=Len1[J];
Len3[J]=Len1[J]; PaintBox1->Canvas->Pen->Color = clRed; PaintBox2->Canvas->Pen->Color = clRed; PaintBox3->Canvas->Pen->Color = clRed; points[0] = Point(0,J*2+1);
points[1] = Point(Len1[J],J*2+1); PaintBox1->Canvas->Polyline(points,1); PaintBox2->Canvas->Polyline(points,1); PaintBox3->Canvas->Polyline(points,1);
235
PDF created with pdfFactory Pro trial version www.pdffactory.com
}
T1=new TNewThread1(false);
T2=new TNewThread2(false);
T3=new TNewThread3(false); T1->Resume(); T2->Resume(); T3->Resume(); bbRun->Enabled=false;
}
Создаём функцию рисования массивов линий в процессе сортировки. В заголовок функции записываем в качестве формальных параметров холст и координаты линий, передаваемые из потоков.
void __fastcall TfmSortTr3::CPaint (TCanvas *Cv, int x1, int x2, int y1, int y2)
{
int M,N; TColor C;
Cv->Brush->Style=bsSolid; Cv->Pen->Color = clBtnFace; Cv->MoveTo(0, y2*2+1); Cv->LineTo(250,y2*2+1); Cv->MoveTo(0, y1*2+1); Cv->LineTo(250,y1*2+1); Cv->Pen->Color = clGreen; Cv->MoveTo(0, y2*2+1); Cv->LineTo(x2,y2*2+1); Cv->Pen->Color = clYellow; Cv->MoveTo(0, y1*2+1); Cv->LineTo(x1,y1*2+1);
for (M=0;M<6;M++) for (N=0; N<6 ;N=N+1)
{
C=random(16777216);
Cv->Pen->Color=C;
Cv->Brush->Color=C;
236
PDF created with pdfFactory Pro trial version www.pdffactory.com
Cv->Rectangle(M*5+230,N*5,M*5+220,N*5+5);
}
}
Вконце функции записываем цикл, рисующий квадратики. Цикл добавляем для замедления процессов, чтобы был лучше виден процесс сортировки.
Взаголовочном файле третьего потока объявляем переменные для хранения координат линий и функцию рисования линий в третьем потоке.
public:
__fastcall TNewThread3(bool CreateSuspended); void __fastcall PaintLine3();
int m_x1, m_y1, m_x2, m_y2;
Создаём текст функции рисования линий в третьем потоке. Функция PaintLine3 вызывает функцию перерисовки перемещаемых линий CPaint и передаёт ей координаты этих линий. void __fastcall TNewThread3::PaintLine3()
{
fmSortTr3->CPaint (fmSortTr3->PaintBox3->Canvas,m_x1,m_x2,m_y1,m_y2);
}
Создаём текст функции сортировки по весу. void __fastcall TNewThread3::Execute()
{
int I,J,T;
//for (I=174;I>=0 ;I=I-1)
//for (J=0; J<I ;J=J+1)
for (I=0;I<175 ;I=I+1) for (J=174; J>=I ;J=J-1)
if (fmSortTr3->Len3[J]>fmSortTr3->Len3[J+1])
{
T=fmSortTr3->Len3[J]; fmSortTr3->Len3[J]=fmSortTr3->Len3[J+1]; fmSortTr3->Len3[J+1]=T; m_x1=fmSortTr3->Len3[J];
m_y1=J; m_x2=fmSortTr3->Len3[J+1];
237
PDF created with pdfFactory Pro trial version www.pdffactory.com
m_y2=J+1;
if (fmSortTr3->stopEvent->WaitFor(0)==wrSignaled) return;
Synchronize(PaintLine3) ;
//Sleep(1);
}// конец перестановки по if fmSortTr3->bbRun->Enabled=true; fmSortTr3->StE=0;
SendMessage(fmSortTr3->bbRun->Handle,WM_SETFOCUS,0,0);
}
Кнопку Пуск после запуска потоков делаем недоступной. Для того чтобы восстановить доступность кнопки после окончания сортировки, её свойству Enabled присваиваем значение true и возвращаем фокус. Но команда SetFocus может работать только из главного потока, поэтому для возврата фокуса использована функция
SendMessage.
Создаём функцию остановки сортировки. void __fastcall TfmSortTr3::StopButClick (TObject *Sender)
{
stopEvent->SetEvent(); bbRun->Enabled=true; StE=1;
}
Создаём функцию прерывания сортировки. void __fastcall TfmSortTr3::AbortButClick (TObject *Sender)
{
stopEvent->SetEvent(); bbRun->Enabled=true; StE=0;
}
Создаём функцию перерисовки линий. void __fastcall TfmSortTr3::RePaintClick (TObject *Sender)
{int J;
238
PDF created with pdfFactory Pro trial version www.pdffactory.com
TPoint points[2];
for (J=0;J<175 ;J=J+1) {PaintBox1->Canvas->Pen->Color = clBlue; PaintBox2->Canvas->Pen->Color = clBlue; PaintBox3->Canvas->Pen->Color = clBlue; points[0] = Point(0,J*2+1);
points[1] = Point(Len1[J],J*2+1); PaintBox1->Canvas->Polyline(points,1); points[1] = Point(Len2[J],J*2+1); PaintBox2->Canvas->Polyline(points,1); points[1] = Point(Len3[J],J*2+1); PaintBox3->Canvas->Polyline(points,1);
}
}
Кнопка Перерисовка должна обеспечить запуск процесса отображения текущего состояния массива в любой момент выполнения сортировки. Если прорисовку текущего состояния выполнять цветом, не совпадающим с исходным цветом и цветом сортировки, то будет видно, какая часть потока отсортирована.
В заголовочном файле второго потока объявляем переменные для хранения координат линий и функцию рисования линий во втором потоке.
public:
void __fastcall PaintLine2();
__fastcall TNewThread2(bool CreateSuspended); int m_x1, m_y1, m_x2, m_y2;
};
Создаём текст функции рисования линий во втором потоке. void __fastcall TNewThread2::PaintLine2() {fmSortTr3->CPaint (fmSortTr3->PaintBox2->Canvas,m_x1,m_x2,m_y1,m_y2);
}
Создаём текст функции сортировки вставками. void __fastcall TNewThread2::Execute()
{
int J,I,Idx,T;
for (I=0;I<175 ;I++)
239
PDF created with pdfFactory Pro trial version www.pdffactory.com
{
idx=I;
for (J=I; J<175 ;J++)
{
if (fmMain->Len2[idx]>fmMain->Len2[J])
{
idx=J;
//Sleep(1);
}// конец if
}// конец цикла for по j
T = fmSortTr3->Len2[I]; fmSortTr3->Len2[I]=fmSortTr3->Len2[idx]; fmSortTr3->Len2[idx]=T; m_x1=fmSortTr3->Len2[idx];
m_y1=idx;
m_x2=fmSortTr3->Len2[I]; m_y2=I;
if (fmSortTr3->stopEvent->WaitFor(0) == wrSignaled) return;
Synchronize(PaintLine2) ;
}//конец цикла for по i
}
В заголовочном файле первого потока объявляем переменные для хранения координат линий, функцию рисования линий в первом потоке и функцию быстрой сортировки.
public:
__fastcall TNewThread1(bool CreateSuspended); void __fastcall PaintLine1();
void __fastcall QuickSort ( int *array, int iLo, int iHi );
int m_x1, m_y1, m_x2, m_y2;
Создаём текст функции рисования линий в первом потоке. void __fastcall TNewThread1::PaintLine1()
240
PDF created with pdfFactory Pro trial version www.pdffactory.com