Популярные алгоритмы сортировки массивов

0. Ekovichev 793 18.10.13 13:29 Сейчас в теме
Разбор популярных алгоритмов сортировки массивов, реализованных на 1с. + обработка с наглядной реализацией алгоритмов.



Перейти к публикации

Вознаграждение за ответ
Показать полностью
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. Поручик 4637 19.10.13 01:08 Сейчас в теме
Где бы их ещё применить для 1С. Взял на заметку, может где понадобится.
2. Yashazz 4512 20.10.13 11:02 Сейчас в теме
Всю жизнь полагал, что в 1С применяется или быстрая, или шелловская сортировка. Интересно, что там на самом деле. Автор, делались ли замеры скорости, насколько метод списка значений выигрывает?
3. Ekovichev 793 20.10.13 13:38 Сейчас в теме
Мне думается, что в 1с используется быстрая сортировка. Сравнения делались между сортировкой списком и быстрой сортировкой. Разница в сортировке массива размерностью 10 000 и значениями диапазоном от 0 до 100 при сортировке списком значений и быстрой сортировкой вообще незаметна. А вот на массиве размерностью 100 000 диапазон значений от 0 до 1000, сортировка списком значений показала результат около 2-3 секунд, а быстрая в среднем 6-7 секунд.
4. Поручик 4637 20.10.13 14:51 Сейчас в теме
(0) Вижу исправили. Вчера Был перебор массива в функции СортировкаСпискомЗначений(). Хотел написать, но отвлёкся.

мСписокЗнч = ЗагрузитьЗначения(Массив);
5. Ekovichev 793 20.10.13 15:01 Сейчас в теме
Да, вчера сам перечитал статью и заметил, понял, что не стоит писать по ночам)
6. hame1e00n 523 20.10.13 18:48 Сейчас в теме
Полезная информация, спасибо!
7. EliasShy 48 21.10.13 06:38 Сейчас в теме
Хорошо было бы написать жадность алгоритмов в нотации большого О.
8. Ekovichev 793 21.10.13 06:42 Сейчас в теме
Хорошо, добавлю в статью
9. PowerBoy 3263 21.10.13 07:52 Сейчас в теме
Очепятки:
Если Массив[i-1] - по убыванию
i = j;
j = j + 1;
Иначе



Если ij Тогда
Прервать;
КонецЕсли;

10. Ekovichev 793 21.10.13 08:11 Сейчас в теме
Исправил, спасибо за замечание
11. juntatalor 63 21.10.13 14:23 Сейчас в теме
Мне приходилось использовать "свою" сортировку для сортировки дерева значений на управляемой форме. Уж не помню, чем меня не устраивал метод ДанныеФормыДерево -> ДеревоЗначений -> Сортировка -> ДанныеФормыДерево, но быстрая сортировка на клиенте подошла лучше.
12. mikmike 8 22.10.13 06:14 Сейчас в теме
а метод двоичного дерева?
У меня в свое время была курсовая по методам сортировки.
Так метод двоичного дерева на больших массивах сильно быстрей работает
PS 1C тогда и в проекте не существовало. Алгоритм сложный, рекурсивный, но шустрый на больших массивах.
13. Ekovichev 793 22.10.13 06:33 Сейчас в теме
Да метод бинарного дерева интересен, я его посмотрел, начал писать на 1С и что-то не закончил :) Но если будет интересно, можно и его рассмотреть
18. mikmike 8 23.10.13 06:31 Сейчас в теме
(13) теоритически конечно интересно - у меня в свое время заметный выигрыш получался на массивах из сотен и более элементов. 10 чисел быстрее всего упорядочивает самый простой алгоритм.
Но вот на сколько реальна задача? Приведите кто-нибудь пример из жизни, пожалуйста.
14. ediks 334 22.10.13 16:18 Сейчас в теме
15. KAPACEB.AA 452 22.10.13 21:55 Сейчас в теме
16. KAPACEB.AA 452 22.10.13 21:57 Сейчас в теме
Если не ошибаюсь, в сортировке вставками вместо:


Пока j > 0 Цикл
Если Замена < Массив[j - 1] Тогда
Массив[j] = Массив[j - 1];
Замена = j - 1;
Ключ = j - 1;
КонецЕсли;
j = j - 1;
КонецЦикла;


в идеале должно быть так:

Пока j > 0 И Замена < Массив[j - 1] Цикл
Массив[j] = Массив[j - 1];
Замена = j - 1;
Ключ = j - 1;
j = j - 1;
КонецЦикла;

В таком случае не будет бессмысленного перебора элементов в уже отсортированной части массива.

