powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Тяпничная пирамида
25 сообщений из 126, страница 3 из 6
Тяпничная пирамида
    #39393498
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ДмитрийИнтересно есть ли какие-то алгоритмы сортировки заточенные на почти отсортированные массивы?

В том случае, если число неотсортированных элементов значительно меньше размера исходного массива, то подойдет сортировка вставками. Попробуй её на своих данных, если у тебя будет время)
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39393502
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
При этом в качестве структуры данных вероятно стоит организовать дерево, вставка будет за
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39393551
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TЯ время меряю std::sort() и своего цикла. На сортированном массиве.
этого мало, иногда сравнение дорого, иногда перемещение
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39393587
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
bool is_sort(std::string *a, size_t size) {
	if (size <= 1) return true;
	for (size_t i = 1; i < size; i++) {
		if (a[i - 1] > a[i]) {
			return false;
		}
	}
	return true;
}


Может быть эта проверка... кхм... слишком пессимистична?
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39393612
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonMasterZiv, давай

Чего вам давать?
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39393625
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)Dima TЯ время меряю std::sort() и своего цикла. На сортированном массиве.
этого мало, иногда сравнение дорого, иногда перемещение
Согласен, надо поискать реализации QuickSort и счетчики туда вставить.
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39393626
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonМожет быть эта проверка... кхм... слишком пессимистична?
Проверка корректна, постановка задачи слишком строгой оказалась.
Не учел что есть такая хрень как Unicode Collation Algorithm где 5 видов сравнения и все правильные.
Поэтому получив отсортированное извне, моя проверка считает его несортированным. Например сортировка от MSSQL не совпадает с сортировкой в ASCII
MSSQLASCIIa/ba+ba+ba-baaaa/ba-baaaabcabc
Думаю надо подход менять:
Первый проход запоминание элементов стоящих не на своих местах, при количестве >N считаем массив несортированным и сортируем алгоритмом со стабильной сложностью O(n log(n)) (std::sort() и т.п.).
При <N облегченная сортировка, например вставками, как Саша предлагает, можно свой велосипед поизобретать с использованием запомненного на первом проходе.

Тут надо с размером N определиться. Тупо в процентах не вариант, т.к. исходим из того что выбираем между алгоритмом стабильно дающим O(n log(n)) и нестабильным где от O(n) в случае сортированного до O(n 2 ) в случае обратноотсортированного.

С первым проходом тоже неясно как быть, например последовательность
Код: plaintext
1.
1,9,2,3,4,5,6,7,8


тут можно посчитать что 9 не на месте, а можно 2,3,4,5,6,7,8

Как вариант сразу начинать сортировать вставками и останавливаться при каком-то количестве перестановок и/или сравнений.

Немного конкретики: я этим в C# занимаюсь, в массиве ссылка на объект хранится, сравниваются строки до 100 символов, совпадение начал соседних строк до 30 символов частое явление. Думаю тут сравнение значительно тяжелее чем перестановка. Думаю можно перестановки не учитывать для упрощения.
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39393670
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тест на реальных данных со встроенным алгоритмом сортировки. Вставил счетчик в функцию сравнения.
Сортировал реальные, почти сортированные данные. Сортировка - вызовов при сортировке, Повтор - сортировка сортированного.
ЭлементовСортировкаПовтор812569456265526579885491862476695563590633866454630181456117681816065114757181573161943
Сравнений в 10-12 раз больше чем элементов. Если сортировать в обратную сторону до 15 раз доходит.
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39393917
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonMasterZiv, давай
Up. Есть новости?
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39393942
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сортировка вставками почти отсортированного массива ускорила сортировку в 10 раз. Как и предполагалось.
Я туда двоичный поиск добавил для поиска места вставки. Без него особого ускорения не было.

Стоимость сравнения и перестановки в моем случае оказались примерно одинаковы, поэтому повесил все на общий счетчик и ограничил количество операций сортировки вставками 3-мя размерами массива, т.е. если не хватило 2N операций, то запуск стандартной сортировки. Цифра выбрана методом научного тыка :)

