thisdesuのブログ

C言語はじめました

にほんブログ村 IT技術ブログ C/C++へ

実用:並び替え(qsort)

そろそろプログラム的な事も混ぜてきしょう。っでソート。
良くある実用事例で、沢山有るデータを何らかの基準を設けて並べる(ソート関数)を使ってみましょう。もちろん自分でソート関数も作ることは出来ますが、ここままず、標準である二分岐ソート(qsort)を使ってみます。

void qsort(void *base, size_t nmemb, size_t size,int(*compar)(const void *, const void *));


さて、いきなり関数が第4引数にある例ですが、この関数は自分で基準を指定する所なので、構造体の一部を指定したりして色々な昇順降順を決定することが出来ます。

#include <stdio.h>
#include <stdlib.h> // qsortで利用します。

typedef struct _item {
  int no;
  char name[10];
} ITEM;

int comp(const void *a, const void *b) {
  // 戻りは、マイナスか0かプラスで、aとbの前後が決まります(0は未確定だけど)
  // プラス:aが先
  // マイナス:bが先
  // 0:同じ
  return( ((ITEM*)a)->no - ((ITEM*)b)->no ); 
}

int comp2(const void *a, const void *b) {
  return( ((ITEM*)b)->no - ((ITEM*)a)->no ); 
}

int comp3(const void *a, const void *b) {
  int w = ((ITEM*)a)->no - ((ITEM*)b)->no ;

  // aとbが同じならnameの文字列比較
  return( (w!=0 ? w : strcmp(((ITEM*)a)->name,((ITEM*)b)->name)) ) ;
}


int main() {
  ITEM item[10] ={ {1,"N1"},{9,"N9"},{3,"N3-2"},{2,"N2"},{3,"N3-1"},{8,"N8"},{5,"N5"},{4,"N4"},{5,"N5"},{6,"N6"} };
  int i;

  printf("before\n");
  for(i=0; i< 10; i++) {
    printf("before(%d): no(%d) name[%s]\n",i,item[i].no,item[i].name);
  }

  qsort(item, 10, sizeof(ITEM), comp );

  printf("after-1\n");
  for(i=0; i< 10; i++) {
    printf("before(%d): no(%d) name[%s]\n",i,item[i].no,item[i].name);
  }

  qsort(item, 10, sizeof(ITEM), comp2 );

  printf("after-2\n");
  for(i=0; i< 10; i++) {
    printf("before(%d): no(%d) name[%s]\n",i,item[i].no,item[i].name);
  }

  qsort(item, 10, sizeof(ITEM), comp3 );

  printf("after-3\n");
  for(i=0; i< 10; i++) {
    printf("before(%d): no(%d) name[%s]\n",i,item[i].no,item[i].name);
  }


}


■実行結果
before:sort前
after-1:noの昇順
after-2:noの降順
after-3:noの昇順だけど同じだったらnameの比較strcmp

$ gcc main.c
$ ./a.out
before
before(0): no(1) name[N1]
before(1): no(9) name[N9]
before(2): no(3) name[N3-2]
before(3): no(2) name[N2]
before(4): no(3) name[N3-1]
before(5): no(8) name[N8]
before(6): no(5) name[N5]
before(7): no(4) name[N4]
before(8): no(5) name[N5]
before(9): no(6) name[N6]
after-1
before(0): no(1) name[N1]
before(1): no(2) name[N2]
before(2): no(3) name[N3-2]
before(3): no(3) name[N3-1]
before(4): no(4) name[N4]
before(5): no(5) name[N5]
before(6): no(5) name[N5]
before(7): no(6) name[N6]
before(8): no(8) name[N8]
before(9): no(9) name[N9]
after-2
before(0): no(9) name[N9]
before(1): no(8) name[N8]
before(2): no(6) name[N6]
before(3): no(5) name[N5]
before(4): no(5) name[N5]
before(5): no(4) name[N4]
before(6): no(3) name[N3-2]
before(7): no(3) name[N3-1]
before(8): no(2) name[N2]
before(9): no(1) name[N1]
after-3
before(0): no(1) name[N1]
before(1): no(2) name[N2]
before(2): no(3) name[N3-1]
before(3): no(3) name[N3-2]
before(4): no(4) name[N4]
before(5): no(5) name[N5]
before(6): no(5) name[N5]
before(7): no(6) name[N6]
before(8): no(8) name[N8]
before(9): no(9) name[N9]