|
|
  |
Быстрый доступ к элементу. |
|
|
|
Oct 22 2017, 10:07
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(Rst7 @ Oct 22 2017, 14:59)  В данном случае за 3 сравнения (бинарным поиском) Вы находите место для вставки элемента с ID 18 (между 13 и 25). После чего Вам его просто нужно вставить (копирование трех элементов плюс запись нового). Массив остается отсортированным. копирование трех элементов плюс запись нового не получиться - таки надо раздвинуть. Цитата(jcxz @ Oct 22 2017, 15:04)  Не в свободное место, а раздвинув существующие. И не все надо сдвигать, а от позиции нового пришедшего, до позиции удаляемого.
Исходить надо из случая заполненности всего массива (имеется все 512 кадров). И при старте делать инициализацию, заполнив первоначально массив недопустимыми индексами (с ID1 > 10000 например). то есть сдвинуть все элементы вправо от искомого. а при удалении все элементы влево от искомого. наверно это все равно будет быстрее чем с несортированным массивом.
Сообщение отредактировал Jenya7 - Oct 22 2017, 10:09
|
|
|
|
|
Oct 22 2017, 10:47
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610

|
QUOTE (Jenya7 @ Oct 22 2017, 13:16)  это как? допустим есть элементы 3 5 7 9. я хочу вставить 6. он встанет на место 7. а семь куда встанет? Еще раз. CODE #define N (5)
int a[N];
a[0]=3; a[1]=5; a[2]=7; a[3]=9;
i=2; //В эту позицию надо вставить элемент
memmove(a+(i+1),a+i,sizeof(int)*(N-1-i)); //Сдвиг элементов 2,3 на позиции 3,4 - копирование a[2],a[3] в a[3],a[4] a[i]=6; После этого массив имеет вид 3,5,6,7,9. memmove в большинстве случаев - это быстро. Но надо проверять, что конкретная библиотечная реализация действительно оптимальна.
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
Oct 22 2017, 10:49
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(Rst7 @ Oct 22 2017, 15:47)  Еще раз. Код #define N (5)
int a[N];
a[0]=3; a[1]=5; a[2]=7; a[3]=9;
i=2; //В эту позицию надо вставить элемент
memmove(a+(i+1),a+i,sizeof(int)*(N-1-i)); //Сдвиг элементов 2,3 на позиции 3,4 - копирование a[2],a[3] в a[3],a[4] a[i]=6; После этого массив имеет вид 3,5,6,7,9. memmove в большинстве случаев - это быстро. Но надо проверять, что конкретная библиотечная реализация действительно оптимальна. да но внутри функции memmove - она все равно сдвинет N элементов. она ж не волшебница. а я понял. ну вот в этом вопрос - насколько это оптимально. получим ли мы выйгрыш в результате всех этих телодвижений. Вставка элемента - допустим случай *как всегда* - memmove не оптимальна - сдвиг N элементов. Удаление - сдвиг N элементов. Это сопоставимо с перебором элементов в форе. Идем дальше. Массив пустой. Пришел первый элемент 100. Пришел элемент 90 - сдвинь вправо, вставь элемент. Пришел элемент 80 - сдвинь вправо, вставь элемент. И так далее. И все таки это будет быстрее простого перебора? Посмотрел красно-черное дерево. пишут конечно красиво. маслом. вопрос так ли он быстЁр как кажется.
Сообщение отредактировал Jenya7 - Oct 22 2017, 11:00
|
|
|
|
|
Oct 22 2017, 10:59
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610

|
QUOTE а я понял. ну вот в этом вопрос - насколько это оптимально. получим ли мы выйгрыш в результате всех этих телодвижений. Ну смотрите. Поиск будет занимать 9 сравнений. Считайте, что это бесплатно. Теперь memmove. Ну при хорошей реализации для ARM он примерно два байта за такт процессора пересылает (ну чуть меньше, чем два, но сейчас это пофиг). Итого максимум будет 8*512=4к/2=2000 тактов. Ну пусть будет среднепотолочная тактовая в 100МГц, т.е. 20мкс. Да даже, если и один байт на такт, все равно 40мкс. Много или мало - решать Вам. QUOTE Это сопоставимо с перебором элементов в форе. memmove куда быстрее, чем перебор элементов в цикле.
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
Oct 22 2017, 11:15
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(k155la3 @ Oct 22 2017, 13:32)  Это зависит от платформы ? - в смысле содержимого memmove() - аппаратная или программная реализация пересылки ? Я говорю о том, что не нужно дважды вызывать memmove(): сначала для удаления старой записи из массива поиска (и сжатия массива), а потом для раздвижки этого массива и вставки нового значения. Достаточно одного вызова memmove() для диапазона элементов от удаляемого до вставляемого. Цитата(Jenya7 @ Oct 22 2017, 13:39)  memmove() применяется к массиву в РАМ. Тут уж какя бы ни была платформа а функция должна взять каждый элемент и сдвинуть. Если разговор о платформе Cortex-M и IAR, то внутри библиотечной memcpy() (и думаю что и memmove() тоже), копирование может идти с использованием нескольких регистров процессора (читается-пишется сразу по несколько 32-битных слов). См. дизасм. Цитата(Rst7 @ Oct 22 2017, 13:59)  Ну смотрите. Поиск будет занимать 9 сравнений. Считайте, что это бесплатно. Теперь memmove. Ну при хорошей реализации для ARM он примерно два байта за такт процессора пересылает (ну чуть меньше, чем два, но сейчас это пофиг). Да ладно! Какой компилятор? IAR-овский memcpy() может использовать до 4х или даже 8и регистров (точно не помню) процессора для копирования. Посчитайте сколько это байт. Конечно он предварительно смотрит на размер пересылки и, в зависимости от него, выбирает тот или иной цикл копирования. Побайтно будет для ОЧЕНЬ маленьких размеров.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|