Итого: получилась сортировка сложностью от O(n) до O(n (log(n) + 3))

А ту задачу 20151862 (добавление в сортированный массив) вообще по другому решил, в один проход.
Исходники
Писал на C#, но если кому надо на С переписать не сложно
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
		// Сортировка почти отсортированного массива
		public static void SortOrdered<T>(this List<T> a) where T : IComparable<T> {
			if(a.Count <= 1) return;
			Int32 cnt = a.Count * 2; // Количество дополнительных операций, после которого считаем несортированным
			for(Int32 i = 1; i < a.Count; i++) {
				if(a[i-1].CompareTo(a[i]) > 0) { // a[i-1] > a[i], a[i] надо сдвинуть назад
					if(cnt < 0) { // несортированно
						a.Sort(); // полноценная сортировка
						return;
					}
					// Поиск места вставки
					T x = a[i];
					Int32 r = 0, l = i - 1; 
					while (r < l) {
						cnt--;
						Int32 c = (r + l) / 2;
						Int32 cmp = x.CompareTo(a[c]);
						if(cmp <= 0) { // x <= a[c]
							l = c;
							if (cmp == 0) break;
						} else { // x > a[c]
							r = c + 1;
						}
					}
					// Сдвиг влево [l,i-1]
					cnt -= i - l;
					for(Int32 j = i; j > l; j--) {
						a[j] = a[j-1];
					}
					a[l] = x;
				}
			}
		}

		//Объединение сортированных массивов
		public static List<T> ClueOrdered<T>(List<T> a1, List<T> a2) where T : IComparable<T> {
			Int32 cnt1 = a1.Count, cnt2 = a2.Count, i1 = 0, i2 = 0;
			var ret = new List<T>(cnt1 + cnt2);
			while(i2 < cnt2 || i1 < cnt1) {
				if(i2 == cnt2 || (i1 < cnt1 && a1[i1].CompareTo(a2[i2]) < 0)) {
					ret.Add(a1[i1]);
					i1++;
				} else if(i2 < cnt2) {
					ret.Add(a2[i2]);
					i2++;
				}
			}
			return ret;
		}

...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39394112
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T, для "почти сортированного" хорошо подходит merge-sort. В первую фазу
мы детектируем границы суб-последовательностей а во вторую - действуем
согласно каноническому слиянию.

Но возможно для тебя "почти отсортированный" определяется как-то иначе... и
возможно стоит уточнить или даже привести пример генератора почти-* последовательностей.
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39394126
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonНо возможно для тебя "почти отсортированный" определяется как-то иначе... и
возможно стоит уточнить или даже привести пример генератора почти-* последовательностей.
Вот писал 20156048 , почти сортированный, это сортированный с другим пониманием юникода. Как-то поднимал топик про эти грабли .
Т.е. из-за этих нюансов строка немного не на своем месте оказывается. Так-то пофиг, но есть второй вариант - вообще не сортированный, его надо сортировать.

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

Началось все с того что у меня разбор XML в 200 Мб занимает 3.5 сек вместе с записью обратно на диск, а промежуточная сортировка сожрала 5+ сек., я ее запараллелил, но все равно она тормозит. Сейчас 0.5 сек.
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39394233
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T, про Unicode я не очень понял. Мне кажется это - должно конфигурироваться извне
или подключаться как плагин к сортировке. Ну... я-бы забил болт и сортировал байты.

Далее. По поводу последовательности

Код: plaintext
1.
1,9,2,3,4,5,6,7,8



Я-бы выделил в ней две под-последовательности
Код: plaintext
1.
[1,9] , [2,3,4,5,6,7,8]



Они - монотонные. Неубывающие. И хорошо проходят через merge-sort.

В противоположность. Если на вход пойдет белый шум длиной N элементов - то нужно эвристически
принять решение о его НЕПРИГОДНОСТИ к частичным методам даже если случайно
в нем будут меньше чем N подпоследовательностей. Ну в общем надо исходить из
какой-то разумной пропорции.
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39394386
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonDima T, про Unicode я не очень понял. Мне кажется это - должно конфигурироваться извне
или подключаться как плагин к сортировке. Ну... я-бы забил болт и сортировал байты.
Данные из разных источников, разным софтом генерятся. Например тот софт сортирует {aaa, a-b, abc} а мой считает что "a-b" < "aaa", т.е. должно быть так {a-b, aaa, abc}.
В C# вообще отличились с дефолтной сортировкой, например это отсортировано по их мнению {ИГРА, Й ОГА, ИРА}.

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

