LoginSignup
15
11

More than 5 years have passed since last update.

C言語でクイックソート

Last updated at Posted at 2018-10-11

クイックソートとは

実用上最も高速といわれる有名なアルゴリズム。

  • 分割統治法による整列アルゴリズム
    • 列を2つに分割して、それぞれを整列していく。
手順:
  1. pivot(軸となる要素)を1つ選び、pivotより小さい部分列と大きい部分列に分ける
  2. 小さい側をクイックソート
  3. 大きい側をクイックソート

サンプルプログラム

ここでは、int型の配列を、クイックソートを用いて小さい順に整列する。

quick_sort.c
#include<stdio.h>

/* 値を入れ替える関数 */
void swap (int *x, int *y) {
  int temp;    // 値を一時保存する変数

  temp = *x;
  *x = *y;
  *y = temp;
}

/***
* pivotを決め、
* 全データをpivotを境目に振り分け、
* pivotの添え字を返す
***/
int partition (int array[], int left, int right) {
  int i, j, pivot;
  i = left;
  j = right + 1;
  pivot = left;   // 先頭要素をpivotとする

  do {
    do { i++; } while (array[i] < array[pivot]);
    do { j--; } while (array[pivot] < array[j]);
    // pivotより小さいものを左へ、大きいものを右へ
    if (i < j) { swap(&array[i], &array[j]); }
  } while (i < j);

  swap(&array[pivot], &array[j]);   //pivotを更新

  return j;
}

/* クイックソート */
void quick_sort (int array[], int left, int right) {
  int pivot;

  if (left < right) {
    pivot = partition(array, left, right);
    quick_sort(array, left, pivot-1);   // pivotを境に再帰的にクイックソート
    quick_sort(array, pivot+1, right);
  }
}

int main (void) {
  int array[10] = { 2, 1, 8, 5, 4, 7, 9, 0, 6, 3 };
  int i;

  printf("Before sort: ");
  for (i = 0; i < 10; i++) { printf("%d ", array[i]); }
  printf("\n");

  quick_sort(array, 0, 9);

  printf("After sort: ");
  for (i = 0; i < 10; i++) { printf("%d ", array[i]); }
  printf("\n");

  return 0;
}

実行結果

Before sort: 2 1 8 5 4 7 9 0 6 3
After sort: 0 1 2 3 4 5 6 7 8 9

性能

  • 平均計算量は$O(n\log n)$
  • 最悪計算量は$O(n^2)$
    • pivotにより列を2分割するが、これが左右に偏ってしまうと分割数が多くなり時間がかかる
    • できるだけ2等分に近い分け方をすると、効率が良くなる
      • 中央値をpivotにするとか
15
11
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
11