Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.12.31;
Скачать: CL | DM;

Вниз

TList.Sort и переполнение стека   Найти похожие ветки 

 
said46   (2006-12-11 14:26) [0]

Есть объект TList, содержащий указатели на record"ы. Пытаюсь отсортировать.

type
 PTRec = ^TRec;
 TRec = record
...
end;

...
// функция обратного вызова для сортировки
function CompareTRec(Item1, Item2: Pointer): Integer;
begin
 Result := CompareDateTime(PTRec(Item1).RT, PTRec(Item2).RT);
end;

Все работает, однако при сортировке зачем то переставляются местами одинаковые элементы списка.
Изменяю функцию так:

function CompareTRec(Item1, Item2: Pointer): Integer;
var
 res: Integer;
begin
 res := CompareDateTime(PTRec(Item1).RT, PTRec(Item2).RT);
 if res = 0 then res := -1;
 Result := res;
end;

Получаю переполнение стека. Почему?


 
clickmaker ©   (2006-12-11 14:28) [1]


> переставляются местами одинаковые элементы списка

может, они не совсем одинаковые?


 
said46   (2006-12-11 14:33) [2]

Вроде одинаковые... Но это не суть, меня больше интересует причина переполнения стека.


 
clickmaker ©   (2006-12-11 14:37) [3]


> причина переполнения стека

см. реализацию QuickSort в classes.pas
влетаешь в рекурсию


 
MBo ©   (2006-12-11 14:37) [4]

>при сортировке зачем то переставляются местами одинаковые элементы списка

TList использует QuickSort, а эта сортировка неустойчива(т.е. не сохраняет взаимное положение элементов с равными ключами)
Если нужна устойчивая, сортируй сам - при небольшом количестве элементов - вставками, при большом - слиянием


 
ЮЮ ©   (2006-12-12 03:18) [5]


> Все работает, однако при сортировке зачем то переставляются
> местами одинаковые элементы списка.


Ну и пусть переставляет, если одинаковые. А если тебя перестановака не устраивает, то значит всё-таки не одинаковые :)


> if res = 0 then res := -1;

предположим пришлось сравнить два элемента списка a и b дважды:  
CompareTRec(a, b) и CompareTRec(b, a),
а твоя функция утверждает, что a < b и b < а. Какой угодно алгоритм сортировки на этом зациклится :)


 
said46   (2006-12-12 09:19) [6]


> Ну и пусть переставляет, если одинаковые. А если тебя перестановака
> не устраивает, то значит всё-таки не одинаковые :)


Мне нужно было отсортировать записи по времени... В списке есть записи с одинаковым временем, но с разными остальными полями.

Рекурсия была из-за парадокса... строка if Result = 0 then Result := -1; подразумевала, что при сравнении элемента с самим с собой результат - он меньше самого себя =) .

Проблемы решилиись изменением функции обратного вызова таким образом:
function CompareTRec(Item1, Item2: Pointer): Integer;
begin
 Result := CompareDateTime(PTRec(Item1)^.RT, PTRec(Item2)^.RT);
 if Result = 0 then Result := -1;
 if Item1 = Item2 then Result := 0;
end;


И переполнения стека нет, и одинаковые элементы не переставляет почем зря...


 
Sha ©   (2006-12-12 09:42) [7]

Для QuickSort требуется, чтобы результат повторного сравнения любых двух элементов был тем же, что и первый раз. И более того, из (a<=b, b<=c) должно следовать, что a<=c. Иначе аозможен выход за границу массива.

Для HeapSort этого не требуется.


 
Sha ©   (2006-12-12 10:02) [8]

QuickSort относится к классу сортировок, не сохраняющих порядок. Это ее принципиальное свойство, которое нельзя изменить. Если тебе кажется, что ты этого добился - значит ты ее ипортил , и тебя подстерегает AV.

Тебе просто надо использовать сортировку, сохраняющую порядок, или использовать в критерии сортировки поле с уникальным значением, задающим порядок следования равных (по остальным полям) элементов.



Страницы: 1 вся ветка

Текущий архив: 2006.12.31;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.044 c
2-1165901349
Данил.Ялта
2006-12-12 08:29
2006.12.31
Загрузка файлов и превращение html->txt


4-1156274077
Dot
2006-08-22 23:14
2006.12.31
поиск hwnd одного из двух окон


2-1166112610
Khabibulin
2006-12-14 19:10
2006.12.31
Выделить нужную ячейку в StringGrid


1-1163162281
mmms
2006-11-10 15:38
2006.12.31
Как вставить пункт в выпадающее меню IE


2-1165911061
pathfinder
2006-12-12 11:11
2006.12.31
Win to Dos, Unicode..