Но иногда данные приходят вообще не сортированные и тут возникла проблема как отличить первое от второго, т.к. в первом случае для сортировки надо сдвинуть 5-10 элементов на 1-10 позиций, во втором - полноценная сортировка. Всегда делать полноценную сортировку оказалось медленно. Отсюда вопрос и родился. Сортировка вставками очень даже к месту пришлась для первого случая.
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39394390
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А ну ОК.

Вообще я смотрю тема сортировок не на шутку возбудила сообщество. Думаю поднять тяпничный
топик на тему merge. И, помнится Илья хвастался дескыть есть у него в тайные рукописи... чего-то
там дженерик и на сях.

У меня тоже есть мысли по поводу внешних сортировок.
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39394712
д0kХ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dima TmaytonНо возможно для тебя "почти отсортированный" определяется как-то иначе... и
возможно стоит уточнить или даже привести пример генератора почти-* последовательностей.
Вот писал 20156048 , почти сортированный, это сортированный с другим пониманием юникода. Как-то поднимал топик про эти грабли .
Т.е. из-за этих нюансов строка немного не на своем месте оказывается. Так-то пофиг, но есть второй вариант - вообще не сортированный, его надо сортировать.

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

Началось все с того что у меня разбор XML в 200 Мб занимает 3.5 сек вместе с записью обратно на диск, а промежуточная сортировка сожрала 5+ сек., я ее запараллелил, но все равно она тормозит. Сейчас 0.5 сек.

Сочуствую , но сортировки в разных кодировках везде аццкий треш.
Особенно когда кодировка в БД одна , а на клиентах другие и разные
обязательно где то вылаят какие то бока.

Я каждый раз когда сталкиваюсь всегда вспоминаю и перечитаваю http://utf8everywhere.org/
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39394772
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonА ну ОК.

Вообще я смотрю тема сортировок не на шутку возбудила сообщество. Думаю поднять тяпничный
топик на тему merge. И, помнится Илья хвастался дескыть есть у него в тайные рукописи... чего-то
там дженерик и на сях.

У меня тоже есть мысли по поводу внешних сортировок.
Это естественно, мы так привыкли пользоваться библами, которые в реализации довольно сложны, что многие и не могут адекватную сортировку написать. Вот затыки на казалось бы вполне понятных местах и вызывают желание разобраться.
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39395008
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А я подумал что ты не будешь пробовать inserting sort. Дмитрий, а почему на C#, тут какое-то преимущество для данного конкретного случая? По коду вроде бы не очевидно.


maytonDima T, для "почти сортированного" хорошо подходит merge-sort. В первую фазу
мы детектируем границы суб-последовательностей а во вторую - действуем
согласно каноническому слиянию.

Но возможно для тебя "почти отсортированный" определяется как-то иначе... и
возможно стоит уточнить или даже привести пример генератора почти-* последовательностей.

Честно говоря я не очень понимаю, каковы все-таки преимущества merge sort в данном случае. Insertion sort выглядит прозрачным и логичным решением. А в качестве метрики неупорядоченности массива можно использовать, например, количество элементов местоположение которых нужно изменить для того, чтобы массив стал упорядоченным. Где-то об этом читал, но уже не помню где
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39395010
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryА я подумал что ты не будешь пробовать inserting sort. Дмитрий, а почему на C#, тут какое-то преимущество для данного конкретного случая? По коду вроде бы не очевидно.
Задача у меня реальная, написана на C#, поэтому C#. Переписать на С/С++ не сложно.
Я тоже не думал что буду пробовать :) читал вскользь вики - не понял, но ты упомянул, я перечитал - понял что это то что надо.
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39395011
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryЧестно говоря я не очень понимаю, каковы все-таки преимущества merge sort в данном случае. Insertion sort выглядит прозрачным и логичным решением. А в качестве метрики неупорядоченности массива можно использовать, например, количество элементов местоположение которых нужно изменить для того, чтобы массив стал упорядоченным. Где-то об этом читал, но уже не помню где
Сложность O(n) - O(n log(n)) против O(n) - O(n 2 ) вот и вся разница.
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39395182
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T,

