Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Общий форум

Страница: 1 |

 

  Вопрос: Сортировка многомерного динамического массива Добавлено: 07.07.05 23:34  

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

Ответить

  Ответы Всего ответов: 15  

Номер ответа: 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
какие структуры ? массив вариантов получается автоматически из рекордсета. а массив структур это надо вручную разносить. значительно быстрее ? это какой алгоритм использовать.

Ответить

Номер ответа: 3
Автор ответа:
 LamerOnLine



ICQ: 334781088 

Вопросов: 108
Ответов: 2822
 Профиль | | #3 Добавлено: 08.07.05 15:33
Не, забудь, наиглушайшее занятие - сортировка массива, да еще и многомерного, да еще и Variant... Придумай че получше.
Откуда масив то берешь?

Ответить

Номер ответа: 4
Автор ответа:
 HOOLIGAN



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

А сортировать - ничего сложного тут нет, алгоритмов сортировки - куча, выбирай любой.

Ответить

Номер ответа: 5
Автор ответа:
 Nash Bridges



Вопросов: 5
Ответов: 139
 Профиль | | #5 Добавлено: 08.07.05 16:13
не хами. хам !

Ответить

Номер ответа: 6
Автор ответа:
 LamerOnLine



ICQ: 334781088 

Вопросов: 108
Ответов: 2822
 Профиль | | #6 Добавлено: 08.07.05 16:16
Дело не в отсутствии алгоритма сортировки. Просто трудно представить более нерациональный способ сортировки данных нежели многомерный массив Variant. Потому и спрашиваю - откуда берутся данные, возможно их проще запихнуть в тот же рекордсет. В идеале - привести код...

Ответить

Номер ответа: 7
Автор ответа:
 CyRax



Разработчик Offline Client

ICQ: 204447456 

Вопросов: 180
Ответов: 4229
 Web-сайт: basicproduction.nm.ru
 Профиль | | #7
Добавлено: 08.07.05 17:01
http://algolist.manual.ru/sort/

Ответить

Номер ответа: 8
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #8 Добавлено: 08.07.05 17:05
Если данные были в рекордсете - незачем их доставать оттуда для сортировки. Обычно у рекордсета есть свои методы сортировки. Можно воспользоваться им.
Если данные не в рекордсете - незачем их туда пихать, можно отсортировать самому данные. Будет гораздо быстрее.

А многомерности тут никакой нет. Обычный одномерный массив. У которого каждый элемент имеет три поля.

anatoliy-2
Берешь любой алгоритм сортировки, и в том месте, где происходит сравнение двух элементов массива (это место обязательно есть), вставляешь свою функцию, которая будет проверять соответствующие (одноименные) поля двух сравниваемых элементов. И всё.

Nash Bridges
Ин да взопрели озимыя?

Ответить

Номер ответа: 9
Автор ответа:
 LamerOnLine



ICQ: 334781088 

Вопросов: 108
Ответов: 2822
 Профиль | | #9 Добавлено: 08.07.05 17:18
Я к тому что подобные данные лучше бы хранить в рекордсете. Массив однозначно одномерный и никаких Variant, но работать с массивами в качестве БД - жуткий гемор. Та же сортировка и удаление займут на порядок больше времени и кода. ИМХО, не для этого есть массивы.

Ответить

Номер ответа: 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
Это не многомерный массив. Это массив одномерный.
Делал такую прогу типа виндового поиска, с выводом имени файла, пути, размера, даты доступа. Тоже в листвью. И сортировка по любой из колонок (т.е. и по стринг, и по лонг, и по дате). Но это не сортировка многомерного массива.
Это массив структур, каждая из которых состоит из нескольких полей разного типа.
Если сортировать одномерный массив умеешь, непонятно, в чём проблема. При сортировке нужно переставлять не отдельные стринги или даты, а целиком несколько полей, связанных в одну структуру, чтобы например стринг, соответствующий одной дате, не переехал к какой-то из других дат. Перемещай все поля одной записи скопом, синхронно.

Ответить

Номер ответа: 12
Автор ответа:
 anatoliy-2



Вопросов: 12
Ответов: 14
 Профиль | | #12 Добавлено: 10.07.05 01:18
HOOLIGAN если можно пожалуйста по подробней о сортировке массива структур. С уважением Анатолий.

Ответить

Номер ответа: 13
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #13 Добавлено: 10.07.05 02:06
Блин, тебе же уже сказали тут, и неоднократно говорили в аналогичных
топиках:

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

Ответить

Номер ответа: 14
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #14 Добавлено: 10.07.05 02:46
Блин, щас будем писать сочинение :(

На примере программы, осуществляющей поиск файлов на винте.

Объявляю структуру, в которой хранится инфа о найденном файле, например:

Public Type FindStruct
    FileName    As String *104
    ;DirName     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;
        ;DWORD        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;
                        }
                }
}


Короче, разбирайся.

Ответить

Номер ответа: 15
Автор ответа:
 anatoliy-2



Вопросов: 12
Ответов: 14
 Профиль | | #15 Добавлено: 15.07.05 23:18
Добрый вечер (день) HOOLIGAN. Огромное спасибо за вполне содержательный ответ!
Извиняюсь за задержку с благодарностью. Пробую сейчас привязать предложенный Вами вариант к своей программе. О результатах сообщу через неделю. У меня еще вопрос. Где же все таки находят применение многомерные динамические массивы, в том числе типа Variant ?! Спасибо большое CyRax за ссылку на Д.Кнут!

С уважением Анатолий. 15.07.2005 22:11

Ответить

Страница: 1 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам