Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Бинарный поиск


Автор: Agarwaen 7.1.2007, 12:22
Задание: вводится строка и ключевой символ. Нужно найти номера позиций этого символа в строке методом деления пополам. Вот код, но он ищет только одну позицию. Посоветуйте что можно сделать. 
Код

#include <stdio.h>
#include <string.h>
#include <iostream.h>
#include <io.h>
#include <iomanip.h>
#define Nmax 255

typedef struct is{
         char symbol;
         int index;
         } isymbol;

int main()
{
char buffer[Nmax],key;
 printf("Enter the string(%d symbols) and press Enter:",Nmax);
 cin>>setw(Nmax)>>buffer;
 printf("Enter the key symbol to search and press Enter:");
 cin>>setw(1)>>key;

 int i,j,size;
 size=strlen(buffer);
 isymbol string[Nmax];
 for (i=0;i<size;i++)
      {
      string[i].symbol=buffer[i];
      string[i].index=i+1;
      }

 isymbol temp;
 for (i=0;i<size;i++)
     for (j=0;j<size;j++)
      if (string[i].symbol<string[j].symbol)
     {
     temp=string[j];
     string[j]=string[i];
     string[i]=temp;
     }

 int m,t=0,b=size;
 while (t<=b)
   {m=(t+b)/2;
   if (string[m].symbol<key) t=m+1;
     else b=m-1;
   if (string[m].symbol==key)
    printf("\n Position of key symbol: %d",m);
   }
return 0;
}

Автор: Kuvaldis 7.1.2007, 13:08
Agarwaen, 
Цитата

Нужно найти номера позиций этого символа в строке методом деления пополам.

Метод деления пополам применяется только к отсортированным данным
Есть обобщение данного метода, которое ищет именно ПЕРВОЕ вхождение символа в строку (остальные получить несложно, нужно лишь запустить цикл: пока символ справа равен искомому, увеличивать счетчик и продвигаться по сортированной строке вправо)

Код

int L, R;

L = 0;
R = N;  // длина строки
while (L > R)
{
        m = (L + R) / 2;
        if (str[m] < x)
              L = m + 1;
        else
              R = m;
}

if (str[m] == x)
 // нашли
else
 // не нашли 

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

Автор: Agarwaen 7.1.2007, 18:56
  Не пойму как это работает. Можно поподробней?

Автор: Agarwaen 7.1.2007, 20:17
Вот функция, возвращает 1 значение. Как её можно изменить? 
Код

int find(struct is s[], int n, char key)
{
    int a,b,m;
     for (a=0,b=n-1;a<=b;)
     {
     m=(a+b)/2;
     if (s[m].symbol==key) return s[m].index;
     if (s[m].symbol>key)
      b = m-1;
     else
      a = m+1;
     }
return -1;
}

Автор: Kuvaldis 7.1.2007, 20:43
Agarwaen, 
Код

//-------------------------------------------------------------
#include <stdio.h>    
#include <conio.h>
#include <string.h>    
#include <iostream.h>
#include <iomanip.h>
//-------------------------------------------------------------    
#define Nmax 255    
//-------------------------------------------------------------
typedef struct is
{    
    char symbol;    
    int index;    
} isymbol;    
//-------------------------------------------------------------
int main()    
{    
    char  buffer[Nmax];
    char  key;
    
    printf("Enter the string (%d symbols) and press Enter: \n",Nmax);    
    cin >> setw(Nmax) >> buffer;    
 
    printf("Enter the key symbol to search and press Enter:");    
    cin >> setw(1) >> key;    
 
    int i,j,size;    
 
    size = strlen(buffer);    
    isymbol string[Nmax];    
 
    for (i = 0; i < size; i++)    
    {    
        string[i].symbol = buffer[i];    
        string[i].index = i;    
    }    
 
    isymbol temp;    
    // сортировка символов  (обычный пузырек)
    for (i = 0; i < size - 1; i++)
    {
        for (j = 1; j < size - i; j++)
        {
            if (string[j - 1].symbol > string[j].symbol)    
            {    
                temp = string[j];    
                string[j] = string[j - 1];
                string[j - 1] = temp;    
            }    
        }
    }

    int m, l = 0, r = size - 1;    
 
    while (l < r)    
    {
        m = (l + r) / 2;    
        if (string[m].symbol < key) 
            l = m + 1;    
        else 
            r = m;    
    }

    if (string[r].symbol == key)    // совпадение было
    {

        printf("\n Positions of key symbol %c are: \n", key);
        do
        {
            cout << string[r].index << ' ';
            r++;    // перейти к следующему символу в отсортированном массиве
        }
        while (string[r].symbol == key);
    }
    else
        cout << "No match" << endl;

    getch();
    return 0;
}
//-------------------------------------------------------------

Автор: Agarwaen 7.1.2007, 21:03
  Огромное спасибо. И ещё такой вопрос: какой метод сортировки самый быстрый?