довольно примечательная сортировка J-сортировка
её можно ещё немного оптимизировать
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39395822
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)Dima T,

довольно примечательная сортировка J-сортировка
её можно ещё немного оптимизировать
Сомневаюсь что на больших массивах будет работать. Автор честно сознался
авторЧем длиннее массив, тем чаще такие вырожденные узлы будет возникать. А значит, в средней полосе длинных массивов сортировке вставками придётся изрядно потрудиться.
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39395845
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Запилил тест
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
#include <windows.h>
#include <stdio.h>

#include <string>
#include <vector>
#include <algorithm>
#include <time.h>

// -------------------------------------------------------
#ifdef _DEBUG
#define TEST_SIZE 20
#else
#define TEST_SIZE 10000000
#endif
// -------------------------------------------------------
int32_t compare_cnt; // Счетчик сравнений
int32_t copy_cnt; // Счетчик копирований
clock_t start;

class item_t {
public:
	char data[10];

	item_t() {}

	item_t(const item_t& b) { *this = b; }

	static int compare(item_t const &a, item_t const &b) {
		compare_cnt++;
		return memcmp(a.data, b.data, sizeof(item_t));
	}

	int compare(item_t const &b) {
		compare_cnt++;
		return memcmp(data, b.data, sizeof(item_t));
	}

	bool operator > (item_t const &b) { return compare(b) > 0; }
	bool operator >= (item_t const &b) { return compare(b) >= 0; }
	bool operator < (item_t const &b) { return compare(b) < 0; }
	bool operator <= (item_t const &b) { return compare(b) <= 0; }
	bool operator == (item_t const &b) { return compare(b) == 0; }
	item_t& operator = (item_t const &b) {
		copy_cnt++;
		memcpy(data, b.data, sizeof(item_t));
		return *this;
	}

	item_t& operator = (int x) {
		_itoa(x, data, 10);
		return *this;
	}

	void swap(item_t &b) {
		item_t t = *this;
		*this = b;
		b = t;
	}

	static void swap(item_t &a, item_t &b) {
		item_t t = a;
		a = b;
		b = t;
	}
};

// -------------------------------------------------------
std::vector<item_t> a(TEST_SIZE); // Тестовый массив

// старт замера
void reset() {
	compare_cnt = 0;
	copy_cnt = 0;
	start = clock();
}

// Вывод текущего состояния
void print() {
	size_t max = a.size() < 20 ? a.size() : 20;
	for (size_t i = 0; i < max; i++) {
		printf("'%s',", a[i].data);
	}
	if (max < a.size()) printf("...");
	printf("\n");
}

// вывод результата
void result(const char* title, std::vector<item_t>* res = NULL) {
	clock_t t = clock() - start;
	printf("%s %d ms %d copies %d compares\n", title, t, copy_cnt, compare_cnt);
	if(res == NULL) {
		if(!std::is_sorted(a.begin(), a.end())) printf("!!! Not sorted\n");
	} else {
		if (!std::is_sorted(res->begin(), res->end())) printf("!!! Not sorted\n");
	}
	static FILE* f = NULL;
	if (f == NULL) {
		f = fopen("result.txt", "w");
	}
	if (f != NULL) {
		fprintf(f, "%s,%d,%d,%d\n", title, t, copy_cnt, compare_cnt);
		fflush(f);
	}
}

// Заполнение тестового массива
void fill() {
	uint32_t k = 1234567;
	for (size_t i = 0; i < a.size(); i++) {
		_itoa(k % (TEST_SIZE * 2), a[i].data, 10);
		k = (k * 65537 + 2017);
	}
	printf("Fill %d OK\n", a.size());
}

