| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Общие вопросы > Работа со StringGrid'ом и не только |
| Автор: MacTep 16.6.2004, 08:58 |
| Помогите, кто может! У меня есть несколько вопросов: 1) На форме есть компонент StringGrid. Его свойство Options.goRowCount установлено в True. Как мне узнать в любой момент времени, сколько именно и какие строки выделены? Вообще, есть ли какое-нибудь свойство у StringGrid'а, которое отвечает за выделение ячеек или целых строк? 2) Еще вопрос по StringGrid'у. Как сделать так, чтобы вывести на печать содержимое StringGrid'a в виде таблицы? 3) Как вывести на печать содержимое формы без заголовка, т.е. только то, что лежит внутри окна формы? 4) Вопрос не в тему, но все-таки вопрос: какая из сортировок массивов эффективнее всего сортирует массивы длинной где-то 500-1500 элементов. Очень надо сортировать, но простыми сортировками получается очень медленно! Заранее всем спасибо! Буду рад, если получу исчерпывающие ответы на свои вопросы! |
| Автор: Serggggg 16.6.2004, 09:56 |
| (2). Я так решаю проблему с DBGrid'ом - Через EXCEL! Поднять ядро Excel, создать/открыть документ (готовый шаблон ведомости, например). А потом 2 цикла - по кол-ву строк и по кол-ву столбцов - выводят в нужные ячейки ячейки Grid'а - Excel.Cells.Item[i,j].Value:=... |
| Автор: Serggggg 16.6.2004, 10:07 | ||||||
(4). В принципе, нас ещё со времен 1-го курса учили сортировать так (по-крайней мере, преподы утверждали, что это лучший способ):
Т.е. признак того, была ли произведена в ходе проверки хотя бы одна перестановка элементов (в данном примере - j). Когда в последний раз массив будет просмотрен и будет обнаружено, что он упорядочен, то j будет равняться 0 - задача решена. Добавлено @ 10:11 Прошу прощения - в строке
слово BEGIN нужно убрать или перед строкой
вставить ещё 1 end; |
| Автор: Pakshin A. S. 16.6.2004, 10:23 |
| Уважайте правила форума!!! Один топик - один вопрос! №3: Это как? |
| Автор: MacTep 16.6.2004, 17:30 |
| 1) Помогите именно со StringGrid'ом, так как проблема именно в нем. Не надо сюда Excel приплетать. 2) За правила форума простите, я обязательно исправлюсь! 3) Про печать StringGrid'а обязательно подскажите, я же знаю, что здесь полно умных людей. 4) Сортировку "пузырьком" (а именно такая и была предложена) не предлагать. Это все лажа. Есть более эффективные сортировки. Ок? По поводу третьего вопроса: есть форма. Там кнопки, все такое прочее. Так вот как это все такое прочее и кнопки вывести, но только так, чтобы не было видно, что вывелось целое окно? Доходчиво? |
| Автор: Serggggg 16.6.2004, 17:40 |
| Пожалуйста. Ищи более эффективные методы. Только грубить не надо - я всего лишь предложил свой вариант. Я же не ручался за то, что это самое рациональное решение. |
| Автор: Albinos_x 16.6.2004, 18:42 |
| По сортировке: // сортировка массива целых чисел с вабором минимального элемента procedure MinSortInt( var M : array of integer ); var i, j, n, Imin, Rtmp: integer; begin N:=High(M); for i:=0 to N-1 do begin Imin:=N; for j:=n-1 downto i do if (M[j] <= M[Imin]) then Imin:=j; if (i<Imin) then begin // Перестановка элементов Rtmp:=M[Imin]; M[Imin]:=M[i]; M[i]:=Rtmp; end; end; end; Немного усовершенствованная пузырьковая сортировка. Совершенствование заключается в том, что в пузырьковой сортировке количество сравнений n*(n-1)/2 количество перестановок n*(n-1)/2 в предложенной количество сравнений n*(n-1)/2 количество перестановок n-1 недостаток метода: Если массив отсортирован, то все равно будут сделаны все сравнения, а метод пузырьковой сорировки ограничится n-1 сравнением |
| Автор: MacTep 17.6.2004, 14:19 |
| Парни, никто не кому не грубил!!! А про быструю сортировку никто не слышал что ли? Про StringGrid подскажитете, как там с выделением быть! Очень надо. И как содержимое StringGrid'а распечатать? Это самое главное!!! |
| Автор: x77 18.6.2004, 04:37 |
| MacTep, руками его печатать, как ещё... через TPrinter.Canvas. говоришь ему BeginDoc, рисуешь в цикле построчно, говоришь EndDoc. |
| Автор: Albinos_x 18.6.2004, 07:04 |
| активную ячейку можно получить: StringGrid1.Selection.Left - столбец StringGrid1.Selection.Top - строка |
| Автор: x77 18.6.2004, 07:31 |
| ... а всё выделение, соответственно, через Selection.Right / Selection.Bottom |
| Автор: Albinos_x 18.6.2004, 07:43 | ||
совершенно точно, забыл что нужно получить несколько выделенных ячеек, поэтому не указал |
| Автор: MacTep 18.6.2004, 23:02 |
| x77, можно поподробнее с Canvas. Я с этим делом мало работал (почти не работал совсем), поэтому плохо пока в этом разбираюсь. Можно что-то типа исходного текста. Про Selection тоже чуть подробнее. Ведь это всего лишь свойство, а как посмотреть, выставлено оно или нет? Про форму: если я напишу Form1.Print, то что я получу на бумаге? Ответьте, пожалуйста. |
| Автор: U 19.6.2004, 10:21 | ||
|
| Автор: MacTep 19.6.2004, 13:48 |
| Благодарю автора предыдущего сообщения. А никто так и не ответил на вопрос: что будет если вызвать такую команду Form1.Print? |
| Автор: _hunter 19.6.2004, 16:17 | ||
справка ответит
|
| Автор: MacTep 19.6.2004, 23:14 |
| Так, в тексте я понял только перво предложение! Переведите второе, плиз! |
| Автор: Medved 21.6.2004, 08:09 | ||
Хм... а самому попробовать сложно? |
| Автор: MacTep 23.6.2004, 23:50 |
| Дело в том, что принтера дома нет! Вот и мучаюсь! А сделать надо так, чтобы работало именно на принтере реальном! |
| Автор: Albinos_x 24.6.2004, 01:56 | ||
на принтер выведится изображение формы |
| Автор: MacTep 24.6.2004, 14:13 |
| Благодарю всех, кто принимал участие в обсуждении этой темы |
| Автор: _hunter 24.6.2004, 19:24 |
| а насчет принтера -- есть такая программа Адоб Дистилятор -- можеш на ней практиковаться |
| Автор: MacTep 28.6.2004, 07:15 |
| _hunter, где такую прогу, как Адоб Дистилятор можно найти. Подскажи, хотябы ссылочку, ок? |
| Автор: Akella 30.6.2004, 08:50 |
| Adobe Acrobat 4.0 - версия для редактирования создает в "принтерах" такую фиговину. Новерсия для редактирование не бесплатна и инсталяха занимает почти 100 метров |
| Автор: Akella 30.6.2004, 14:26 |
| 2)вариантов может быть много отправляй все в Excel или печать через файл или печать через TMemo или Canvas.TextOut, затем затем печатаешь последние три способа нужно использовать со знаком табуляции(можно с двумя), т.е. ячейка1+#9+ячейка2 и т.д., для того, чтобы все столбцы были ровными 111 222 333 444 555 666 777 1111 22 333 4444 5 666 77777 ну ты понял ///////////////////////////////////////////////////// 3) я таким еще не занимался, может показаться сложно, но всё таки... нажимаешь програмно Alt+PrintScreen (т.е. копируешь в буфер обмена) потом из буфера в Bitmap берёш ClientWidth и ClientHeight формы отмеряешь от правого нижнего края примоугольник и копируешь этот прямоуголник в основной Bitmap ///////////////////////////////////////////////////////// 4)здесь информации побольше Алгоритмы сортировки Previous Top Next Алгоритм 1. Сортировка вставками. Это изящный и простой для понимания метод. Вот в чем его суть: создается новый ма ссив, в который мы последовательно вставляем элементы из исходного массива так, чтобы новый массив был упорядоченным. Вставка происходит следующим образом: в конце нового массива выделяется свободная ячейка, далее анализируется элемент, стоящий перед пустой ячейкой (если, конечно, пустая ячейка не стоит на первом месте), и если этот элемент больше вставляемого, то подвигаем элемент в свободную ячейку (при этом на том месте, где он стоял, образуется пустая ячейка) и сравниваем следующий элемент. Так мы прейдем к ситуации, когда элемент перед пустой ячейкой меньше вставляемого, или пустая ячейка стоит в начале массива. Помещаем вставляемый элемент в пустую ячейку . Таким образом, по очереди вставляем все элементы исходного массива. Очевидно, что если до вставки элемента массив был упорядочен, то после вставки перед вставленным элементом расположены все элементы, меньшие его, а после — большие. Так как порядок элементов в новом массиве не меняется, то сформированный массив будет упорядоченным после каждой вставки. А значит, после последней вставки мы получим упорядоченный исходный массив. Вот как такой алгоритм можно реализовать на языке программирования Pascal: Program InsertionSort; Var A,B : array[1..1000] of integer; N,i,j : integer; Begin {Определение размера массива A (N) и его заполнение} … {сортировка данных} for i:=1 to N do begin j:=i; while (j>1) and (B[j-1]>A[i]) do begin B[j]:=B[j-1]; j:=j-1; end; B[j]:=A[i]; end; {Вывод массива B} … End. В принципе, данную сортировку можно реализовать и без дополнительного массива B, если сортировать массив A сразу при считывании, т. е. осуществлять вставку нового элемента в массив A. Алгоритм 2. Пузырьковая сортировка. Реализация данного метода не требует дополнительной памяти. Метод очень прост и состоит в следующем: берется пара рядом стоящих элементов, и если элемент с меньшим индексом оказывается больше элемента с большим индексом, то мы меняем их местами. Эти действия продолжаем, пока есть такие пары. Легко понять, что когда таких пар не останется, то данные будут отсортированными. Для упрощения поиска таких пар данные просматриваются по порядку от начала до конца. Из этого следует, что за такой просмотр находится максимум, который помещается в конец массива, а потому следующий раз достаточно просматривать уже меньшее количество элементов. Максимальный элемент как бы всплывает вверх, отсюда и название алгоритма Так как каждый раз на свое место становится по крайней мере один элемент, то не потребуется более N проходов, где N — количество элементов. Вот как это можно реализовать: Program BubbleSort; Var A : array[1..1000] of integer; N,i,j,p : integer; Begin {Определение размера массива A (N) и его заполнение} … {сортировка данных} for i:=1 to n do for j:=1 to n-i do if A[j]>A[j+1] then begin {Обмен элементов} p:=A[j]; A[j]:=A[j+1]; A[j+1]:=P; end; {Вывод отсортированного массива A} … End. Алгоритм 3. Сортировка Шейкером. Когда данные сортируются не в оперативной памяти, а на жестком диске, особенно если ключ связан с большим объемом дополнительной информации, то количество перемещений элементов существенно влияет на время работы. Этот алгоритм уменьшает количество таких перемещений, действуя следующим образом: за один проход из всех элементов выбирается минимальный и максимальный. Потом минимальный элемент помещается в начало массива, а максимальный, соответственно, в конец. Далее алгоритм выполняется для остальных данных. Таким образом, за каждый проход два элемента помещаются на свои места, а значит, понадобится N/2 проходов, где N — количество элементов. Реализация данного алгоритма выглядит так: Program ShakerSort; Var A : array[1..1000] of integer; N,i,j,p : integer; Min, Max : integer; Begin {Определение размера массива A — N) и его заполнение} … {сортировка данных} for i:=1 to n div 2 do begin if A[i]>A[i+1] then begin Min:=i+1; Max:=i; end else begin Min:=i; Max:=i+1; end; for j:=i+2 to n-i+1 do if A[j]>A[Max] then Max:=j else if A[j]<A[Min] then Min:=j; {Обмен элементов} P:=A[i]; A[i]:=A[min]; A[min]:=P; if max=i then max:=min; P:=A[N-i+1]; A[N-i+1]:=A[max]; A[max]:=P; end; {Вывод отсортированного массива A} … End. Рассмотрев эти методы, сделаем определенные выводы. Их объединяет не только то, что они сортируют данные, но также и время их работы. В каждом из алгоритмов присутствуют вложенные циклы, время выполнения которых зависит от размера входных данных. Значит, общее время выполнения программ есть O(n2) (константа, умноженная на n2). Следует отметить, что первые два алгоритма используют также O(n2) перестановок, в то время как третий использует их O(n). Отсюда следует, что метод Шейкера является более выгодным для сортировки данных на внешних носителях информации. Если вы думаете, что бравые «алгоритмщики» остановились на достигнутом, то вы ошибаетесь. Видите ли, временная оценка O(n2) показалась им слишком громоздкой, и они, жадины такие, решили еще потратить свое время, чтобы впоследствии сэкономить наше. Итак, давайте теперь рассмотрим более быстрые алгоритмы. Алгоритм 4. Сортировка слиянием. Эта сортировка использует следующую подзадачу: есть два отсортированных массива, нужно сделать (слить) из них один отсортированный. Алгоритм сортировки работает по такому принципу: разбить массив на две части, отсортировать каждую из них, а потом слить обе части в одну отсортированную. Корректность данного метода практически очевидна, поэтому перейдем к реализации. Program SlivSort; Var A,B : array[1..1000] of integer; N : integer; Procedure Sliv(p,q : integer); {процедура сливающая массивы} Var r,i,j,k : integer; Begin r:=(p+q) div 2; i:=p; j:=r+1; for k:=p to q do if (i<=r) and ((j>q) or (a[i]<a[j])) then begin b[k]:=a[i]; i:=i+1; end else begin b[k]:=a[j]; j:=j+1; end ; for k:=p to q do a[k]:=b[k]; End; Procedure Sort(p,q : integer); {p,q — индексы начала и конца сортируемой части массива} Begin if p<q then {массив из одного элемента тривиально упорядочен} begin Sort(p,(p+q) div 2); Sort((p+q) div 2 + 1,q); Sliv(p,q); end; End; Begin {Определение размера массива A — N) и его заполнение} … {запуск сортирующей процедуры} Sort(1,N); {Вывод отсортированного массива A} … End. Чтобы оценить время работы этого алгоритма, составим рекуррентное соотношение. Пускай T(n) — время сортировки массива длины n, тогда для сортировки слиянием справедливо T(n)=2T(n/2)+O(n) (O(n) — это время, необходимое на то, чтобы слить два массива). Распишем это соотношение: T(n)=2T(n/2)+O(n)=4T(n/4)+2O(n/2)+O(n)=4T(n/4)+2O(n)= … = 2kT(1)+kO(n) Осталось оценить k. Мы знаем, что 2k=n, а значит k=log2n. Уравнение примет вид T(n)=nT(1)+ log2nO(n). Так как T(1) — константа, то T(n)=O(n)+log2nO(n)=O(nlog2n). То есть, оценка времени работы сортировки слиянием меньше, чем у первых трех алгоритмов (я прошу прощения у тех, кто не понял мои рассуждения или не согласен с ними, — просто поверьте мне на слово). Перед тем как объяснить, чем этот метод лучше, рассмотрим еще один алгоритм. Алгоритм 5. Сортировка двоичной кучей Проблема первых трех алгоритмов, описанных в прошлой части статьи, состояла в том, что после того как элемент занимал свое место, информация об уже произведенных сравнениях никак не использовалась. Структура двоичного дерева позволяет сохранить эту информацию. Итак, представим массив в виде дерева (Рис. 1). Корень дерева — элемент с индексом 1; элемент с индексом i является «родителем» для элементов с индексами 2*i и 2*i+1, а те, в свою очередь, являются его «детьми». Каждый элемент кроме первого имеет «родителя» и может иметь до двух «детей» — речь ведь идет именно о ДВОИЧНОМ дереве. Очевидно, что корнем дерева является наименьший элемент, а наибольший не имеет детей. Тут возникают два вопроса: как нам такую кучу наплодить? И зачем нам это вообще нужно? Пренебрегая порядком, отвечу сразу на второй вопрос: мы хотим извлечь из кучи минимальный элемент, а потом как-то преобразовать и восстановить кучу. Таким образом, по очереди извлечь все элементы и получить отсортированный массив. И вот как мы собираемся это сделать: пусть поддеревья с корнями 2*i и 2*i+1 уже имеют свойство кучи, мы же хотим, чтобы такое свойство имело и поддерево с корнем i. Для этого, если корень больше наименьшего своего «ребенка», мы меняем корень дерева (элемент с индексом i) с этим «ребенком», после повторяем алгоритм для поддерева, куда перешел бывший корень. Выполняя этот алгоритм «снизу вверх» (сначала для маленьких поддеревьев, потом для больших), мы добьемся того, что свойство кучи будет выполняться для всего дерева. Извлечение элемента происходит очень простым способом: мы ставим последний элемент на первое место и запускаем алгоритм исправления кучи от корня дерева… Я тут много наговорил, но на самом деле, реализация совсем несложная: Program HeapSort; Var A,B : array[1..1000] of integer; N,i,P : integer; Procedure Heapi(ind : integer); {процедура, формирующая и исправляющяя кучу} Var k : integer; Begin k:=ind*2; If k<=N then begin if (k+1<=N) and (A[k]>A[k+1]) then k:=k+1; if A[ind]>A[k] then begin P:=A[ind]; A[ind]:=A[k]; A[k]:=P; Heapi(k); end; end; End; Begin {Определение размера массива A — N) и его заполнение} … {формирование кучи} for i:=N div 2 downto 1 do Heapi(i); {формирование массива B} for i:=1 to N do begin B[i]:=A[1]; A[1]:=A[N]; N:=N-1; Heapi(1); end; {Вывод отсортированного массива B} … End. А теперь главное, т. е. оценка сложности. Время работы процедуры исправляющей кучу зависит от высоты дерева. Высота всего дерева равна log2n, значит, время работы процедуры есть O(log2n). Программа состоит из двух частей: формирование кучи и создание отсортированного массива B. Время исполнения каждой из частей не больше O(n log2n) (в каждой части исправляющая процедура вызывается не более n раз). Значит, время работы то же, что и в сортировке слиянием. Теперь лирическое отступление насчет времени работы. Может, читатель думает, что быстрые алгоритмы сложны в исполнении и проще написать что-то вроде сортировки вставками. Что ж, рассмотрим простой пример: допустим, вы написали сортировку вставками, тщательно, с помощью ассемблера, и время работы получилось 2n2, а какой-нибудь раздолбай написал сортировку слиянием со временем работы 50nlog2n. И тут появилась необходимость отсортировать 1000000 элементов (что в наше время не редкость). Вы использовали крутой компьютер, который делает 108 операций сравнения и перестановки в секунду, а у него компьютер похуже — всего 106 операций в секунду. И вы будете ждать 2*(106)2/108 = 20 000 секунд (приблизительно 5.56 часов), а ваш конкурент — 50*(106)*log2(106)/106 = 1000 секунд (приблизительно 17 минут). Надеюсь, вы проведете это время (5 часов) с пользой для себя и поймете, что хороший алгоритм — быстрый алгоритм :-). Хотя, если вы будете сортировать маленький массив или много маленьких массивов, то 2n2 для вас будет лучше, чем 50nlog2n. Эту закономерность использует один из способов оптимизации сортировки слиянием: сортировать маленькие части массива вставками. Теперь переходим к самому интересному, а именно к одной из самых быстрых и эффективных из известных сортировок, которая так и называется — «быстрая сортировка». Алгоритм 6. Быстрая сортировка. Как и в сортировке слиянием, массив разбивается на две части, с условием, что все элементы первой части меньше любого элемента второй. Потом каждая часть сортируется отдельно. Разбиение на части достигается упорядочиванием относительно некоторого элемента массива, т. е. в первой части все числа меньше либо равны этому элементу, а во второй, соответственно, больше либо равны. Два индекса проходят по массиву с разных сторон и ищут элементы, которые попали не в свою группу. Найдя такие элементы, их меняют местами. Тот элемент, на котором индексы пересекутся, и определяет разбиение на группы. Классическая реализация алгоритма выглядит так: Program QuickSort; Var A : array[1..1000] of integer; N,T : integer; Procedure Sort(p,q : integer); {p,q — индексы начала и конца сортируемой части массива} Var i,j,r : integer; Begin if p<q then {массив из одного элемента тривиально упорядочен} begin r:=A[p]; i:=p-1; j:=q+1; while i<j do begin repeat i:=i+1; until A[i]>=r; repeat j:=j-1; until A[j]<=r; if i<j then begin T:=A[i]; A[i]:=A[j]; A[j]:=T; end; end; Sort(p,j); Sort(j+1,q); end; End; Begin {Определение размера массива A — N) и его заполнение} … {запуск сортирующей процедуры} Sort(1,N); {Вывод отсортированного массива A} … End. Что же делает данный алгоритм таким быстрым? Ну во-первых, если массив каждый раз будет делится на приблизительно равные части, то для него будет верно то же соотношение, что и для сортировки слиянием, т. е. время работы будет O(nlog2n). Это уже само по себе хорошо. Кроме того, константа при nlog2n очень мала, ввиду простоты внутреннего цикла программы. В комплексе это обеспечивает огромную скорость работы. Но как всегда есть одно «но». Вы, наверное, уже задумались: а что если массив не будет делится на равные части? Классическим примером является попытка «быстро» отсортировать уже отсортированный массив. При этом данные каждый раз будут делиться в пропорции 1 к n-1, и так n раз. Общее время работы при этом будет O(n2), тогда как вставкам, для того чтобы «понять», что массив уже отсортирован, требуется всего-навсего O(n). А на кой нам сортировка, которая одно сортирует хорошо, а другое плохо? А собственно, что она сортирует хорошо? Оказывается, что лучше всего она сортирует случайные массивы (порядок элементов в массиве случаен). И поэтому нам предлагают ввести в алгоритм долю случайности. А точнее, вставить randomize и вместо r:=A[p]; написать r:=A[random(q-p)+p]; т. е. теперь мы разбиваем данные не относительно конкретного, а относительно случайного элемента. Благодаря этому алгоритм получает приставку к имени «вероятностный». Особо недоверчивым предлагаю на своем опыте убедится, что данная модификация быстрой сортировки сортирует любые массивы столь же быстро. А теперь еще один интересный факт: время O(nlog2n) является минимальным для сортировок, которые используют только попарное сравнение элементов и не использует структуру самих элементов. Тем, кому интересно, откуда это взялось, рекомендую поискать в литературе, доказательство я здесь приводить не намерен, не Дональд Кнут, в конце концов :-). Но вы обратили внимание, что для рассмотренных алгоритмов в принципе не важно, что сортировать — такими методами можно сортировать хоть числа, хоть строки, хоть какие-то абстрактные объекты. Следующие сортировки могут сортировать только определенные типы данных, но за счет этого они имеют рекордную временную оценку O(n). Алгоритм 7. Сортировка подсчетом. Этот метод подходит для сортировки целых чисел из не очень большого диапазона (сравнимого с размером массива). Идея вот в чем: для каждого элемента найти, сколько элементов, меньших определенного числа, и поместить это число на соответствующие место. Делается это так: за линейный проход по массиву мы для каждого из возможных значений подсчитываем, сколько элементов имеют такое значение. Потом добавляем к каждому из найденных чисел суму всех предыдущих. Получая, таким образом, сколько есть элементов, значения которых не больше данного значения. Далее, опять-таки за линейный проход, формируем из исходного массива новый отсортированный. При этом следим, чтобы два одинаковых элемента не были записаны в одно место. Если все равно непонятно, смотрите реализацию: Program CountingSort; Var A,B : array[1..1000] of byte; C : array[byte] of integer; N,i : integer; Begin {Определение размера массива A (N) и его заполнение} … {сортировка данных} for i:=0 to 255 do C[i]:=0; for i:=1 to N do C[A[i]]:=C[A[i]]+1; for i:=1 to 255 do C[i]:=C[i-1]+C[i]; for i:=N downto 1 do begin B[C[A[i]]]:=A[i]; C[A[i]]:=C[A[i]]-1; {здесь мы избегаем возможности записи двух одинаковых чисел в одну ячейку} end; {Вывод массива B} … End. Этот простой метод не использует вложенных циклов и, учитывая небольшой диапазон значений, время его работы есть O(n). Рассмотрев такое количество сортировок, можно задуматься: а будет ли результат их работы одинаковым? Странный вопрос, ведь все сортировки правильно сортируют данные, так почему же результат работы может быть разным? Хорошо, объясню: меньшие элементы всегда расположены перед большими, но порядок одинаковых элементов может быть нарушен. Если мы сортируем данные, которые состоят из одного ключа, то мы, конечно, не заметим разницы. Но если к ключу прилагается дополнительная информация, то одна сортировка может вернуть нам 1977 "Иванов" и 1977 "Сидоров", а другая — 1977 "Сидоров" и 1977 "Иванов". Значит, порядок одинаковых элементов может в процессе сортировки стать другим. Правда, это бывает далеко не всегда и не в каждой сортировке. В сортировках вставками, пузырьком, подсчетом и слиянием порядок элементов с одинаковыми ключами всегда такой же, как и в изначальном массиве. Такие сортировки называются устойчивыми, и сейчас я познакомлю вас с улучшенной сортировкой подсчетом, которая позволяет сортировать числа большего диапазона, используя другую устойчивую сортировку. Алгоритм 8. Цифровая сортировка. Этой сортировкой можно сортировать целые неотрицательные числа большого диапазона. Идея состоит в следующем: отсортировать числа по младшему разряду, потом устойчивой сортировкой сортируем по второму, третьему, и так до старшего разряда. В качестве устойчивой сортировки можно выбрать сортировку подсчетом, в виду малого времени работы. Реализация такова: Program RadixSort; Var A,B : array[1..1000] of word; N,i : integer; t : longint; Procedure Sort; {сортировка подсчетом} Var C : array[0..9] of integer; j : integer; Begin For j:=0 to 9 do C[j]:=0; For j:=1 to N do C[(A[j] mod (t*10)) div t]:= C[(A[j] mod (t*10)) div t]+1; For j:=1 to 9 do C[j]:=C[j-1]+C[j]; For j:=N downto 1 do begin B[C[(A[j] mod (t*10)) div t]]:=A[j]; C[(A[j] mod (t*10)) div t] := C[(A[j] mod (t*10)) div t]-1; end; End; Begin {Определение размера массива A (N) и его заполнение} … {сортировка данных} t:=1; for i:=1 to 5 do begin Sort; A:=B; t:= t*10; end; {Вывод массива A} … End. Так как сортировка подсчетом вызывается константное число раз, то время работы всей сортировки есть O(n). Заметим, что таким способом можно сортировать не только числа, но и строки, если же использовать сортировку слиянием в качестве устойчивой, то можно сортировать объекты по нескольким полям. Теперь вы владеете достаточным арсеналом, чтобы сортировать все что угодно и как угодно. Помните, что выбор нужной вам сортировки зависит от того, какие данные вы будете сортировать и где вы их будете сортировать. P.S. Все программы рабочие — если, конечно, вам не лень будет заменить три точки на код ввода и вывода массивов :-). /////////////////////////////////////////////////////////////////////////////////// Сортировка столбцов в StringGrid Previous Top Next Procedure GridSort(StrGrid: TStringGrid; NoColumn: Integer); Var Line, PosActual: Integer; Row: TStrings; begin Renglon := TStringList.Create; For Line := 1 to StrGrid.RowCount-1 do Begin PosActual := Line; Row.Assign(TStringlist(StrGrid.Rows[PosActual])); While True do Begin If (PosActual = 0) Or (StrToInt(Row.Strings[NoColumn-1]) >= StrToInt(StrGrid.Cells[NoColumn-1,PosActual-1])) then Break; StrGrid.Rows[PosActual] := StrGrid.Rows[PosActual-1]; Dec(PosActual); End; If StrToInt(Row.Strings[NoColumn-1]) < StrToInt(StrGrid.Cells[NoColumn-1,PosActual]) then StrGrid.Rows[PosActual] := Row; End; Renglon.Free; end; -------------------------------------------------------------------------------- type TStringGridExSortType = (srtAlpha,srtInteger,srtDouble); procedure GridSort(SG : TStringGrid; ByColNumber,FromRow,ToRow : integer; SortType : TStringGridExSortType = srtAlpha); var Temp : TStringList; function SortStr(Line : string) : string; var RetVar : string; begin case SortType of srtAlpha : Retvar := Line; srtInteger : Retvar := FormatFloat('000000000',StrToIntDef(trim(Line),0)); srtDouble : try Retvar := FormatFloat('000000000.000000',StrToFloat(trim(Line))); except RetVar := '0.00'; end; end; Result := RetVar; end; // Рекурсивный QuickSort procedure QuickSort(Lo,Hi : integer; CC : TStrings); procedure Sort(l,r: integer); var i,j : integer; x : string; begin i := l; j := r; x := SortStr(CC[(l+r) DIV 2]); repeat while SortStr(CC[i]) < x do inc(i); while x < SortStr(CC[j]) do dec(j); if i <= j then begin Temp.Assign(SG.Rows[j]); // Меняем местами 2 строки SG.Rows[j].Assign(SG.Rows[i]); SG.Rows[i].Assign(Temp); inc(i); dec(j); end; until i > j; if l < j then sort(l,j); if i < r then sort(i,r); end; begin {quicksort}; Sort(Lo,Hi); end; begin Temp := TStringList.Create; QuickSort(FromRow,ToRow,SG.Cols[ByColNumber]); Temp.Free; end; для 4-го вопроса инфа из DRKB |
| Автор: Akella 30.6.2004, 14:39 |
| 3) почитай эту тему http://forum.vingrad.ru/index.php?showtopic=25097 |
| Автор: MacTep 3.7.2004, 22:37 |
| У меня нет слов о человеке под ником dsergey. Это просто монстр в хорошем смысле этого слова! Благодарю за столь распространненный ответ! А можно задать вопрос не по теме? Откуда вы столько знаете? А точнее, откуда столько подробной инфы? |