· Начало · Отвђтить · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.A&O —› Вопрос по сортировке

. 1 . 2 . 3 . >>

Посл.отвђт Сообщенiе


Дата: Янв 16, 2004 13:42:55

В книге Касперски "Оптимизация программ" описывается очень "соблазнительный" алгоритм линейной сортировки. Приведен также пример сортировки чисел типа float(правда для меня непонятный ). Может у кого есть идеи как реализовать подобное,но по другому, с сохранением скорости линейной сортировки (очень надо)?

P.S. В догонку: может у кого валяется исходник быстрой сортировки на асме?


Дата: Янв 16, 2004 13:56:38

HeDiN
Для чисел Float?
Так он же отличается только функцией сравнения.


Дата: Янв 16, 2004 14:01:02

;tasm
;qsort(array,nitems,itemsize,cmpproc([edx],[edi])) pascal
;cmpproc must save ebp,esi,edi,edx
proc    qsort nolanguage; pascal decl
arg     @@arr:dword,@@len:dword,@@size:dword,@@cmpp:dword=argsize
        push ebp
        mov ebp,esp
        mov esi,[@@arr]
        mov eax,[@@len]
        dec eax
        mul [@@size]
        lea edi,[esi+eax]
        call @@qs
        mov esp,ebp
        pop ebp
        ret argsize
@@rt:
        ret
@@2:
        pop esi
        call @@qs
        mov esi,edi
        add esi,[@@size]
        pop edi
@@qs:
        cmp esi,edi
        jae @@rt
        push edi
        push esi
        mov edx,esi
        sub esi,[@@size]
        add edi,[@@size]
@@0:
        sub edi,[@@size]
        call [@@cmpp]
        test eax,eax
        jl @@0
        xchg esi,edi
@@1:
        add edi,[@@size]
        call [@@cmpp]
        test eax,eax
        jg @@1
        xchg esi,edi
        cmp esi,edi
        jae @@2
        mov ecx,[@@size]
        jmp @@5
@@4:
        dec ecx
        mov al,[esi+ecx]
        xchg [edi+ecx],al
        mov [esi+ecx],al
        jz @@0
@@5:
        test cl,3
        jnz @@4
@@3:
        sub ecx,4
        mov eax,[esi+ecx]
        xchg [edi+ecx],eax
        mov [esi+ecx],eax
        jnz @@3
        jmp @@0
endp    qsort


Дата: Янв 16, 2004 14:10:20

А это в качестве бонуса:
(defun qsort(list meth % Local: % l0 l1 l2 key)
   ((null list) NIL)
   ((null (cdr list)) list)
   (setq key (car list))
   (loop
      ((null list))
      (if (eval (list meth (car list) key))
         (setq l0 (cons (car list) l0))
         (if (eval (list meth key (car list)))
            (setq l2 (cons (car list) l2))
            (setq l1 (cons (car list) l1))
         )
      )
      (setq list (cdr list))
   )
   (append (qsort l0 meth) l1 (qsort l2 meth))
)

(qsort '(1 6 23 8 12 5 12 0 4 41 14 6 22 7 9 0) <)
(qsort '(1 6 23 8 12 5 12 0 4 41 14 6 22 7 9 0) >)
(return)


Дата: Янв 16, 2004 14:27:58 · Поправил: HeDiN

Edmond
Непонятна функция PrepareMem()( из книги). Дальше по тексту:" Во-первых, не плохо было бы проверить, чем закончилось выделение 16 Гбайт памяти". Почему 16, а не 4,
(float ведь 32 бита). Где под Windows мы возьмем пускай 4 гига, без извращений с разделением на процессы(как у Касперски)?
Black_mirror
Thx. Только мне бы хотелось обойтись без вызова функции сравнения,т.е. встроить ее код в основной. И объясни,пожалуйста, бонус :)


Дата: Янв 16, 2004 16:40:38

HeDiN
Я посмотрю её дома.
Что насчёт касперски, АWE позваляет использовать свыше 2 Гб


Дата: Янв 16, 2004 17:08:44

@@2:
        pop esi
        call @@qs
        lea esi,[edi+4]
        pop edi
@@qs:;(esi - pfirst, edi - plast)
        cmp esi,edi
        jae @@rt
        push edi
        push esi
        mov edx,esi
        sub esi,4
        add edi,4
@@0:
        sub edi,4
        fld dword [edx]
        fcomp dword [edi]
        fstsw ax
        sahf
        jc @@0
        xchg esi,edi
@@1:
        add edi,4
        fld dword [edx]
        fcomp dword [edi]
        fstsw ax
        sahf
        ja @@0
        xchg esi,edi
        cmp esi,edi
        jae @@2
        mov eax,[esi]
        xchg [edi],eax
        mov [esi],eax
        jmp @@0
@@rt:
        ret

А что касается бонуса то это тот же quick-sort только на языке lisp. list это список который нужно отсортировать, meth это та же функция сравнения. Если в списке 0 элементов то функция возвращает пустой список. Если в списке 1 элемент то возвращается сам список. Далее первый элемент выбирается в качестве ключа, а затем все элементы распределябтся по трем спискам: в l0 - '<key', в l1 - '=key', а в l2 - '>key' (в предположении, что в качестве meth используется '<'). После чего, в качестве результата, возвращается объединение отсортированного l0 ,l1 и отсортированного l2.


Дата: Янв 16, 2004 17:31:08

Edmond
Извиняюсь, за темноту, но что такое AWE?

Black_mirror
Я листинг на Лиспе буду вместо мантры при медитации использовать:)))


