Быстрая сортировка
Быстрая сортировка, как и следует из её названия, является одной из самых быстрых и эффективных из известных сортировок. Как и в сортировке слиянием, массив разбивается на две части, с условием, что все элементы первой части меньше любого элемента второй. Потом каждая часть сортируется отдельно. Разбиение на части достигается упорядочиванием относительно некоторого элемента массива, т. е. в первой части все числа меньше либо равны этому элементу, а во второй, соответственно, больше либо равны. Два индекса проходят по массиву с разных сторон и ищут элементы, которые попали не в свою группу. Найдя такие элементы, их меняют местами. Тот элемент, на котором индексы пересекутся, и определяет разбиение на группы.
Цифровая сортировка целых неотрицательных чисел
В ходе цифровой сортировки (также называемой поразрядной сортировкой) данные разбиваются на "разряды", после этого данные сортируются какой-либо устойчивой сортировкой по каждому разряду, в порядке от младшего разряда к старшему. Для чисел наиболее часто в качестве устойчивой сортировки применяют сортировку подсчетом.
Идея алгоритма сортировки подсчётом заключается в простом подсчете количества вхождений каждого числа в массив. Это делается так: выполним один проход массива и для каждого числа из отрезка [0, max] подсчитаем сколько раз оно встретится. Вычисленные количества сохраним в специальном массиве счетчиков. Затем запишем в массив – результат (а это может быть и исходный массив) каждое число столько раз, чему равно значение соответствующего ему счетчика, то есть, сколько раз оно встретилось.
Листинг программ:
Быстрая сортировка
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Быстрая_сортировка
{
class Program
{
static int partition(int[] array, int start, int end)
{
int marker = start;
for (int i = start; i <= end; i++)
{
if (array[i] <= array[end])
{
int temp = array[marker];
array[marker] = array[i];
array[i] = temp;
marker += 1;
}
}
return marker - 1;
}
static void quicksort(Int32[] array, int start, int end)
{
int pivot;
if (start >= end)
{
return;
}
pivot = partition(array, start, end);
quicksort(array, start, pivot - 1);
quicksort(array, pivot + 1, end);
}
static void Main(string[] args)
{
#region Read from file
List<int> lst = new List<int>();
using (StreamReader sr = new StreamReader(@"C:\500k.txt"))
{
while (!sr.EndOfStream)
{
string str = sr.ReadLine();
int value = int.Parse(str);
lst.Add(value);
}
}
#endregion
#region Цикл копирования массива
Int32[] arr = new Int32[lst.Count];
for (int i = 0; i < lst.Count; ++i)
{
arr[i] = (int)lst[i];
}
#endregion
#region Засекаем время
int start = DateTime.Now.Minute * 60000 + DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;
quicksort(arr,0,arr.Length-1);
int finish = DateTime.Now.Minute * 60000 + DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;
int delta = finish - start;
#endregion
System.Console.WriteLine("Время работы алгоритма сортировки слиянием c размерностью массива в {0} элементов: {1} миллисекунд(ы)\n\n", arr.Length, delta);
System.Console.WriteLine("Нажмите клавишу <Enter>");
Console.ReadKey();
}
}
}
Сортировка Шелла
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace СортировкаШелла
{
class Program
{
static Int32[] sort_shall(Int32[] mass) {
Int32[] s_massive = new Int32[mass.Length];
s_massive = mass;
int tmp = s_massive.Length / 2;
while (tmp > 0)
{
int i, j;
for (i = tmp; i < s_massive.Length; i++)
{
int value = s_massive[i];
for (j = i - tmp; (j >= 0) && (s_massive[j] > value); j -= tmp)
s_massive[j + tmp] = s_massive[j];
s_massive[j + tmp] = value;
}
tmp /= 2;
}
return s_massive;
}
static void Main(string[] args)
{
#region Read from file
List<int> lst = new List<int>();
using (StreamReader sr = new StreamReader(@"C:\50k.txt"))
{
while (!sr.EndOfStream)
{
string str = sr.ReadLine();
int value = int.Parse(str);
lst.Add(value);
}
}
#endregion
#region Инициализация массива
Int32[] massive = new Int32[lst.Count];
#endregion
// копирование массива lst
for (Int32 i = 0; i < lst.Count; ++i) {
massive[i] = (int)lst[i];
}
#region Засекаем время
int start = DateTime.Now.Minute * 60000 + DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;
//осуществление сортировки
massive = sort_shall(massive);
int finish = DateTime.Now.Minute * 60000 + DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;
int delta = finish - start;
#endregion
System.Console.WriteLine("Время работы алгоритма сортировки слиянием c размерностью массива в {0} элементов: {1} миллисекунд(ы)\n\n", massive.Length, delta);
System.Console.WriteLine("\n\n");
System.Console.WriteLine("Нажмите клавишу <Enter>");
System.Console.ReadLine();
}
}
}
Сортировка слиянием
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace СортировкаСлиянием
{
class Program
{
static Int32[] Sortirovat(Int32[] massive)
{
if (massive.Length == 1)
return massive;
Int32 half_part = massive.Length / 2;
return sliyanie(Sortirovat(massive.Take(half_part).ToArray()), Sortirovat(massive.Skip(half_part).ToArray()));
}
static Int32[] sliyanie(Int32[] part_1, Int32[] part_2)
{
Int32 a = 0, b = 0;
Int32[] sliyanied = new int[part_1.Length + part_2.Length];
for (Int32 i = 0; i < part_1.Length + part_2.Length; i++)
{
if (b < part_2.Length && a < part_1.Length)
if (part_1[a] > part_2[b] && b < part_2.Length)
sliyanied[i] = part_2[b++];
else
sliyanied[i] = part_1[a++];
else
if (b < part_2.Length)
sliyanied[i] = part_2[b++];
else
sliyanied[i] = part_1[a++];
}
return sliyanied;
}
static void Main(string[] args)
{
#region Read from file
List<int> lst = new List<int>();
using (StreamReader sr = new StreamReader(@"C:\50k.txt"))
{
while (!sr.EndOfStream)
{
string str = sr.ReadLine();
int value = int.Parse(str);
lst.Add(value);
}
}
#endregion
#region Цикл копирования массива
Int32[] arr = new Int32[lst.Count];
for (int i = 0; i < lst.Count; ++i) {
arr[i] = (int)lst[i];
}
#endregion
#region Вывод массива до сортировки
#endregion
#region Засекаем время
int start = DateTime.Now.Minute*60000 + DateTime.Now.Second*1000 + DateTime.Now.Millisecond;
arr = Sortirovat(arr);
int finish = DateTime.Now.Minute*60000 + DateTime.Now.Second*1000 + DateTime.Now.Millisecond;
int delta = finish - start;
#endregion
System.Console.WriteLine("Время работы алгоритма сортировки слиянием c размерностью массива в {0} элементов: {1} миллисекунд(ы)\n\n",arr.Length,delta);
#region Вывод отсортированного массива
#endregion
System.Console.WriteLine("Нажмите клавишу <Enter>");
System.Console.ReadLine();
}
}
}
Пирамидальная сортировка
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Пирамидальная_сортировка
{
class Program
{
static Int32 add2pyramid(Int32[] arr, Int32 i, Int32 N)
{
Int32 imax;
Int32 buf;
if ((2 * i + 2) < N)
{
if (arr[2 * i + 1] < arr[2 * i + 2]) imax = 2 * i + 2;
else imax = 2 * i + 1;
}
else imax = 2 * i + 1;
if (imax >= N) return i;
if (arr[i] < arr[imax])
{
buf = arr[i];
arr[i] = arr[imax];
arr[imax] = buf;
if (imax < N / 2) i = imax;
}
return i;
}
static void Pyramid_Sort(Int32[] arr, Int32 len)
{
//создаем пирамиду
for (Int32 i = len / 2 - 1; i >= 0; --i)
{
long prev_i = i;
i = add2pyramid(arr, i, len);
if (prev_i != i) ++i;
}
//сортировка
Int32 buf;
for (Int32 k = len - 1; k > 0; --k)
{
buf = arr[0];
arr[0] = arr[k];
arr[k] = buf;
Int32 i = 0, prev_i = -1;
while (i != prev_i)
{
prev_i = i;
i = add2pyramid(arr, i, k);
}
}
}
static void Main(string[] args)
{
#region Read from file
List<int> lst = new List<int>();
using (StreamReader sr = new StreamReader(@"C:\50k.txt"))
{
while (!sr.EndOfStream)
{
string str = sr.ReadLine();
int value = int.Parse(str);
lst.Add(value);
}
}
#endregion
#region Цикл копирования массива
Int32[] arr = new Int32[lst.Count];
for (int i = 0; i < lst.Count; ++i)
{
arr[i] = (int)lst[i];
}
#endregion
#region Засекаем время
int start = DateTime.Now.Minute * 60000 + DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;
//сортировка
Pyramid_Sort(arr, arr.Length);
int finish = DateTime.Now.Minute * 60000 + DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;
int delta = finish - start;
#endregion
System.Console.WriteLine("Время работы алгоритма сортировки слиянием c размерностью массива в {0} элементов: {1} миллисекунд(ы)\n\n", arr.Length, delta);
System.Console.WriteLine("\n\n Нажмите клавишу <Enter>");
System.Console.ReadLine();
}
}
}
Цифровая сортировка
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.IO;
namespace Цифровая_сортировка
{
class Program
{
static void sorting(int[] arr, int range, int length)
{
ArrayList[] lists = new ArrayList[range];
for (int i = 0; i < range; ++i)
lists[i] = new ArrayList();
for (int step = 0; step < length; ++step)
{
//распределение по спискам
for (int i = 0; i < arr.Length; ++i)
{
int temp = (arr[i] % (int)Math.Pow(range, step + 1)) /
(int)Math.Pow(range, step);
lists[temp].Add(arr[i]);
}
//сборка
int k = 0;
for (int i = 0; i < range; ++i)
{
for (int j = 0; j < lists[i].Count; ++j)
{
arr[k++] = (int)lists[i][j];
}
}
for (int i = 0; i < range; ++i)
lists[i].Clear();
}
}
static void Main(string[] args)
{
#region Read from file
List<int> lst = new List<int>();
using (StreamReader sr = new StreamReader(@"C:\50k.txt"))
{
while (!sr.EndOfStream)
{
string str = sr.ReadLine();
int value = int.Parse(str);
lst.Add(value);
}
}
#endregion
#region Цикл копирования массива
Int32[] arr = new Int32[lst.Count];
for (int i = 0; i < lst.Count; ++i)
{
arr[i] = (int)lst[i];
}
#endregion
#region Засекаем время
int start = DateTime.Now.Minute * 60000 + DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;
// сортировка
sorting(arr, 10, 2);
int finish = DateTime.Now.Minute * 60000 + DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;
int delta = finish - start;
#endregion
System.Console.WriteLine("Время работы алгоритма сортировки слиянием c размерностью массива в {0} элементов: {1} миллисекунд(ы)\n\n", arr.Length, delta);
System.Console.WriteLine("Нажмите клавишу <Enter>");
Console.ReadKey();
}
}
}
Создание и заполнение файлов
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Создание_и_заполнение_файла
{
class Program
{
static void Main(string[] args)
{
Random random = new Random();
#region Write to file (50000)
using (StreamWriter sw = new StreamWriter(@"C:\50k.txt", false))
{
for (int i = 0; i < 50000; i++)
{
sw.WriteLine(random.Next(0, 10000));
}
}
#endregion
#region Write to file (100000)
using (StreamWriter sw = new StreamWriter(@"C:\100k.txt", false))
{
for (int i = 0; i < 100000; i++)
{
sw.WriteLine(random.Next(0, 10000));
}
}
#endregion
#region Write to file (500000)
using (StreamWriter sw = new StreamWriter(@"C:\500k.txt", false))
{
for (int i = 0; i < 500000; i++)
{
sw.WriteLine(random.Next(0, 10000));
}
}
#endregion
#region Write to file (1000000)
using (StreamWriter sw = new StreamWriter(@"C:\1m.txt", false))
{
for (int i = 0; i < 1000000; i++)
{
sw.WriteLine(random.Next(0, 10000));
}
}
#endregion
#region Write to file (5000000)
using (StreamWriter sw = new StreamWriter(@"C:\5m.txt", false))
{
for (int i = 0; i < 5000000; i++)
{
sw.WriteLine(random.Next(0, 10000));
}
}
#endregion
#region Write to file (10000000)
using (StreamWriter sw = new StreamWriter(@"C:\10m.txt", false))
{
for (int i = 0; i < 10000000; i++)
{
sw.WriteLine(random.Next(0, 10000));
}
}
#endregion
}
}
}
Результат работы:
Временные гистограммы алгоритмов:
Вывод: в ходе данной работы было произведено сравнение быстродействий алгоритмов сортировок при различных размерностях входных массивов. Время работы сортировки массива со временем при увеличении размерности массива увеличивается в среднем в несколько раз.