Поиск массива строк

В основном цель этой программы состоит в том, чтобы прочитать до 100 имен из файла, отсортировать с помощью пузырьковой сортировки, а затем найти введенное имя с помощью двоичного поиска.

Вроде бы все работает, за исключением того, что когда я ввожу имя, которое есть в списке, ничего не происходит, мне просто предлагают ввести имя еще раз.

Произнесите имя из списка Элвисом Пресли. Мне предлагают ввести имя. Я печатаю Элвиса Пресли. Я ДОЛЖЕН принять, что Элвис Пресли — твой друг. Не происходит. Любая помощь приветствуется.

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

void bubblesort(string[], const int);
void search(string[], const int);
int sub = 0;

int main()
{
 const int maxsize = 100;
 string friendArray[maxsize];

 ifstream friends;
 friends.open("myFriends.dat");

 while (sub < maxsize && getline(friends, friendArray[sub]))
   sub++;


 bubblesort(friendArray, sub);
 search(friendArray, maxsize);


 system("pause");
 return 0;
}



void bubblesort(string *array, const int size)
{
    bool swap;
    string temp;

    do
    {
        swap = false;
        for (int count = 1; count < (size - 1); count++)
        {
            if(array[count-1] >array[count])
            {
                temp = array[count-1];
                array[count-1] = array[count];
                array[count] = temp;
                swap = true;
            }
        }
    }
    while(swap);

}

void search(string *array, int size)
{
    int first = 0;
    int last = size - 1;
    int middle;
    string name;
    bool friends = false;

    do
    {
     cout<<"Please enter a name or END to terminate:";
     cin>>name;
    }
    while(!friends && first <= last && name != "END");
    {
        middle = (first + last) / 2;
        if (array[middle] == name)
            {
                friends = true;
                cout<<array[middle]<<" is my friend."<<endl;
            }
        else if (array[middle] > name)
            last = middle - 1;
        else
            last = middle + 1;
    }
}

person sircrisp    schedule 06.12.2011    source источник
comment
Не рекомендуется исправлять вопрос на основе ответов, так как это в значительной степени делает недействительным каждый ответ и делает вопрос бесполезным (поскольку после исправления не возникает проблемы). Если изменения не носят чисто косметический характер, вам следует задать другой вопрос, удалив этот, если он больше не актуален.   -  person paxdiablo    schedule 06.12.2011
comment
Хорошо, я начну новый вопрос.   -  person sircrisp    schedule 06.12.2011


Ответы (9)


В вашей функции search() конструкция do { } while; { } ошибочна. Он скомпилируется, но не будет делать то, что вы хотите. Я внес несколько изменений и изменил ваш код, чтобы он имел больше смысла.

void search(string *array, int size)
{
    string name;

    for (;;)
    {
        cout<<"Please enter a name or END to terminate:";
        getline(cin, name);
        if (name == "END") break;

        int first = 0;
        int last = size - 1;
        bool friends = false;

        while (!friends && first <= last)
        {
            int middle = (first + last) / 2;
            if (array[middle] == name)
            {
                friends = true;
                cout<<array[middle]<<" is my friend."<<endl;
            }
            else if (array[middle] > name)
                last = middle - 1;
            else
                first = middle + 1;
        }
    }
}

int main () // test the search() function
{
    string array[] = { "bird", "cat", "dog", "horse", "loon", "zebra" };
    search(array, 6);
}

ТАК, это слишком много домашней работы? Должен ли я удалить это?

person Blastfurnace    schedule 06.12.2011
comment
Это здорово, я чувствую, что намного лучше учусь на визуальных примерах, потому что именно так я узнал все из моей книги. Он не очень хорошо объясняет мне алгоритмы. - person sircrisp; 06.12.2011
comment
@sircrisp: Вы были близки. Я только что изменил ваш код, так что есть внешний цикл, который запрашивает имя поиска, и внутренний цикл, который выполняет двоичный поиск. - person Blastfurnace; 06.12.2011
comment
Я изменил свой код, чтобы он соответствовал вашему, теперь, когда я набираю имя из списка, программа ничего не делает, но я слышу, как вентилятор процессора становится все громче и громче. - person sircrisp; 06.12.2011
comment
@sircrisp: проверьте свой код сортировки и убедитесь, что массив в порядке, прежде чем вызывать функцию поиска. - person Blastfurnace; 06.12.2011
comment
@sircrisp: я добавил тестовый код, и этот search() работает. Входной массив должен быть отсортирован в порядке возрастания. - person Blastfurnace; 06.12.2011
comment
Это сработало, я очень благодарен, я слишком устал, чтобы просматривать код, но я обязательно проверю его утром, чтобы посмотреть, что я делал неправильно, спасибо, я наконец-то могу закончить! - person sircrisp; 06.12.2011

Мне кажется интересным, что вы установили last в оба случаях, когда не нашли соответствия.

Первое, что вы должны сделать, это подумать о том, что это значит, подтолкнуть, подтолкнуть, подмигнуть, подмигнуть :-)

