Сортировка Шелла - Assembler
Формулировка задачи:
Мне нужно написать курсовую на тему сортировка Шелла
Я видел на сайте код для неё, но так и не понял как сделать её рабочей.
Есть у меня уже готовый код, с меню, красиво оформлено, только для сортировки Гнома, и никак не могу переделать её на Шелла.
Может кто шарит и поможет переделать? Я так понимаю нужно только GnomeSort поменять на алгоритм Шелла, но я так и не разобрался как
Вот код для Гнома
Листинг программы
- ;---------------------------------------------------------------------
- ; Підпрограма запису цілого числа з клавіатури з перевіркою на знак
- ;---------------------------------------------------------------------
- ; Параматри
- ; ax - введене число
- ;---------------------------------------------------------------------
- InputPInt proc
- ;збереження значень регістрів у стек
- push dx
- push bx
- push cx
- push si
- push di
- push ds
- push cs
- pop ds
- ;при невдалому введенні спробувати знову
- @@again:
- PRINT "==> "
- ;функція вводу символу з клавіатури
- mov ah,0ah
- xor di,di
- mov dx, offset @@buff
- int 21h
- mov dl,0ah
- mov ah,02
- int 21h
- ;обробляємо значення буфера
- ;адрес початку строки
- mov si, offset @@buff+2
- cmp byte ptr [si], "-" ;перевірка першого символу на мінус
- jnz @@ii1
- jmp @@er
- @@ii1:
- xor ax, ax
- mov bx, 10 ;ініціалізація основи системи числення
- @@ii2:
- mov cl,[si] ;беремо символ з буферу
- cmp cl,0dh ;перевіряємо, чи не останній він
- jz @@enddecin
- ;якщо символ не останній, перевіряємо на правильність вводу
- cmp cl,'0'
- jl @@er
- cmp cl,'9'
- ja @@er
- ;перетворюємо символ в 10-ве число
- sub cl,'0'
- mul bx
- add ax,cx
- inc si
- jmp @@ii2
- ;вивід повідомлення про помилку вводу
- @@er:
- PRINTN "Invalid number!Try again."
- jmp @@again
- @@enddecin:
- ;відновлюємо значення регістів
- cmp ax, 0
- je @@er
- pop ds
- pop di
- pop si
- pop cx
- pop bx
- pop dx
- ret
- @@buff db 6,7 Dup(?)
- InputPInt endp
- ;---------------------------------------------------------------------
- ;Підпрограма запису відповіді в файл
- ;---------------------------------------------------------------------
- ;Параматри:
- ; нічого
- ;---------------------------------------------------------------------
- InputToFile proc
- ;Відкриваємо файл
- mov ah,3ch
- xor cx, cx
- lea dx, fn
- int 21h
- ;При помилці відкриття виходимо
- jc @exit
- mov dscr, ax
- mov si, 0 ;ітератор
- mov di, count
- ;ініціалізуємо цикл
- @@again:
- cmp di, 0
- je @exit
- ;вибираємо число з масиву
- xor cx,cx
- mov ax, array[si]
- add si, 2
- ;якщо число відємне, то приводимо його до відповідного типу
- test ax, ax
- jns pos
- neg ax
- push ax
- push bx
- push cx
- push dx
- mov ah, 40h
- mov bx, dscr
- mov cx, 1
- mov dx, offset minus
- int 21h
- pop dx
- pop cx
- pop bx
- pop ax
- ;інакше продовжуємо
- pos:
- ;перетворюємо число
- mov bx, 10
- div10:
- xor dx,dx
- div bx
- push dx
- inc cx
- or ax, 0
- jnz div10
- mov dx, cx
- xor bx, bx
- nxt:
- pop ax
- add ax, 30h
- mov buf[bx], ax
- inc bx
- loop nxt
- ;записуємо переведене число в файл
- mov ah, 40h
- mov bx, dscr
- mov cx, dx
- lea dx, buf
- int 21h
- ;записуємо пробіл
- mov ah, 40h
- mov bx, dscr
- mov cx, 1
- mov dx, offset space
- int 21h
- ;декрементуємо di та при необхідності повторюємо
- dec di
- jmp @@again
- @exit:
- ret
- InputToFile endp
- ;--------------------------------------------------------------------
- ;Підпрограма сортування масиву DWORD алгоритмом "гнома"
- ;-------------------------------------------------------------------
- ;Параматри:
- ; array - покажчик на масиву
- ; count - кількість елементів у масиві
- ;--------------------------------------------------------------------
- GnomeSort proc
- push BP
- mov BP, SP
- push BX
- push SI
- push DI
- ;xor si, si
- mov CX, count ;заносимо в ECX кількість елементів массиву
- xor AX, AX ;обнулюємо АХ, який буде ітератором
- xor si, si
- MainLoop:
- ;Якщо 'i' >= кількості елементів, то виходисо з циклу
- cmp AX, CX
- jge EndLoop
- ;Якщо 'i' == 0, перейти до наступного елементу
- cmp AX, 0
- je IncreaseCounter
- ;Якщо array[i-1] <= array[i], це означає що массив є відсортованим, отже переводимо до наступного елементу
- mov BX, array[SI]
- mov DX, array[SI-2]
- cmp DX, BX
- jle IncreaseCounter
- ;Інакше міняємо місцями array[i-1] з array[i]
- push array[SI]
- push array[SI-2]
- pop array[SI]
- pop array[SI-2]
- ;Переходимо до попереднього елементу в масиві і декрементуємо АХ
- sub SI, 2
- dec AX
- BackToMainLoop:
- jmp MainLoop
- ;Переходимо до наступного елементу в масиві і інкрементуємо АХ
- IncreaseCounter:
- inc AX
- add SI, 2
- jmp BackToMainLoop
- EndLoop:
- ;Відновлюємо регістри
- pop DI
- pop SI
- pop BX
- pop BP
- GnomeSort endp
- ;--------------------------------------------------------------
- ; Підпрограма запису цілого 10-числа з клавіатури
- ;--------------------------------------------------------------
- ; Параматри
- ; ax - введене число
- ;--------------------------------------------------------------
- InputInt proc
- ;збереження значень регістрів у стек
- push dx
- push bx
- push cx
- push si
- push di
- push ds
- push cs
- pop ds
- ;при невдалому введенні спробувати знову
- again:
- PRINT "==>"
- ;функція вводу символу з клавіатури
- mov ah,0ah
- xor di,di
- mov dx, offset buffs
- int 21h
- mov dl,0ah
- mov ah,02
- int 21h
- ;обробляємо значення буфера
- ;адрес початку строки
- mov si, offset buffs+2
- cmp byte ptr [si], "-" ;перевірка першого символу на мінус
- jnz ii1
- mov di,1
- inc si
- ii1:
- xor ax,ax
- mov bx,10 ;ініціалізація основи системи числення
- ii2:
- mov cl,[si] ;беремо символ з буферу
- cmp cl,0dh ;перевіряємо, чи не останній він
- jz enddecin
- ;якщо символ не останній, перевіряємо на правильність вводу
- cmp cl,'0'
- jl er
- cmp cl,'9'
- ja er
- ;перетворюємо символ в 10-ве число
- sub cl,'0'
- mul bx
- add ax,cx
- inc si
- jmp ii2
- ;вивід повідомлення про помилку вводу
- er:
- PRINTN "Invalid number!Try again."
- jmp again
- ;якщо встановлений флаг, то робимо число відємним
- enddecin:
- cmp di,1
- jnz ii3
- neg ax
- ii3:
- ;відновлюємо значення регістів
- pop ds
- pop di
- pop si
- pop cx
- pop bx
- pop dx
- ret
- buffs db 6,7 Dup(?)
- InputInt endp
- ;--------------------------------------------------------------
- ;Підпрограма виводу цілого 10-го числа
- ;--------------------------------------------------------------
- ; Параматри:
- ; ах - чило для виводу
- ;--------------------------------------------------------------
- OutInt proc
- ;Зберігаємо значення регістрів
- push ax
- push dx
- push bx
- push cx
- push ds
- push di
- push cs
- pop ds
- ;Перевіряємо число на знак
- test ax, ax
- jns oi1
- mov di, 1
- neg ax
- oi1:
- xor cx, cx
- mov bx, 10 ;основа СЧ
- oi2:
- xor dx, dx
- div bx
- add dx, '0'
- push dx ;зберігаємо значення в стек
- inc cx
- ;Відділяємо цифру справа поки не залишиться 0
- test ax, ax
- jne oi2
- ;Виводимо отримане значення
- mov ah, 2
- cmp di, 1
- jne oi3
- ;При відємному числі виводимо знак '-'
- mov dl, '-'
- int 21h
- oi3:
- pop dx ;Виштовхеємо цифру, переводимо її в символ і виводимо
- int 21h
- loop oi3 ;повторюємо стільки разів, скільки цифр було нараховано
- ;Відновлюємо значення регістрів
- pop di
- pop ds
- pop cx
- pop bx
- pop dx
- pop ax
- ret
- OutInt endp
- ;-------------------------------------------------------------
- ; Підпрограма заповнення массива з клавіатури
- ;-------------------------------------------------------------
- ; Параматри:
- ; сх - кількість елементів у масиві
- ;-------------------------------------------------------------
- GetArray proc
- mov cx, count ;довжина массива
- mov bx, 0 ;ітератор
- @@1:
- call InputInt
- mov array[bx], ax
- add bx, 2
- loop @@1
- ret
- GetArray endp
- ;------------------------------------------------------------
- ; Підпрограма виводу масиву на консоль
- ;------------------------------------------------------------
- ; Параматри
- ; сх - довжина массива
- ;------------------------------------------------------------
- OutArray proc
- cmp count, 0
- je @@Exit
- mov cx, count ;довжина массива
- mov bx, 0
- mov dl, ' '
- @@2:
- mov ax, array[bx]
- call OutInt
- mov ah, 2
- int 21h
- add bx, 2
- loop @@2
- @@Exit:
- ret
- OutArray endp
- ;-----------------------------------------------------------------
- ;Процедура відкриття файлу
- ;-----------------------------------------------------------------
- ;Параматри
- ; немає
- ;-----------------------------------------------------------------
- OpenFileRead PROC
- mov ah,3dh
- mov al,0
- int 21h
- ret
- OpenFileRead ENDP
- ;-------------------------------------------------------------
- ;Процедура закриття файлу
- ;------------------------------------------------------------
- ;Параматри:
- ; BX декриптор файла
- ;-------------------------------------------------------------
- CloseFile PROC
- mov ah,3eh
- int 21h
- ret
- CloseFile ENDP
- ;------------------------------------------------------------------
- ;Процедура виходу з проограми
- ;------------------------------------------------------------------
- ;Параматри:
- ; немає
- ;----------------------------------------------------
- ExitProgramm PROC
- mov ah,0
- mov al,2
- int 10h
- mov ah,04Ch
- mov al,0h
- int 21h
- ExitProgramm ENDP
- ;------------------------------------------------------------------------
- ;Процедура вивиду рядку символів на екран
- ;------------------------------------------------------------------------
- ;Параматри:
- ; bx - символ для виводу
- ;------------------------------------------------------------------------
- WriteStr PROC
- mov ah,09h
- int 21h
- ret
- WriteStr ENDP
- ;-----------------------------------------------------------------------
- ;функція читання з файлу
- ;----------------------------------------------------------------------
- ReadFromFile proc
- ;Відкриваємо файл
- mov dx, offset fname
- call OpenFileRead
- mov handle, ax
- mov buff, 0
- mov position, 0
- xor si, si
- xor di, di
- @@again:
- ;--------------------------------------------------------------------
- ;Покажчик на потрібну позицію
- mov bx, handle
- mov al, 0
- mov cx, 0
- mov dx, position
- mov ah, 42h
- int 21h
- inc position ;Зміщуємо позицію
- ;Читаємо з файлу
- mov bx, handle
- mov ah, 3fh
- mov cx, 1 ;Зчитуємо по 1 байту
- mov dx, offset t_buff
- int 21h
- ;Перевіряємо на кінець файлу
- cmp t_buff, '$'
- je Exit
- ;Перевіряємо на відємне число
- cmp t_buff, '-'
- jne @@postv
- mov di, 1
- jmp @@again
- @@postv:
- ;Перевіряємо на пробіл
- cmp t_buff, ' '
- jne @@cont
- ;Якщо пробіл, записуємо значення в масив
- cmp position, 3
- jne @@ncount
- push buff
- pop count
- mov buff, 0
- jmp @@again
- @@ncount:
- cmp di,1
- jne @@pos
- mov bx, buff
- neg bx
- mov buff, bx
- @@pos:
- mov bx, buff
- mov array[si], bx
- add si, 2 ;Зміщуємо позицію
- mov buff, 0
- xor di, di
- jmp @@again
- @@cont:
- xor ch, ch
- mov cl, t_buff
- ;перевіряємо на правильність вводу
- cmp cl,'0'
- jl Exit
- cmp cl,'9'
- ja Exit
- ;початкові установки
- mov bx, 10 ;ініціалізація основи системи числення
- ;перетворюємо символ в 10-ве число
- sub cl,'0'
- xor ch, ch
- mov ax, buff
- mul bx
- add ax, cx
- mov buff, ax
- jmp @@again
- Exit:
- mov bx, handle
- Call CloseFile
- jc Exit
- ret
- ReadFromFile endp
Решение задачи: «Сортировка Шелла»
textual
Листинг программы
- // BaseType - любой перечисляемый тип
- // typedef int BaseType - пример
- void ShellsSort(BaseType *A, unsigned N)
- {
- unsigned i,j,k;
- BaseType t;
- for(k = N/2; k > 0; k /=2)
- for(i = k; i < N; i++)
- {
- t = A[i];
- for(j = i; j>=k; j-=k)
- {
- if(t < A[j-k])
- A[j] = A[j-k];
- else
- break;
- }
- A[j] = t;
- }
- }
Объяснение кода листинга программы
- Входные данные:
- A - указатель на массив, который необходимо отсортировать
- N - количество элементов в массиве A
- Создаются три переменные:
- i - счётчик, который будет использоваться в двух вложенных циклах
- j - счётчик, который будет использоваться во внутреннем цикле
- k - делитель, который будет применяться к N во внутреннем цикле
- Запускается внешний цикл, который будет выполняться до тех пор, пока k не станет равным 1:
- Текущее значение k вычитается из i во внутреннем цикле
- Во внутреннем цикле происходит перебор элементов массива A, начиная с элемента с индексом j-k
- Если текущий элемент A[j-k] больше t, то A[j] присваивается значение A[j-k]
- Если текущий элемент A[j-k] меньше или равен t, то цикл прерывается
- После выхода из внутреннего цикла, A[j] присваивается значение t
- По завершении внешнего цикла, массив A будет отсортирован в порядке возрастания.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д