Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Бинарный поиск в С / 25 сообщений из 39, страница 1 из 2
23.10.2017, 10:00
    #39540282
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
Я хочу сделать бинарный поиск в сортированном массиве. Без рекурсии.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
int BinarySearch(int arr[], int low, int high, int key)
{
     int mid; // = (low + high)/2;
     int  done = 0;
     
     if (high < low) 
           return -1;
       
     mid = (low + high)/2;
         
     while (!done)
     {
         if(key==arr[mid])
             return mid;
         else if (key > arr[mid])
             mid = ((mid+1) + high) / 2;
         else if (key < arr[mid])
            mid = (low + (mid-1)) / 2;
     }
     
     return -1;
}



Если искомый элемент (key) есть в массиве (arr) то все нормально, функция возвращает индекс массива. Но если элемента нет в массиве я кручусь все время в цикле (while (!done)).
Я что то никак не соображу по какому условию выйти из цикла.
...
Рейтинг: 0 / 0
23.10.2017, 10:26
    #39540293
Vladimir Baskakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
Надо сжимать интервал, если он сжался, а ничего не нашлось, тогда ой. шпаргалка под спойлером, лучше не подглядывать, без крайней нужды. а додумать. потому что все несложно. Главное не забыть менять done - а то же там константа, поэтому цикл будет вращаться до конца света.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
int BinarySearch(int arr[], int low, int high, int key)
{
     int mid; // = (low + high)/2;
     int  done = 0;
     
     if (high < low) 
           return -1;
       
         
     while (1)
     {
         mid = (low + high)/2;

         if(key==arr[mid])  return mid;

         if (low==high) return -1;

         if (key > arr[mid])  low = (mid+1) 
         else  high =  (mid-1);
                
     }   
    
}


int BinarySearch_rec(int arr[], int low, int high, int key)
{
     int mid; // = (low + high)/2;
     int  done = 0;
     
     if (high < low) return -1;
       
     mid = (low + high)/2;

     if(key==arr[mid])
             return mid;
     if (low==high) return -1;
     if (key > arr[mid])
             low = (mid+1) ;
     else  high =  (mid-1);
     return BinarySearch_rec(arr, low, high, key);
}

...
Рейтинг: 0 / 0
23.10.2017, 10:27
    #39540294
exp98
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
По условию done = y, где у != 0
например внутри цикла
...
Рейтинг: 0 / 0
23.10.2017, 10:39
    #39540306
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
Vladimir BaskakovНадо сжимать интервал, если он сжался, а ничего не нашлось, тогда ой. шпаргалка под спойлером, лучше не подглядывать, без крайней нужды. а додумать. потому что все несложно. Главное не забыть менять done - а то же там константа, поэтому цикл будет вращаться до конца света.

большое спасибо. работает. но у меня тут еще одна проблема. я хочу вставлять элемент если он не найден. то есть я хочу вернуть не -1 а индекс на место которого я хочу вставить элемент. соответсвенно все элементы перед ним я сдвину вправо. как мне модифицировать функцию?
я думал ввести условие
Код: plaintext
1.
 else if (key > arr[mid] && key <  arr[mid+1])


но что то в нем не так.
...
Рейтинг: 0 / 0
23.10.2017, 10:48
    #39540314
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
а проблема в том что это недостаточное условие. нужен какой то флаг - элемент не найден. но тогда получается нужно делать еще один пробег?
...
Рейтинг: 0 / 0
23.10.2017, 11:07
    #39540336
MBo
MBo
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
jenya7, пробег делать не надо, достаточно ещё одного сравнения. Вот из Вики:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
 
   while (first < last) {
        size_t mid = first + (last - first) / 2;

        if (x <= a[mid])
            last = mid;
        else
            first = mid + 1;
    }

    /* Если условный оператор if (n == 0) и т.д. в начале опущен -
     * значит, тут раскомментировать!
     */
    if (/* last < n && */ a[last] == x) {
        /* Искомый элемент найден. last - искомый индекс */
        return FOUND(last);
    } else {
        /* Искомый элемент не найден. Но если вам вдруг надо его
         * вставить со сдвигом, то его место - last.
         */
        return NOTFOUND(last);
    }
