Страница: 1 |
|
Вопрос: Сортировка многомерного динамического массива
|
Добавлено: 07.07.05 23:34
|
|
Автор вопроса: anatoliy-2
|
Как отсортировать многомерный динамический массив по любому из имеющихся столбцов? Массив типа variant.
Данные в первом столбце числа, во втором даты, в третьем
строки.
С уважением Анатолий.
Ответить
|
Номер ответа: 1 Автор ответа:
HOOLIGAN

Вопросов: 0 Ответов: 1066
|
Профиль | | #1
|
Добавлено: 08.07.05 01:07
|
массив Variant - не лучшее решение в данном случае.
Лучше одномерный массив структур типа такого:
MyStruct
lDate As Date
lTime As Date
lString As String * xx 'лучше фиксированной длины
EndStruct
и сортировать по значениям MyStruct.lDate или MyStruct.lString и т.д.
Так ты будешь иметь данные о длине каждого элемента массива (каждой переменной типа MyStruct). Это значительно быстрее.
Ответить
|
Номер ответа: 2 Автор ответа:
Nash Bridges

Вопросов: 5 Ответов: 139
|
Профиль | | #2
|
Добавлено: 08.07.05 14:57
|
какие структуры ? массив вариантов получается автоматически из рекордсета. а массив структур это надо вручную разносить. значительно быстрее ? это какой алгоритм использовать.
Ответить
|
Номер ответа: 4 Автор ответа:
HOOLIGAN

Вопросов: 0 Ответов: 1066
|
Профиль | | #4
|
Добавлено: 08.07.05 16:05
|
Nash Bridges
Какой к чёрту рекордсет? О рекордсете речи не шло пока.
Или ты ясновидящий?
А сортировать - ничего сложного тут нет, алгоритмов сортировки - куча, выбирай любой.
Ответить
|
Номер ответа: 8 Автор ответа:
HOOLIGAN

Вопросов: 0 Ответов: 1066
|
Профиль | | #8
|
Добавлено: 08.07.05 17:05
|
Если данные были в рекордсете - незачем их доставать оттуда для сортировки. Обычно у рекордсета есть свои методы сортировки. Можно воспользоваться им.
Если данные не в рекордсете - незачем их туда пихать, можно отсортировать самому данные. Будет гораздо быстрее.
А многомерности тут никакой нет. Обычный одномерный массив. У которого каждый элемент имеет три поля.
anatoliy-2
Берешь любой алгоритм сортировки, и в том месте, где происходит сравнение двух элементов массива (это место обязательно есть), вставляешь свою функцию, которая будет проверять соответствующие (одноименные) поля двух сравниваемых элементов. И всё.
Nash Bridges
Ин да взопрели озимыя?
Ответить
|
Номер ответа: 10 Автор ответа:
anatoliy-2
 
Вопросов: 12 Ответов: 14
|
Профиль | | #10
|
Добавлено: 10.07.05 00:47
|
Спасибо Всем что ответили, но варианта который меня устроил бы, пока не предложили.
Уточняю вопрос:
Есть многомерный динамический массив типа Variant в котором накапливаются данные разных форматов(string, date, time, integer). После этого все это, для вывода информации записывается в ListView. ListView может сортировать данные только как String. Мне необходимо отсортировать данные скажем по дате. Для этого стираю данные в ListView, сортирую данные в массиве в необходимом столбце по дате (а вот как не знаю) и записываю их опять в ListView. Сортировать данные в одномерном массиве умею, а в многомерном никак не соображу, и как быть дальше не знаю, а очень надо.
С уважением Анатолий. 09.07.2005 23:42:52
Ответить
|
Номер ответа: 11 Автор ответа:
HOOLIGAN