Дата: Янв 16, 2004 18:50:53

HeDiN
Addres Window Extention (прошу прощения за плохой Английский) :()


Дата: Янв 17, 2004 14:32:01 · Поправил: HeDiN

Вот еще непонятное место:

"Причем, этот результат можно существенно улучшить, если прибегнуть к услугам разряженных массивов, а не тупо сканировать массив vurtual_array целиком!"

1. Массив vurtual_array упоминается только в этом месте и о его назначении можно только догадываться.
2. Кто-нибудь может сказать в чем идея, наверное все таки
разреженных, а не разряженных массивов??


Дата: Янв 17, 2004 18:28:50 · Поправил: Black_mirror

HeDiN
Смысл алгоритма линейной сортироваки в подсчете сколько раз встречается какое значение элемента, после чего идет сканирование всех значений, и запись в исходный массив каждого из них столько раз, сколько оно встретилось в исходном массиве:
lsort(type *a,int n)
{
  int count[type];//в качестве индекса могут
 //использоваться все значения type
  for(type j=type_min;j<=type_max;j++)
    count[i]=0;    
  for(i=0;i<n;i++)
    count[a[i]]++;
  i=0;
  for(j=type_min;j<=type_max;j++)
    while(count[j]--)
      a[i++]=j;
}

Что касается разреженных массивов то здесь Крис наверное имел ввиду следующее:

Разбиваем массив count на несколько частей.
Для кажной части при заполнении будем подсчитывать сумму.
При сканировании если сумма равна нулю, значит данную часть можно не сканировать.

Рекомендую посчитать на сколько это улучшит производительность. 8)


Дата: Янв 17, 2004 20:30:28 · Поправил: volodya

Black_mirror

Криса, как алгоритмизатора я уважаю не слишком...
Слушай, объясни мне тупому:
for(int i=0;i<p;i++)
    count=0;    
  for(i=0;i<p;i++)
    count[a[p]]++;


т.е., в худшем случае это O(n*2)?
Где применяется линейная сортировка? Смысл?

[i]Рекомендую посчитать на сколько это улучшит производительность


И опять я не догоняю :( Если массив разбивать на части - то, так или иначе, через него придется(!) пройти раз - т.е. это уже O(n)... Потом считать сумму - это еще раз.

При сканировании если сумма равна нулю

А это с какой радости?

Хотя, к сожалению, я эту книгу не читал. Чего-то внятного сказать не могу. Вы же оперируете терминами текста :((( Надо будет взять...


Дата: Янв 17, 2004 21:26:13

volodya
Прошу прощения меня малость(или не малость) переглючило. Код исправлен.
Линейной сортировка называется потому, что время ее работы линейно зависит от числа элементов исходного массива.(Время выполнения первого цикла от размера сортируемого массива не зависит.)


Дата: Янв 17, 2004 21:40:57

volodya
count[100];
sum[10];

for(int i=0;i<n;i++)
{
  count[a[i]]++;
  sum[a[i]/10]++; 
}
i=0;
for(j=0;j<100;j+=10)
{
  if(sum[j/10]>0)
  for(int k=j;j<k+10;j++)  
    while(count[k]--)
      a[i++]=k;
}


А книгу эту я тоже не читал.


Дата: Янв 17, 2004 22:28:43

Теперь более-менее понятно. Спасибо большое. Вопрос - область применения? Ведь быстрая сортировка тоже достаточно стабильна!

. 1 . 2 . 3 . >>


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.079