...
Рейтинг: 0 / 0
23.10.2017, 11:10
    #39540339
exp98
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
jenya7, а done чем не флаг? в integer разных значений как грязи весной ...
...
Рейтинг: 0 / 0
23.10.2017, 11:24
    #39540345
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
MBojenya7, пробег делать не надо, достаточно ещё одного сравнения. Вот из Вики:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
 
   while (first < last) {
        size_t mid = first + (last - first) / 2;

        if (x <= a[mid])
            last = mid;
        else
            first = mid + 1;
    }

    /* Если условный оператор if (n == 0) и т.д. в начале опущен -
     * значит, тут раскомментировать!
     */
    if (/* last < n && */ a[last] == x) {
        /* Искомый элемент найден. last - искомый индекс */
        return FOUND(last);
    } else {
        /* Искомый элемент не найден. Но если вам вдруг надо его
         * вставить со сдвигом, то его место - last.
         */
        return NOTFOUND(last);
    }


а FOUND это что? дефайн?
...
Рейтинг: 0 / 0
23.10.2017, 11:36
    #39540349
MBo
MBo
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
а FOUND это что? дефайн?
Да, там возвращается структура из двух членов - индекс и boolean признак. Достаточно нелепо.
Варианты:
- изменить прототип, индекс сделать аргументом, а результат - boolean
- возвращать положительный индекс при наличии, отрицательный при отсутствии.
- при использовании исключительно для поиска места для вставки - оставить обычный интерфейс
...
Рейтинг: 0 / 0
23.10.2017, 11:37
    #39540350
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
а где изменяется n?
...
Рейтинг: 0 / 0
23.10.2017, 11:45
    #39540355
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
не хватает условия. я могу вывести флаг аргументом наружу

int BinarySearch(int a[], int first, int last, int key, int *found)

но нужно еще одно условие
...
Рейтинг: 0 / 0
23.10.2017, 11:46
    #39540356
MBo
MBo
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
jenya7, это длина массива, она, в общем-то, не нужна и закомментарена. Код https://ru.wikipedia.org/wiki/Двоичный_поиск
...
Рейтинг: 0 / 0
23.10.2017, 11:47
    #39540357
MBo
MBo
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
jenya7,

какое ещё условие нужно?
...
Рейтинг: 0 / 0
23.10.2017, 12:37
    #39540389
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
MBojenya7,

какое ещё условие нужно?
спасибо. сделал так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
int BinarySearch(int a[], int pos, int key, int *found)
{
    int first = 0;
    int last = pos;
    int mid;
    
    if (pos == 0)  //empty array
    {
        *found = 0;
        return 0;
    }
    else if (a[0] > key) 
    {
        *found = 0;
        return 0;
    }
    else if (a[pos - 1] < key)
    {
        *found = 0;
        return pos;
    }
    
    while (first < last)
    {
        mid = first + (last - first) / 2;

        if (key <= a[mid])
            last = mid;
        else
            first = mid + 1;
    }

    if (a[last] == key)
    {
        *found = 1;
        return last;
    }
    else
    {
        *found = 0;
        return last;
    }
}


похоже что работает.
...
Рейтинг: 0 / 0
23.10.2017, 12:53
    #39540405
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
jenya7спасибо. сделал так
Код: plaintext
1.
int BinarySearch(int a[], int pos, int key, int *found)


Я так понимаю found это найдено/не найдено.

Обычно наоборот делают, функция возвращает ошибку, а переменная под результат в параметрах, т.е.
Код: plaintext
1.
int BinarySearch(int a[], int pos, int key, int *result)
...
Рейтинг: 0 / 0
23.10.2017, 12:55
    #39540410
Siemargl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
http://www.cplusplus.com/reference/cstdlib/bsearch/

и не надо изобретать
...
Рейтинг: 0 / 0
23.10.2017, 12:57
    #39540413
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
Dima Tjenya7спасибо. сделал так
Код: plaintext
1.
int BinarySearch(int a[], int pos, int key, int *found)