// -------------------------------------------------------
// тест qsort()
int compare(const void * a, const void * b) {
	return item_t::compare(*(item_t*)a, *(item_t*)b);
}

__declspec(noinline) void test1() {
	reset();
	qsort(&a[0], a.size(), sizeof(item_t), compare);
	result("qsort()");
}

// -------------------------------------------------------
// тест std::sort()
__declspec(noinline) void test2() {
	reset();
	std::sort(a.begin(), a.end());
	result("std::sort()");
}

// -------------------------------------------------------
// тест quick sort https://ru.wikibooks.org/wiki/%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D0%BE%D0%B2/%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0/%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%B0%D1%8F
void quick_sort(item_t* s_arr, int first, int last)
{
	int i = first, j = last;
	item_t x = s_arr[(first + last) / 2];

	do {
		while (s_arr[i] < x) i++;
		while (s_arr[j] > x) j--;

		if (i <= j) {
			if (s_arr[i] > s_arr[j]) item_t::swap(s_arr[i], s_arr[j]);
			i++;
			j--;
		}
	} while (i <= j);

	if (i < last)
		quick_sort(s_arr, i, last);
	if (first < j)
		quick_sort(s_arr, first, j);
}

__declspec(noinline) void test3() {
	reset();
	quick_sort(&a[0], 0, a.size() - 1);
	result("quick_sort()");
}

// -------------------------------------------------------
// тест merge sort https://ru.wikipedia.org/wiki/%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%BB%D0%B8%D1%8F%D0%BD%D0%B8%D0%B5%D0%BC

/**
* Сортирует массив, используя рекурсивную сортировку слиянием
* up - указатель на массив, который нужно сортировать
* down - указатель на массив с, как минимум, таким же размером как у 'up', используется как буфер
* left - левая граница массива, передайте 0, чтобы сортировать массив с начала
* right - правая граница массива, передайте длину массива - 1, чтобы сортировать массив до последнего элемента
* возвращает: указатель на отсортированный массив. Из-за особенностей работы данной реализации
* отсортированная версия массива может оказаться либо в 'up', либо в 'down'
**/
item_t* merge_sort(item_t* up, item_t* down, unsigned int left, unsigned int right)
{
	if (left == right)
	{
		down[left] = up[left];
		return down;
	}

	unsigned int middle = (unsigned int)((left + right) * 0.5);

	// разделяй и сортируй
	item_t *l_buff = merge_sort(up, down, left, middle);
	item_t *r_buff = merge_sort(up, down, middle + 1, right);

	// слияние двух отсортированных половин
	item_t *target = l_buff == up ? down : up;

	unsigned int width = right - left, l_cur = left, r_cur = middle + 1;
	for (unsigned int i = left; i <= right; i++)
	{
		if (l_cur <= middle && r_cur <= right)
		{
			if (l_buff[l_cur] < r_buff[r_cur])
			{
				target[i] = l_buff[l_cur];
				l_cur++;
			}
			else
			{
				target[i] = r_buff[r_cur];
				r_cur++;
			}
		}
		else if (l_cur <= middle)
		{
			target[i] = l_buff[l_cur];
			l_cur++;
		}
		else
		{
			target[i] = r_buff[r_cur];
			r_cur++;
		}
	}
	return target;
}

__declspec(noinline) void test4() {
	reset();
	std::vector<item_t> b(TEST_SIZE);
	item_t* r = merge_sort(&a[0], &b[0], 0, a.size() - 1);
	if(r == &a[0]) {
		result("merge_sort()");
	} else {
		result("merge_sort()", &b);
	}
}

//----------------------------------------------------------------------------------
// Моя самодельная Insert sort+