Пруфлинк
17. Ekovichev 793 22.10.13 22:03 Сейчас в теме
(16) Mu_meson, Вы правы, поправил.
19. пользователь 23.10.13 11:13
Сообщение было скрыто модератором.
...
20. gruk 7 23.10.13 12:27 Сейчас в теме
А вот на массиве размерностью 100 000 диапазон значений от 0 до 1000, сортировка списком значений показала результат около 2-3 секунд, а быстрая в среднем 6-7 секунд.

ИМХО: Дак наверное и не получится "сортировку списком значений" обогнать. Это же функция платформы, а любые самописные алгоритмы требуют время на интерпритацию команд.

Вот еще надо проверить, сколько памяти массив и список отъедают, и может в жизни и пригодиться для обработки очень больших массивов.

Думал, что в конце статьи увижу табличку с замером производительности алгоритмов и потребляемыми ресурсами :(

Но все равно плюсую, познавательно.
21. Ekovichev 793 23.10.13 12:30 Сейчас в теме
(20) gruk, Сделаю, хорошая идея. Насчет времени все ясно, только как замерить потребляемые ресурсы?
24. gruk 7 24.10.13 04:27 Сейчас в теме
(21) Я имел ввиду оценить ресурсы приблизительно. Допустим "Сортировка вставками" потребляет мало, т.к. не нужен доп. массив и используется всего 4 переменных. (Кстати, если сделать процедуру и работать не со Знач массив, а со ссылкой, то ресурсов потребуется в 2 раза меньше.) Экономия ресурсов - 5. А "Сортировка слиянием" создает новые массивы. Экономия - 3.
Почему я заговорил про ресурсы, пишу програмку, там использую 2-х мерные большие массивы. Комп слабоват. Сортирую через таблицы значений и память подъедает заметно, винда начинает использовать файл подкачки и падает производительность.

Замер памяти я делал так: запускал 1с, консоль программиста, писал код, смотрел потребляемую память через дисп.задач, запускал код(в конце выводил предупреждение, чтоб массив не уничтожился), опять смотрел память.
Результаты с 100 000 элементов от 0 до 65535 такие: Массив ~800 Кб, СписокЗначений ~9,5 Мб, ТаблицаЗначений с одной колонкой ~5,8 Мб. Еще заметил что после массива память освобождается почти сразу, а после списка или таблицы нет (но если запустить второй раз, увеличение потребления памяти уже намного меньше)
25. gruk 7 24.10.13 04:37 Сейчас в теме
(21) насчет времени все просто.

Scr = Новый COMОбъект("MSScriptControl.ScriptControl"); 
Scr.Language = "javascript"; 

ВремяНачалаВыполнения = Scr.Eval("new Date().getTime()");

   //выполнить код

ВремяКонцаВыполнения = Scr.Eval("new Date().getTime()");
ВремяВыполнения = ВремяКонцаВыполнения - ВремяНачалаВыполнения; //время в милисекундах
Показать


Откуда взял, не помню, да простит меня автор.
user1795406; +1 Ответить
22. DAnry 8 23.10.13 13:06 Сейчас в теме
Спасибо. Достаточно полный анализ по узкой теме. Однозначно +
23. Evil Beaver 7872 23.10.13 14:54 Сейчас в теме
Еще бы неплохо написать, какой именно алгоритм скрывается за 1С-овским "СортироватьПоЗначению()". Сейчас уже не найду, но вроде бы где-то проскакивало в сети, что там qsort, т.е. быстрая сортировка.
26. Ekovichev 793 24.10.13 06:42 Сейчас в теме
Как будет время проведу тест и в таблице опубликую. Замер времени вы взяли отсюда http://infostart.ru/public/71130/ :)
27. CagoBHuK 32 25.10.13 14:20 Сейчас в теме
Однозначный плюс за труд.
29. Ekovichev 793 25.10.13 15:10 Сейчас в теме
(28) kasper076, Я тоже сегодня на хабре прочел, заинтересовался:)
30. mikhailovaew 127 28.11.13 12:47 Сейчас в теме
эх, где тут ildarovich, он бы еще каждый алгоритм оптимизировал с ускорением работы в 5 раз )
31. saver77 36 06.03.14 15:29 Сейчас в теме
Спасибо за проделанную работу. Имею два предложения по быстрой сортировке:
1. Для наглядности вызов ОтобразитьДиаграммуСортировки лучше разместить в цикле, тогда нагляднее будет.
2. Полагаю, так красивее, если условие выхода из цикла перенести из оператора Если в оператор Пока.
В итоге код процедуры будет такой