Автор: KpoHyc 7.1.2007, 21:05
Agarwaen, так и называйется "Быстрая сортировка" Чарльз Хоар автор...

Автор: Agarwaen 7.1.2007, 21:53
  Странно, когда вводишь в строке пробел, то он сбрасывает в ключ первый символ и всё. В чём дело?

Автор: Agarwaen 8.1.2007, 00:40
 Блин не пойму почему строка записывается в buffer до первого пробела. 
Код

    char* buffer=new char[Nmax];
    char  key;

    clrscr();
    printf("Enter the string (%d symbols) and press Enter: ",Nmax);
    scanf("%s",buffer);
    /*cout.unsetf(ios::skipws);
    cin >> setw(Nmax) >> buffer;*/

    printf("\n Enter the key symbol to search and press Enter:");
    cout << (key=getch());

Автор: Agarwaen 8.1.2007, 04:03
Вот посмотрите этот код. Какие общие замечания? По-прежнему есть проблемы с пробелами во входной строке, может кто подскажет. И ещё насколько здесь оправдано использование ввода/вывода через потоки? Заранее спасибо.   
Код

//-------------------------------------------------------------
#include <stdio.h>
#include <conio.h>
#include <string.h>
//-------------------------------------------------------------
#define Nmax 128
//-------------------------------------------------------------
typedef struct IS
{
    char symbol;
    int index;
} isymbol;
void sort(struct IS[], int);
void bisearch(struct IS[], char, int);
//-------------------------------------------------------------
void main()
{
  char buffer[Nmax];
  char key;

  clrscr();
  printf("===========================Binary search========================\n");
  printf("   Enter the string and press Enter: ");
  scanf("%s",buffer);

  int i,size;
  size = strlen(buffer);
  isymbol string[Nmax];

  for (i = 0; i < size; i++)
    {
    string[i].symbol = buffer[i];
    string[i].index = i+1;
    }

  sort (string, size);

  do
    {
    printf("\n   Enter the key symbol to search and press Enter:");
    key = getch();
    printf(" %c\n",key);
    printf("\n=============================Search=============================\n");
    bisearch(string, key, size);
    printf("\n   Press y to continue, any other key to exit:");
    }
  while (getch()=='y');
}
//-------------------------------------------------------------
void sort(struct IS s[], int size)
{
  int i,j;
  isymbol temp;
  for (i = 0; i < size - 1; i++)
    {
    for (j = 1; j < size - i; j++)
      {
      if (s[j - 1].symbol > s[j].symbol)
    {
    temp = s[j];
    s[j] = s[j - 1];
    s[j - 1] = temp;
    }
      }
    }
}
//-------------------------------------------------------------
void bisearch(struct IS s[], char key, int size)
{
  int m = 0, l = 0, r = size - 1;
  while (l < r)
    {
    m = (l + r) / 2;
    if (s[m].symbol < key)
    l = m + 1;
    else
    r = m;
    }
   if (s[r].symbol == key)
    {
    printf("\n   Position(s) of key symbol %c are: ", key);
    do
      {
      printf(" %d", s[r].index);
      r++;
      }
    while (s[r].symbol == key);
    }
   else
      printf("\n   Position(s) of key symbol %c are: No solution", key);
}

Автор: Kuvaldis 8.1.2007, 10:42
Agarwaen, 
Цитата

 По-прежнему есть проблемы с пробелами во входной строке, может кто подскажет.

Такой принцип работы у cin и scanf при работе со строками. Чтобы изменить ситуацию, можно:
1. С:
fgets(char* str, int maexlen); используем эту функцию, подробности по F1

2. C++:
cin.getline(char* str, int maxlen); 
подробности также по F1

Автор: Agarwaen 8.1.2007, 13:31
 Спасибо, ты мне очень помог. Использую наверно gets(buffer).

Автор: sergejzr 8.1.2007, 14:08
Существует стандартная функция сортировки "qsort".
Ей сортировать лучше и быстрее всего.

Код

#include <iostream>
#include "stdlib.h"
using namespace std;
#define Nmax 26
int compareChar(const void *first,const void *second)
{
char *firstc=(char*)first;
 char *secondc=(char*)second;
return (*firstc)-(*secondc);
//return (*secondc)-(*firstc); //Если сортируем в обратном порядке
}
int main()
{
char buffer[Nmax];
int i;
for(i=0;i<Nmax;i++)
{
buffer[i]=25-i+'A';
}
cout<<"Do sortirovki"<<endl;
for(i=0;i<Nmax;i++)
{
cout<<buffer[i];
}
cout<<endl;
qsort ( buffer, Nmax, sizeof(char), compareChar);

cout<<"Posle sortirovki"<<endl;
for(i=0;i<Nmax;i++)
{
cout<<buffer[i];
}
cin>>i;
}

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)