Я так понимаю found это найдено/не найдено.

Обычно наоборот делают, функция возвращает ошибку, а переменная под результат в параметрах, т.е.
Код: plaintext
1.
int BinarySearch(int a[], int pos, int key, int *result)


понял. спасибо. переделаю.
...
Рейтинг: 0 / 0
23.10.2017, 13:03
    #39540419
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
Siemargl http://www.cplusplus.com/reference/cstdlib/bsearch/

и не надо изобретать
инетересно но сложно. вопрос что будет compar в моем случае?
...
Рейтинг: 0 / 0
23.10.2017, 13:06
    #39540422
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
jenya7Siemargl http://www.cplusplus.com/reference/cstdlib/bsearch/

и не надо изобретать
инетересно но сложно. вопрос что будет compar в моем случае?
Там есть пример кода с твоим случаем, т.е. массивом int.
...
Рейтинг: 0 / 0
23.10.2017, 13:17
    #39540435
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
Dima Tjenya7пропущено...

инетересно но сложно. вопрос что будет compar в моем случае?
Там есть пример кода с твоим случаем, т.е. массивом int.

а где тут поиск середины?

Код: plaintext
1.
2.
3.
4.
int compareints (const void * a, const void * b)
{
  return ( *(int*)a - *(int*)b );
}
...
Рейтинг: 0 / 0
23.10.2017, 13:22
    #39540441
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
jenya7Dima Tпропущено...

Там есть пример кода с твоим случаем, т.е. массивом int.

а где тут поиск середины?

Код: plaintext
1.
2.
3.
4.
int compareints (const void * a, const void * b)
{
  return ( *(int*)a - *(int*)b );
}


Тут нет поиска середины, т.к. это компаратор, т.е. функция сравнения двух элементов массива.
Сам алгоритм поиска внутри bsearch(), в которую передаются исходные данные, включая компаратор.
...
Рейтинг: 0 / 0
23.10.2017, 13:26
    #39540446
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
Dima Tэто компаратор, т.е. функция сравнения двух элементов массива
Неправильно выразился, это функция сравнения значений по двум указателям.
...
Рейтинг: 0 / 0
23.10.2017, 13:36
    #39540454
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
Dima Tjenya7пропущено...


а где тут поиск середины?

Код: plaintext
1.
2.
3.
4.
int compareints (const void * a, const void * b)
{
  return ( *(int*)a - *(int*)b );
}


Тут нет поиска середины, т.к. это компаратор, т.е. функция сравнения двух элементов массива.
Сам алгоритм поиска внутри bsearch(), в которую передаются исходные данные, включая компаратор.
а нам нужна эта функция для бинарного поиска? мне кажется я могу передать нулевой указатель в качестве аргумента. все аргументы для поиска присутствуют в bsearch а компаратор как мне кажется лишний элемент.
...
Рейтинг: 0 / 0
23.10.2017, 13:54
    #39540468
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
jenya7Dima Tпропущено...

Тут нет поиска середины, т.к. это компаратор, т.е. функция сравнения двух элементов массива.
Сам алгоритм поиска внутри bsearch(), в которую передаются исходные данные, включая компаратор.
а нам нужна эта функция для бинарного поиска? мне кажется я могу передать нулевой указатель в качестве аргумента. все аргументы для поиска присутствуют в bsearch а компаратор как мне кажется лишний элемент.
bsearch() универсальная функция для любых типов, на входе у нее void*. Компаратор нужен для того чтобы правильно сравнить два void*
...
Рейтинг: 0 / 0
23.10.2017, 14:23
    #39540488
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Бинарный поиск в С
Dima Tjenya7пропущено...

а нам нужна эта функция для бинарного поиска? мне кажется я могу передать нулевой указатель в качестве аргумента. все аргументы для поиска присутствуют в bsearch а компаратор как мне кажется лишний элемент.
bsearch() универсальная функция для любых типов, на входе у нее void*. Компаратор нужен для того чтобы правильно сравнить два void*
понял. спасибо. попробую.
...
Рейтинг: 0 / 0
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Бинарный поиск в С / 25 сообщений из 39, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]