Процедура б_Сортировка(Массив,НижнийПредел,ВерхнийПредел)

    i    = НижнийПредел;
    j    = ВерхнийПредел;
    m    = Массив[Цел((i+j)/2)];
	
	//Пока Истина Цикл
	Пока i<=j Цикл  		
		
        Пока Массив[i] < m Цикл            
            i    = i + 1;                   
		КонецЦикла;
		
        Пока Массив[j] > m Цикл            
            j    = j - 1;                   
        КонецЦикла; 
        
        Если i<=j Тогда               
            Замена            = Массив[i];
            Массив[i]    = Массив[j];
            Массив[j]    = Замена;
            i            = i + 1;
            j            = j - 1;            
			Если ПрименитьОтображениеСортировки Тогда	
				ОтобразитьДиаграммуСортировки(Массив);	
			КонецЕсли;			
        КонецЕсли;
        
		//Если i>j Тогда                       
		//	Прервать;                        
		//КонецЕсли;
        
	КонецЦикла;
	
    Если НижнийПредел < j Тогда         
        б_Сортировка(Массив,НижнийПредел,j);        
	КонецЕсли; 
	
    Если i < ВерхнийПредел Тогда                      
        б_Сортировка(Массив,i,ВерхнийПредел);        
    КонецЕсли;
    
КонецПроцедуры
Показать
Артано; 🅵🅾️🆇; Ekovichev; +3 Ответить
32. tarasenkov 339 20.06.14 12:46 Сейчас в теме
В коде процедуры быстрой сортировки забыли важную часть:
       Если i <= j Тогда               
            Замена       = Массив[i];
            Массив[i]    = Массив[j];
            Массив[j]    = Замена;
            i            = i + 1;
            j            = j - 1;            
        КонецЕсли;

(Обработку скачал, там этот код есть)
user1286487; AlexDiablo; Астиг; 🅵🅾️🆇; Фаршик; Ekovichev; +6 Ответить
45. Астиг 18 25.02.19 15:36 Сейчас в теме
(32) А я смотрю на быструю сортировку, и не понимаю, где же тут обмен элементами то?))
33. JohnConnor 61 22.12.14 07:43 Сейчас в теме
однозначна нужная вещь, для изучения алгоритмов
34. Sasha25 26.12.14 11:24 Сейчас в теме
Ну прямо таки даже и не знаю что и сказать. Наверное конечно фундаментальными знаниями нужно владеть
35. pakill 43 20.01.15 03:30 Сейчас в теме
Когда-то, еще до нашей эры (ДОС, Паскаль) придумал метод сортировки: "разноской по значению" и для сравнения написал маленькую демо-програмку.
Прикрепленные файлы:
SORTDEMO.EXE
SORTDEMO.PAS
SORTSHOW.PAS
DoctorRoza; +1 Ответить
36. DoctorRoza 03.02.15 11:11 Сейчас в теме
Отмечусь, может пригодится! Хотя .. обрабатывать в 1С Массив(), да еще и большим количеством элементов .. в какой задаче такое возможно? :)
37. AlexO 132 03.02.15 11:16 Сейчас в теме
(36) DoctorRoza,
в какой задаче такое возможно?
Например, в задаче, где в массив запихнута огромная ТЗ ))
38. platon_ 10 21.08.15 16:59 Сейчас в теме
В Алгоритм "Гномья сортировка".
Упущена часть кода в первом условии
Если Массив[i-1]  < Массив[i]
unknownDaemon; +1 Ответить
39. sadiv 21 31.08.16 19:55 Сейчас в теме
Добавил управляемую форму.
Прикрепленные файлы:
СортировкиМассиваУпр.epf
40. mark_oilbass 19.05.18 15:54 Сейчас в теме
Отличная статья! Спасибо автору)
41. пользователь 22.06.18 17:17
Сообщение было скрыто модератором.
...
42. 1Cnik) 22.06.18 17:42 Сейчас в теме
У вас в алгоритме вставками вроде как ошибка, проверьте на маленьких массивах, в теле цикла
Пока j > 0 И Замена < Массив[j - 1] Цикл
            Массив[j] = Массив[j - 1];
            Замена = j - 1;
            Ключ = j - 1; 
            j = j - 1;
        КонецЦикла; 

Когда замена примет значение 0, то ниже в значение массива просто подставиться 0

Переделал алгоритм на более логичный, убрал ненужные переменные
Для i = 1 По Массив.ВГраница() Цикл 					
		Замена = Массив[i];          
		j = i;
		Пока j > 0 И Массив[j - 1] > Замена Цикл  
			Массив[j] = Массив[j - 1]; 
			j = j - 1;
		КонецЦикла;		
		Массив[j] = Замена;
				
	КонецЦикла;
Показать
43. 1Cnik) 24.06.18 18:08 Сейчас в теме
Так же в быстрой сортировке в теле
Если i<=j Тогда               
            Замена            = Массив[i];
            Массив[i]    = Массив[j];
            Массив[j]    = Замена;
            i            = i + 1;
            j            = j - 1;            
        КонецЕсли;
        
        Если i>j Тогда                       
            Прервать;                        
        КонецЕсли;