Вы также должны передать количество используемых элементов в search, а не размер массива (поскольку вы можете использовать не весь массив).

person paxdiablo    schedule 06.12.2011
comment
Два последних были просто опечаткой, но это могло что-то разрушить, когда проблема, которую я пытаюсь решить, была решена. - person sircrisp; 06.12.2011

Я полагаю, что

search(friendArray, maxsize);

должно быть

search(friendArray, sub);

Входное условие бинарного поиска состоит в том, что искомый массив отсортирован. Ваш массив выглядит так:

Aaron Burr
Bill Cosby
Celine Dion
...
Zachary Taylor
""
""
""
""

etc.

Так как пустая строка не меньше непустой строки, то friendArray[0..maxsize] не сортируется, а массив friendArray[0..sub] сортируется.


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

person Robᵩ    schedule 06.12.2011

Оператор >> читает отформатированные данные из потока, т.е. отбрасывает пробелы. Когда вы произносите cin >> name; и вводите «Элвис Пресли», в name сохраняется только «Элвис».

Вам нужно getline(cin, name);

person jrok    schedule 06.12.2011
comment
Однако спасибо, что заметили, что проблема все еще остается. - person sircrisp; 06.12.2011

Подумайте, что произойдет, если длина вашего массива friends будет равна 3. Если не ошибаюсь, будет проблема.

Также рекомендуется использовать более безопасные типы данных, такие как vector<string>, например, тогда вам не нужно заботиться о слишком большом количестве данных во входном файле. Также ваша жизнь станет проще в функции поиска, так как вы можете использовать итераторы и не нужно передавать размер массива.

Посмотрите, что люди говорят в других ответах о cin.

person Roman Byshko    schedule 06.12.2011
comment
Я изменил cin на getline и search на search(friendArray, sub). Никогда раньше не использовал векторы или еще не знал о них, поэтому я хотел бы как можно меньше изменить свой существующий код. - person sircrisp; 06.12.2011
comment
@sircrisp Хорошо. Подумайте, что произойдет, если длина friends равна 3. Я вижу, что вы указываете, просто примите это как совет и взгляните на них позже, это того стоит. - person Roman Byshko; 06.12.2011

Это одна петля do-whi:

do
{
 cout<<"Please enter a name or END to terminate:";
 cin>>name;
}
while(!friends && first <= last && name != "END");

Код будет в основном зацикливаться навсегда (друзья никогда не будут истинными, а первый никогда не будет> последним), запрашивая у вас имя, пока вы либо не завершите программу, либо не наберете «КОНЕЦ».

Этот:

{
    middle = (first + last) / 2;
    if (array[middle] == name)
        {
            friends = true;
            cout<<array[middle]<<" is my friend."<<endl;
        }
    else if (array[middle] > name)
        last = middle - 1;
    else
        last = middle + 1; 
}

не будет возможности выполниться, пока условие цикла не станет ложным (в данном случае, пока вы не наберете «КОНЕЦ»).

person Dimitar Velitchkov    schedule 06.12.2011
comment
Я изменил while на while(!friends && name != END); Однако не повезло. Я работаю над этим 4 часа, я больше ничего не могу определить, моя логика мертва. - person sircrisp; 06.12.2011

Вы говорите, что вроде все работает, за исключением случаев, когда вы ввели имя для поиска. На самом деле, вы попали в точку. В вашем двоичном коде поиска ошибка. И первый ответ в этой теме в сторону этого пути.

Если массив используется в бинарном поиске, он должен быть разбит на две части на каждом этапе поиска.

Например, на этапе, если текущая часть отмечена следующим образом: первая - средняя - последняя, ​​на следующем этапе части будут либо между первой - средней - 1, либо средней + 1 - последней.

So

    else if (array[middle] > name)
      last = middle - 1;
    else 
      last = middle + 1;

должно быть

  else if (array[middle] > name)
      last = middle - 1;
  else 
      first = middle + 1;
person oak    schedule 06.12.2011

У вас есть ошибка на единицу в вашей сортировке.

person Mark Ransom    schedule 06.12.2011
comment
Хочешь указать, какая часть неверна? Я получил помощь с сортировкой ранее. - person sircrisp; 06.12.2011
comment
@sircrisp, извините, это слишком похоже на домашнее задание, чтобы я мог дать простой ответ. Но пройдитесь по коду и посмотрите, какой элемент пропущен. - person Mark Ransom; 06.12.2011

Проблема в поиске функций. переместите } после cin>>name в конец функции, чтобы она выглядела так:

void search(string *array, int size)
{
    int first = 0;
    int last = size - 1;
    int middle;
    string name;
    bool friends = false;

    do
    {
        cout<<"Please enter a name or END to terminate:";
        cin>>name;

        while(!friends && first <= last && name != "END");
        {
            middle = (first + last) / 2;
            if (array[middle] == name)
            {
                friends = true;
                cout<<array[middle]<<" is my friend."<<endl;
            }
            else if (array[middle] > name)
                last = middle - 1;
            else 
                last = middle + 1;
        }
    }
}
person Kamyar Souri    schedule 06.12.2011