Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторна робота 4.1.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
68.61 Кб
Скачать

6. Швидке сортування (сортування Хоара)

"Швидке сортування", хоч і була розроблена більше 40 років тому, є найбільш широко застосовуваним і одним їх найефективніших алгоритмів.

void quickSortR(int* a, long N) {

// На входе - массив a[], a[N] - его последний элемент.

 

  long i = 0, j = N;        // поставить указатели на исходные места

  T temp, p;

 

  p = a[ N>>1 ];        // центральный элемент

 

  // процедура разделения

  do {

    while ( a[i] < p ) i++;

    while ( a[j] > p ) j--;

 

    if (i <= j) {

      temp = a[i]; a[i] = a[j]; a[j] = temp;

      i++; j--;

    }

  } while ( i<=j );

 

  // рекурсивные вызовы, если есть, что сортировать

  if ( j > 0 ) quickSortR(a, j);

  if ( N > i ) quickSortR(a+i, N-i);

}

Кожне поділ вимагає, очевидно, O (n) операцій. Кількість кроків поділу (глибина рекурсії) становить приблизно log n, якщо масив ділиться на більш-менш рівні частини. Таким чином, загальну швидкодію: O (n log n), що і має місце на практиці.

Порозрядне сортування.

Розглянутий нижче алгоритм істотно відрізняється від описаних раніше.

По-перше, він зовсім не використовує порівнянь сортируемих елементів.

По-друге, ключ, за яким відбувається сортування, необхідно розділити на частини, розряди ключа. Наприклад, слово можна розділити по буквах, число - по цифрах ...

typedef struct slist_ {

  long val;

  struct slist_ *next;

} slist;

 

// функция сортировки возвращает указатель на начало отсортированного списка

slist *radix_list(slist *l, int t) {

  //  t - разрядность (максимальная длина числа)

  int i, j, d, m=1;

  slist *temp, *out, *head[10], *tail[10];

  out=l;

 

  for (j=1; j<=t; j++) {

    for (i=0; i<=9; i++)

      head[i] = (tail[i]=NULL);

 

    while ( l != NULL ) {

      d = ((int)(l->val/m))%(int)10;

      temp = tail[d];

      if ( head[d]==NULL ) head[d] = l;

      else temp->next = l;

      temp = tail[d] = l;

      l = l->next;

      temp->next = NULL;

    }

    for (i=0; i<=9; i++)

      if ( head[i] != NULL ) break;

    l = head[i];

    temp = tail[i];

    for (d=i+1; d<=9; d++) {

      if ( head[d] != NULL) {

        temp->next = head[d];

        temp = tail[d];

      }

    }

    m*=10;

  }

  return (out);

}

Завдання:

Дано послідовність, що містить від 1 до 30 слів, у кожному з яких від 1 до 5 прописних латинських букв; між сусідніми словами - кома, за останнім словом - крапка. Надрукувати:

  1. цю же послідовність слів, але у зворотному порядку;

  2. ті слова, перед якими в послідовності перебувають тільки менші (за алфавітом) слова, а за ними - тільки більші;

  3. цю же послідовність слів, але видаливши з її повторні входження слів;

  4. всі слова, які зустрічаються в послідовності по одному разі;

  5. всі різні слова, указавши для кожного з них число його входжень у послідовність;

  6. всі слова за абеткою (у порядку зростання);

  7. всі слова в порядку убування.

Контрольні питання:

  1. Особливості опису рядкових змінних.

  2. Особливості використання операторів вводу-виведення для рядкових даних.

Аналіз одержаних результатів:

Підсумування та оформлення результатів експерименту слід обов’язково писати в кінці звіту в розділі «висновки». Висновки до лабораторної роботи слід писати про те, що було досліджено чи проаналізовано в даній лабораторній роботі. Не писати висновки від першої особи, уникаючи фраз типу: «я вивчи(в) / (ла)», чи «ми вивчили». Обов’язково здійснити та задокументувати обробку експериментальних даних.