Вопросов: 0 Ответов: 1066
|
Профиль | | #11
|
Добавлено: 10.07.05 01:04
|
Это не многомерный массив. Это массив одномерный.
Делал такую прогу типа виндового поиска, с выводом имени файла, пути, размера, даты доступа. Тоже в листвью. И сортировка по любой из колонок (т.е. и по стринг, и по лонг, и по дате). Но это не сортировка многомерного массива.
Это массив структур, каждая из которых состоит из нескольких полей разного типа.
Если сортировать одномерный массив умеешь, непонятно, в чём проблема. При сортировке нужно переставлять не отдельные стринги или даты, а целиком несколько полей, связанных в одну структуру, чтобы например стринг, соответствующий одной дате, не переехал к какой-то из других дат. Перемещай все поля одной записи скопом, синхронно.
Ответить
|
Номер ответа: 14 Автор ответа:
HOOLIGAN

Вопросов: 0 Ответов: 1066
|
Профиль | | #14
|
Добавлено: 10.07.05 02:46
|
Блин, щас будем писать сочинение
На примере программы, осуществляющей поиск файлов на винте.
Объявляю структуру, в которой хранится инфа о найденном файле, например:
Public Type FindStruct
FileName As String *104
   irName As String *200
FileSize As Long
WriteTime As SYSTEMTIME
End Type
Можно ещё какие-нибудь поля добавить, например атрибуты файла, но для примера достаточно.
Далее делаю массив структур.
Dim MyFindData(0 To 100000) As FindStruct 'в него можно записать данные о 100000 файлах.
Запускаю цикл поиска с FindFirstFile/FindNextFile. Из этих АПИ получаю интересующую меня инфу, и копирую их в поля элементов массива, например получил данные файла - и сделал
MyFindData (i).FileName = <имя файла>
MyFindData (i).DirName = <имя папки>
MyFindData (i).FileSize = <размер файла>
MyFindData (i).WriteTime= <время последней записи в файл>
Один элемент массива заполнен, Последовательно по мере нахождения файлов, заполняю следующие элементы массива.
Это примерно чтобы объяснить, что variant здесь ни к чему. И чтобы видно было, как хранятся найденные данные.
После того, как все твои найденные файлы упакованы в массив, можно сортировать его. Процедура сортировки должна реагировать на то, по какому из признаков (полей структуры) надо сортировать. Т.е. знать, какие поля сравнивать между собой у разных элементов массива.
Function Sort_Array (Struct_Arr() As FindStruct, columnIndex As Long) As Long
Dim temp As FindStruct 'вспомогательная переменная для обмена
'тут любой алгоритм сортировки
'какой нравится или подходит
'в нем обязательно есть сравнение 2-х элементов
'и производится перестановка элементов, или нет
'в зависимости от результата сравнения
If columnIndex = 1 Then 'сортируем по имени файла
'..........
'дошли до места сравнения
If Struct_Arr(m).FileName < Struct_Arr(n).FileName Then 'если надо поменять элементы массива
temp = Struct_Arr(m) 'меняем не просто имя. а весь элемент целиком
Struct_Arr(m) = Struct_Arr(n) 'используя временную переменную
Struct_Arr(n) = temp 'теперь два элемента поменялись целиком
'все данные каждого из файлов остались при них
'и не перепутались.
End If
ElseIf columnIndex = 2 Then 'сортируем по папке файла также, только сравнивать будем .DirName
'..........
'дошли до места сравнения
If Struct_Arr(m).DirName < Struct_Arr(n).DirName Then 'если надо поменять элементы массива
temp = Struct_Arr(m) 'меняем не просто папку, а весь элемент целиком
Struct_Arr(m) = Struct_Arr(n) 'используя временную переменную
Struct_Arr(n) = temp 'теперь два элемента поменялись целиком
'все данные каждого из файлов остались при них
'и не перепутались.
End If
ElseIf columnIndex = 3 Then 'сортируем по размерам файлов
'все повторяется, только для поля .FileSize
'и т.д. продолжается код, для каждого из полей по которому сортируется массив
End Function
На выходе из ф-ции сортировки будут переставлены в порядке возрастания/убывания элементы массива.
Причём данные, изначально связанные в один элемент, так и останутся принадлежностью одного элемента. Просто они всем блоком из четырех полей перекочуют в положенное им по алфавиту место.
Функция Sort_Array принимает в качестве параметров твой массив (Struct_Arr() As FindStruct) и номер колонки листвью, по которой кликнули, чтобы отсортировать её (columnIndex As Long).
Это простейшая схема. Её конечно надо дополнить необходимыми кусками алгоритма сортировки.
Но принцип здесь виден. Это будет значительно проще и быстрее, чем с variant-массивом.
Было бы ещё быстрее, если бы vb позволял работать напрямую с указателями. При этом можно было бы менять местами только указатели на элементы масива, а сами элементы перемещать не надо было бы.
Но увы, vb не позволяет работать напрямую с указателями, только через огромную задницу
На всякий случай код, которым я сортировал колонки листвью. Это широко известный алгоритм quick_sort.
Правда код не на vb, на си++, но думаю, тут можно разглядеть кое-что.
И ещё: тут сравнивались элементы массива, но сами они не перемещались (не менялись местами). Менялись местами только указатели на элементы, которые были скомпонованы в отдельную табличку.
//============= struct =====================================
typedef struct FIND_DATA{
SYSTEMTIME writeTime;
int iIcon;
   WORD dwSize;
char fName[104];
char attr[5];
char dirName[200];
}FIND_DATA, *pFIND_DATA;
//============= types =====================================
typedef FIND_DATA* item; /* Тип сортируемых элементов */
typedef int tblIndex; /* Тип ключей, по которым сортируем */
typedef FIND_DATA* T;
//===============================================================
int CmpIndex(item ptr1, item ptr2){
FILETIME ft1;
FILETIME ft2;
int result;
if (ColumnIndex==0){
result = (_stricoll((ptr1->fName),ptr2->fName));
}
else if (ColumnIndex==1){
result = (_stricoll((ptr1->dirName),ptr2->dirName));
}
else if (ColumnIndex==2){
result = (ptr1->dwSize - ptr2->dwSize);
}
else if (ColumnIndex==3){
result = (strcmp(ptr1->attr, ptr2->attr));
}
else if (ColumnIndex==4){
SystemTimeToFileTime(&ptr1->writeTime, &ft1);
SystemTimeToFileTime(&ptr2->writeTime, &ft2);
result = (CompareFileTime(&ft1,&ft2));
}
return SortDirection*result;
}
//===============================================================
tblIndex partition(T* a, tblIndex lb, tblIndex ub) {
item t, pivot;
tblIndex i, j, p;
/**********************************
* разделение массива a[lb..ub] *
**********************************/
/* Выбираем центр - pivot */
p = lb + ((ub - lb)>>2);
pivot = a[p];
a[p] = a[lb];
/* сортируем lb+1..ub относительно центра */
i = lb+1;
j = ub;
while (1) {
while (i < j && CmpIndex(pivot,a[i]  >0){
i++;
}
while (j >= i && CmpIndex(a[j],pivot)>0){
j--;
}
//while (i < j && pivot>a[i]  i++;
//while (j >= i && a[j]>pivot) j--;
if (i >= j) break;
t = (FIND_DATA*)a[i];
a[i] = a[j];
a[j] = t;
j--; i++;
}
/* центр в a[j] */
a[lb] = a[j];
a[j] = pivot;
return j;
}
//===============================================================
void __stdcall quickSort(T *a, tblIndex lb, tblIndex ub) {
tblIndex m;
/**************************
* сортируем a[lb..ub] *
**************************/
while (lb < ub) {
/* разделение пополам */
m = partition (a, lb, ub);
if (m - lb <= ub - m) {
quickSort(a, lb, m - 1);
lb = m + 1;
}
else {
quickSort(a, m + 1, ub);
ub = m - 1;
}
}
}
Короче, разбирайся.
Ответить
|
Страница: 1 |
Поиск по форуму