Додайте клас Form1 і клас SortingArrs, в яких вже є код швидкого сортування.
namespace Sorting
{
public partial class Form1 : Form
{
SortingArrs A;
public int m, n = 1;
public Form1()
{ InitializeComponent(); }
private void AddColumns(int n, DataGridView dgw)
{
DataGridViewColumn column;
for (int i = 0; i < n; i++)
{ column = new DataGridViewColumn();
column.HeaderText = "Column" + i.ToString();
column.Name = "Column" + i.ToString();
dgw.Columns.Add(column.Name, column.HeaderText);
}
}
private void AddRows(int m, DataGridView dgw)
{
for (int i = 0; i <m; i++)
{
dgw.Rows.Add(); dgw.Rows[i].HeaderCell.Value = i.ToString();
}
}
private void размерМассиваToolStripMenuItem_Click(object sender, EventArgs e)
{
this.textBoxArraySize.Enabled = true;
if (string.IsNullOrWhiteSpace(textBoxArraySize.Text))
{
MessageBox.Show("Поле не должно быть пустым!");
return;
}
m = int.Parse(this.textBoxArraySize.Text);
}
private void создатьМассивToolStripMenuItem_Click(object sender, EventArgs e)
{
m = int.Parse(this.textBoxArraySize.Text);
A = new SortingArrs(m);//Создание массива
A.FillRndNumbers();
int k; k = this.dataGridView1.ColumnCount; //Чистка таблицы
if (k != 0)
for (int i = 0; i < k; i++)
this.dataGridView1.Columns.RemoveAt(0);
n = 1;
AddColumns(n, this.dataGridView1);
AddRows(m, this.dataGridView1);
}
Додайте в меню пункти заповнення масиву і обробник події Click нього.

private void заполнитьМассивToolStripMenuItem_Click(object sender, EventArgs e)
{
this.A.FillRndNumbers();
for (int i = 0; i < m; i++)
{ dataGridView1.Rows[i].Cells[0].Value = this.A.arr[i].ToString(); }
}
private void перезагрузитьИсходныToolStripMenuItem_Click(object sender, EventArgs e)
{
label3.Text = "Время в миллисекундах ";
for (int i = 0; i < m; i++)
{
dataGridView1.Rows[i].Cells[0].Value = this.A.copyarr[i].ToString();
A.arr[i] = A.copyarr[i];
}
}
Додайте в меню пункти вибора алгоритмів сортування і обробники подій Click них.

private void быстраяСортировкаToolStripMenuItem_Click(object sender, EventArgs e)
{
A.QuickSort(); this.label3.Text += "QuickSort";
textBox1.Text = A.AnalyseTimeQuickSort().Time.ToString();
this.textBoxSwapCount.Text=A.AnalyseTimeQuickSort().CountSwap.ToString();
for (int i = 0; i < m; i++)
{
dataGridView1.Rows[i].Cells[0].Value = this.A.arr[i].ToString();
}
}
private void сортировкаСлияниемToolStripMenuItem_Click(object sender, EventArgs e)
{
A.SortMerge(); this.label3.Text += "MergeSort";
textBox1.Text = A.AnalyseTimeMergeSort().Time.ToString();
this.textBoxSwapCount.Text = A.AnalyseTimeMergeSort().CountSwap.ToString();
for (int i = 0; i < m; i++)
{
dataGridView1.Rows[i].Cells[0].Value = this.A.arr[i].ToString();
}
}
private void пирамидальнаяСортировкаToolStripMenuItem_Click(object sender, EventArgs e)
{
A.PyramidSort(); this.label3.Text += "PyramidSort";
textBox1.Text = A.AnalyseTimeHeapSort().Time.ToString();
this.textBoxSwapCount.Text = A.AnalyseTimeHeapSort().CountSwap.ToString();
for (int i = 0; i < m; i++)
{
dataGridView1.Rows[i].Cells[0].Value = this.A.arr[i].ToString();
}
}
private void выходToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void textBoxArraySize_KeyPress(object sender, KeyPressEventArgs e)
{
// Разрешить клавиши управления: Backspace, Delete, стрелки
if (char.IsControl(e.KeyChar))
return;
// Разрешить только цифры
if (!char.IsDigit(e.KeyChar))
e.Handled = true;
}
}
}
Клас SortingArrs, в якому вже є код швидкого сортування, долайте інші.
namespace Sorting
{
public struct Analyse
{
public long Time { get; set; }
public long CountSwap { get; set; }
public Analyse(long time, long countSwap)
{
Time = time;
CountSwap = countSwap;
}
}
internal class SortingArrs
{
//delegate
public delegate void SortMethod();
int n; //размер массива
int Heap_Size; //размер пирамиды, построенной на массиве
public int[] arr; //сортируемый массив
public int[] copyarr;
Random rnd;
private long swapCount; // счетчик перестановок
//конструктор класса
public SortingArrs(int n)
{
this.n = n;
this.arr = new int[n]; this.copyarr = new int[n];
Heap_Size = n;
rnd = new Random();
swapCount = 0;
}
public int this[int n]
{
get
{
return arr[n];
}
}
public void FillRndNumbers()
{
for (int i = 0; i < n; i++)
{
arr[i] = rnd.Next(-1000, 1000);
copyarr[i] = arr[i];
}
}
// Вспомогательный метод для обмена элементов с подсчетом
private void Swap(ref int a, ref int b)
{
int temp = a;
a = b;
b = temp;
swapCount++;
}
// Вызывает рекурсивную процедуру QSort,
// передавая ей границы сортируемого массива.
// Сортируемый массив arr задается
// соответствующим полем класса.
public void QuickSort()
{
swapCount = 0; // сброс счетчика перед сортировкой
QSort(0, n - 1);
}
void QSort(int start, int finish)
{
if (start != finish)
{
int ind = rnd.Next(start, finish);
int item = arr[ind];
int ind1 = start, ind2 = finish;
/********
Введем три непересекающихся множества:
S1: {arr(i), start <= i =< ind1-1}
S2: {arr(i), ind1 <= i =< ind2}
S1: {arr(i), ind2+1 <= i =< finish}
Введем следующие логические условия,
играющие роль инвариантов циклов нашей программы:
P1: объединение S1, S2, S3 = arr
P2: (S1(i) < item) Для всех элементов S1
P3: (S3(i) >= item) Для всех элементов S3
P4: item - случайно выбранный элемент arr
Нетрудно видеть, что все условия становятся
истинными после завершения инициализатора цикла.
Для пустых множеств S1 и S3 условия P2 и P3
считаются истинными по определению.
Inv = P1 & P2 & P3 & P4
********/
while (ind1 <= ind2)
{
while ((ind1 <= ind2) && (arr[ind1] < item)) ind1++;
//(Inv == true) & ~B1 (B1 - условие цикла while)
while ((ind1 <= ind2) && (arr[ind2] >= item)) ind2--;
//(Inv == true) & ~B2 (B2 - условие цикла while)
if (ind1 < ind2)
{
Swap(ref arr[ind1], ref arr[ind2]);
ind1++; ind2--;
}
//(Inv ==true)
}
if (ind1 == start)
{
Swap(ref arr[start], ref arr[ind]);
QSort(start + 1, finish);
}
else
{
QSort(start, ind1 - 1);
QSort(ind2 + 1, finish);
}
}
}
//HeapSort - SortTree - PyramidSort
// Рекурсивная поцедура просеивания элемента по древу (пирамиде)
// Основная компонента построения пирамиды для массива
// и построения отсортированного массива по пирамиде
private void Seed(int i)
{
//просеивание элемента с индексом i,
//нарушающего свойство пирамидальности массива
int l = 2 * i + 1, r = l + 1; //индексы левого и правого потомка
if (l > Heap_Size - 1) return; //это лист пирамиды
int cand = i;
if (arr[i] < arr[l]) cand = l;
if ((r <Heap_Size) && (arr[cand] < arr[r])) cand = r;
if (cand != i) //обмен
{
Swap(ref arr[i], ref arr[cand]);
Seed(cand); //Просеивание вниз
}
}
// Преобразует массив arr в пирамиду
// Массив является пирамидой, если для каждого элемента массива,
// не являющегося листом пирамиды, его значение меньше или равно
// значения двух его потомков
private void MakePyramid()
{
int m = (n - 2) / 2;
//m- индекс последнего элемента, имеющего потомков
//элементы с индексами, большими m, являются листьями пирамиды
for (int k = m; k >= 0; k--)
Seed(k);
}
// Пирамидальная сортировка
// Вначале по массиву строится пирамида
// затем по пирамиде строится отсортированный массив
public void PyramidSort()
{
swapCount = 0; // сброс счетчика перед сортировкой
Heap_Size = arr.Length;
MakePyramid();
for (int i = 0; i < n - 1; i++)
{
Swap(ref arr[0], ref arr[Heap_Size - 1]);
Heap_Size--;
Seed(0);
}
}
// Сортировка слиянием
public void SortMerge()
{
swapCount = 0; // сброс счетчика перед сортировкой
int[] temp = new int[arr.Length];
SortM(0, n - 1, temp);
}
// Рекурсивная процедура сортировки слиянием
void SortM(int start, int finish, int[] temp)
{
if (start < finish)
{
int mid = (start + finish) / 2;
SortM(start, mid, temp);
SortM(mid + 1, finish, temp);
Merge(start, mid, finish, temp);
}
}
// Слияние отсортированных частей масссива в массив temp
// После слияния массив переписывается в исходный массив
void Merge(int start, int mid, int finish, int[] temp)
{
int topl = start, topr = mid + 1, topt = start;
//Слияние, пока не завершится одна из частей массива
while ((topl <= mid) && (topr <= finish))
{
if (arr[topl] <= arr[topr])
temp[topt++] = arr[topl++];
else
temp[topt++] = arr[topr++];
}
//дописывание остатка незавершенной части массива
while (topl <= mid)
temp[topt++] = arr[topl++];
while (topr <= finish)
temp[topt++] = arr[topr++];
//переливаем элементы в исходный массив
for (int i = start; i <= finish; i++)
{
if (arr[i] != temp[i]) // считаем только реальные перестановки
{
arr[i] = temp[i];
swapCount++;
}
}
}
// Поиск за линейное время(в среднем) квантили
// массива порядка k.
//При k = n/2 квантиль задает медиану массива.
//порядок квантили returns квантиль порядка k
public int Find(int k)
{
swapCount = 0; // сброс счетчика перед поиском
int l = 0, r = n - 1;
int x = 0;
while (l < r)
{
x = arr[k]; //барьер
//Разбиение на два подмножества
int i = l, j = r;
do
{
while (arr[i] < x) i++;
while (x < arr[j]) j--;
if (i <= j)
{
if (arr[i] != arr[j])
{//обмен
Swap(ref arr[i], ref arr[j]);
}
i++; j--;
}
}
while (i <= j);
//Изменение границ интервала поиска
if (j < k) l = i;
if (k < i) r = j;
}
return (arr[k]);
}
// Подсчет времени сортировки
// Сортируется один и тот же массив 10000 раз
// Метод сортировки передается как параметр
//>Метод сортировки returns время сортировки
private long HowLong(SortMethod sort)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
sort();
stopwatch.Stop();
return stopwatch.ElapsedMilliseconds;
}
//Подсчет количества перестановок сортировки
// Метод сортировки передается как параметр
// Метод сортировки returns количество операций перестановок
private long HowCountSwap(SortMethod sort)
{
// Восстанавливаем исходный массив перед каждой сортировкой
Array.Copy(copyarr, arr, n);
swapCount = 0;
sort();
return swapCount;
}
public Analyse AnalyseSort(SortMethod method)
{
// Восстанавливаем исходный массив перед анализом
Array.Copy(copyarr, arr, n);
long time = HowLong(method);
// Восстанавливаем исходный массив перед подсчетом перестановок
Array.Copy(copyarr, arr, n);
long countSwap = HowCountSwap(method);
return new Analyse(time, countSwap);
}
public Analyse AnalyseTimeQuickSort()
{
Analyse a = AnalyseSort(QuickSort);
return a;
}
public Analyse AnalyseTimeHeapSort()
{
Analyse a = AnalyseSort(PyramidSort);
return a;
}
public Analyse AnalyseTimeMergeSort()
{
Analyse a = AnalyseSort(SortMerge);
return a;
}
}
}