void insert_sort(std::vector<item_t>& a) {
	// Сортировка почти отсортированного массива
	int size = a.size();
	if (size <= 1) return;
	int cnt = size * 2; // Количество дополнительных операций, после которого считаем несортированным
	for (int i = 1; i < size; i++) {
		if (a[i - 1] > a[i]) { // a[i] надо сдвинуть назад
			if (cnt < 0) { // несортированно
				std::sort(a.begin(), a.end()); // полноценная сортировка
				return;
			}
			// Поиск места вставки
			item_t x = a[i];
			int r = 0, l = i - 1;
			while (r < l) {
				cnt--;
				int c = (r + l) / 2;
				int cmp = item_t::compare(x, a[c]);
				if (cmp <= 0) { // x <= a[c]
					l = c;
					if (cmp == 0) break;
				}
				else { // x > a[c]
					r = c + 1;
				}
			}
			// Сдвиг влево [l,i-1]
			cnt -= i - l;
			for (int j = i; j > l; j--) {
				a[j] = a[j - 1];
			}
			a[l] = x;
		}
	}
}

__declspec(noinline) void test5() {
	reset();
	insert_sort(a);
	result("insert_sort()");
}


int main()
{
	printf("Test unordered\n");
	fill();
	print();
	test1();
	fill();
	test2();
	fill();
	test3();
	fill();
	test4();
	fill();
	test5();
	printf("\nTest ordered\n");
	test1();
	test2();
	test3();
	test4();
	test5();

	return 0;
}


Результат 5-ти видов сортировки на массиве в 10 млн. элементов. Места ставил по времени.
Несортированный
АлгоритмВремя мсКопированийСравненийПримечаниеmerge_sort()1 990243 222 784230 068 109из инетаstd::sort()2 035338 720 497375 556 538MSVC2015insert_sort()2 049363 169 751376 875 415моя поделкаquick_sort()2 510168 421 944389 659 279из инетаqsort()3 045н/д277 090 450MSVC2015
Сортированный
АлгоритмВремя мсКопированийСравненийinsert_sort()520 19 999 998std::sort()48017 415 788220 483 043quick_sort()5526 465 373243 606 228merge_sort()827243 222 784129 428 083qsort()1 054н/д237 187 025
Выводы:
1. qsort() тормозит из-за того что функция сравнения не инлайнится, в остальном относительно неплохо. Количество копирований неизвестно, т.к. замерить можно только вызовы сравнений.
2. merge_sort() (скопипащено из вики ) показала неплохой результат на несортированном массиве, но заявленные O(n) на сортированном не айс, копирует много и рекурсия. Может реализация не лучшая, но пробовал несколько, остальные еще тормознее.
3. insert_sort() моя поделка комбинация сортировки вставками и std::sort()

ИМХО надо merge_sort() скрещивать с сортировкой вставками, как mayton предложил 20159478 . Должно взлететь. Есть мысли в этом направлении.

PS Не довелось тему сортировок изучить, образование не программистское, в фокспро все на таблицах, т.е. SQL, т.е. order by и готово. "Удивило" что log 2 (15000) = 14, просто никогда не задумывался об этом, поэтому интересно побыть студентом :)
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39395887
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TСомневаюсь что на больших массивах будет работать. Автор честно сознался
авторЧем длиннее массив, тем чаще такие вырожденные узлы будет возникать. А значит, в средней полосе длинных массивов сортировке вставками придётся изрядно потрудиться.
ага, фигня получилась:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
JSort с небольшой оптимизацией 
  inverse array: time=2250  CompareCount=272457260  ChangeCount=272590534
  sorted  array: time=0  CompareCount=0  ChangeCount=0
  randomic array: time=1031  CompareCount=127509157  ChangeCount=126205133
HeapSort
  inverse array: time=16  CompareCount=2928116  ChangeCount=1497536
  sorted  array: time=31  CompareCount=4256886  ChangeCount=2937924
  randomic array: time=32  CompareCount=3059438  ChangeCount=1628454

но где проблемы с HeapSort он правильно подметил
...
Рейтинг: 0 / 0
Тяпничная пирамида
    #39395914
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)Dima T,

довольно примечательная сортировка J-сортировка
её можно ещё немного оптимизировать
Спасибо. Интересная статья. Жаль что автор не расчитал среднюю оценку O(n).
...
Рейтинг: 0 / 0
25 сообщений из 126, страница 3 из 6
Форумы / C++ [игнор отключен] [закрыт для гостей] / Тяпничная пирамида
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]