Лекция 9. Поиск и сортировка

Лексикографическое сравнение строк

char s1[] = "abc"; // компилятор выделит память под 4 символа, влючая \0.
char s2[] = "xyz";

Как сравнить содержимое строк s1 и s2? Простое сравнение s1 == s2 не даст желаемого результата, так сравниваться будут адреса массивов в памяти, а не их содержание. В этом случае не остаётся ничего лучшего, кроме как поэлементно сравнить строки и убедиться, что они равны.

Рассмотрим функцию лексикографического (алфавитного) сравнения, которая есть в стандартной библиотеке:

int strcmp(char s1[], char s2[])
{
    int i = 0;
    while (s1[i] == s2[i]) {
        if (s1[i] == '\0') {
            break;
        }
        ++i;
    }
    return s1[i] - s2[i];
}

Данная функция возвращает отрицательное число, если s1 стоит по алфавиту раньше s2, положительное, если s1 стоит позже, и 0, если строки равны. Её можно, например, использовать для сравнения строк:

char buf[80];
scanf("%80s", buf);
if (0 == strcmp(buf, "hello") {
        printf("И тебе тоже привет!");
}

Такой код выведет приветсвите в том случае, если пользователь введёт hello.

Функция поиска

Предпочтительный вариант, краткий и выразительный.

int find(int a[], int n, int x)
{
    int i;
    for(i = 0; i < n; ++i) {
        if (a[i] == x) {
            return i;
        }
    }
    return -1;
}

Не забывайте, что return одновременно и копирует результат переданного ей выражения в ячейку памяти для результата функции, и завершает выполнение функции.

Вариант поиска с использованием break:

int find(int a[], int n, int x)
{
    int i;
    for(i = 0; i < n; ++i) {
        if (a[i] == n) {
            break;
        }
    }
    if (i == n) {
        return -1;
    } else {
        return i;
    }
}

Обратите внимание на условие if-a.

И наконец, вариант поиска с иcпользованием флага. Флаг – это логическая переменная (тип int в языке си, 0 – ложь, 1 – истина), которая используется для того, чтобы сохранить информацию о наступлении некоторого события, чтобы предпринять некоторые действия в дальнейшем.

int find(int a[], int n, int x)
{
    int i, found_flag = 0;
    for (i = 0; i < n; ++i) {
        if (a[i] == n) {
            found_flag = 1;
            break;
        }
    }
    if (found_flag) {
        return i;
    } else {
        return -1;
    }
}

Поиск минимума

Функция для поиска минимума выглядит следующим образом:

int find_min(int a[], int n)
{
    if (n < 1) { // В массиве из 0 элементов нельзя найти минимум.
        return -1;
    }
    int min_ind = 0;
    for (i = 1; i < n; ++i) {
        if (a[i] < a[min_ind]) {
            min_ind = i;
        }
    }
    return min_ind;
}

Сортировка

Сортировка пузырьком:

void bubble_sort(int a[], int n)
{
    int i, j;
    for(i = 1; i < n; ++i) {
        for(j = 0; j < n - i; ++j) {
            if(a[j] > a[j + 1]) {
                int t = a[j];
                a[j] = a[j + 1];
                a[j + 1] = t;
            }
        }
    }
}

Сортировка выбором (так же имеет квадратичное по n время работы, но быстрее, так как делаем меньше присваиваний).

void selection_sort(int a[], int n)
{
    int i;
    for (i = 0; i < n - 1; ++i) {
        // см. вопрос в задании 8. :)
    }
}

TODO: напоминание про вызов функции