Показать

Когда i = j, то элемент массива просто заменит сам себя. Это глупо по логике, можно добавить условие для красоты.
Если i<=j Тогда
			Если М[i] = М[j] Тогда
				i = i + 1;
				j = j - 1;
			Иначе
				Замена = М[i];
				М[i] = М[j];
				М[j] = Замена;
				i = i + 1;
				j = j - 1;            	
			КонецЕсли;
		КонецЕсли;
		
        Если i>j Тогда                       
            Прервать;                        
        КонецЕсли;
Показать
44. vlakur1 04.11.18 10:31 Сейчас в теме
.Алгоритм "Сортировка выбором" можно добавить -1 во внешний цикл

Для i = 0 По Массив.ВГраница() Цикл -1
.....
46. user1355753 07.07.21 21:31 Сейчас в теме
Пример работы с массивом документов.
В списке выделили несколько накладных и хотите их распечатать по дате (масив содержит ссылки на РН)
если в массиве происходит хоть одна перестановка, то после окончания перебора,
перебор стартует еще раз. Перестановок не было - цикл заканчиваеться.

&НаСервере
Процедура ПечатьСписком(ТабДок,ТабДок_счета, ПараметрКоманды)
	
кол_док = ПараметрКоманды.количество();	
не_сортирован=Истина;	
пока не_сортирован цикл
	тд=0; не_сортирован=ложь;
	
пока тд<кол_док-2 цикл
если ПараметрКоманды[тд].дата>ПараметрКоманды[тд+1].дата тогда
темп_док = ПараметрКоманды[тд+1]; 	
ПараметрКоманды[тд+1] = ПараметрКоманды[тд];
ПараметрКоманды[тд] = темп_док;
не_сортирован = Истина;
КонецЕсли;
тд = тд+1;
КонецЦикла;

КонецЦикла;  // массив отсортирован

	Документы.РНОпт_БН.ПечатьСписком(ТабДок,ТабДок_счета,ПараметрКоманды);
КонецПроцедуры
Показать
47. TyurinArt 73 28.09.22 18:00 Сейчас в теме
Начал изучать алгоритмы, предлагаю быструю сортировку математика Хоара через рекурсию без замены:

Функция б_Сортировка(Массив)
	
	Если Массив.вграница() = -1 Тогда
		Возврат Массив;
	КонецЕсли;	
		
    сред = Массив[Цел(Массив.ВГраница()/2)];
	
	мин = Новый Массив();

	макс = Новый Массив();
	
	отсортированный = Новый Массив();	
	
	Для Каждого н из Массив цикл
		
		Если н < сред Тогда 
			мин.Добавить(н);
		ИначеЕсли н > сред Тогда
			макс.Добавить(н);
		Иначе
			отсортированный.Добавить(н);
		КонецЕсли;
		
	КонецЦикла;
	
	Возврат ОбъеденитьМассивы(ОбъеденитьМассивы(б_Сортировка(мин), отсортированный), б_Сортировка(макс));	

КонецФункции


Функция ОбъеденитьМассивы(Приемник, Источник)
	
	Для Каждого н Из Источник Цикл 	
		Приемник.добавить(н);
	КонецЦикла;
	
	Возврат Приемник;
	
КонецФункции
Показать
48. user1701201 19.04.23 22:40 Сейчас в теме
Дали задачу с сортировкой массива на собеседовании.
Позднее получилось следующее (похоже на гномью сортировку):

Индекс = 1;
Пока Индекс < Массив.Количество() Цикл
Если Массив[Индекс - 1] < Массив[Индекс] Тогда
Индекс = Индекс + 1;
Иначе
Замена = Массив[Индекс];
Массив[Индекс] = Массив[Индекс - 1];
Массив[Индекс - 1] = Замена;
Индекс = Индекс - 1;
Если Индекс = 0 Тогда
Индекс = Индекс + 2;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Оставьте свое сообщение
Вакансии
Программист/тестировщик
Москва
зарплата от 130 000 руб. до 150 000 руб.
Полный день

Ведущий разработчик 1С / Team lead отдела разработки 1С
Москва
зарплата от 300 000 руб. до 300 000 руб.
Полный день

Программист 1С
Москва
зарплата от 130 000 руб. до 150 000 руб.
Полный день

Бизнес-аналитик
Москва
зарплата от 130 000 руб. до 150 000 руб.
Полный день

Аналитик-архитектор 1С ЕРП (управленческого учета)
Москва
зарплата от 300 000 руб. до 300 000 руб.
Полный день