本日の目標
- ソートのアルゴリズムを理解して、利用することができる。
- 構造体を使って表されるデータをソートすることができる。
予習・復習
以下のスライドを利用して、予習と復習をしよう。復習では、自分の理解度を確認するために、実際にプログラムを作成し、意図する結果が得られるか確認しよう。本日の講義・演習予定
- 線形探索
- 二分探索
- 計算量
- 演習問題
- 提出課題
#define <stdio.h>
#define N 10
void print_array(int a[], int size);
void simple_sort(int a[], int size);
int main(void)
{
int data[N] = {21,12,8,65,22,40,34,17,7,51};
printf("before: ");
print_array(data,N);
simple_sort(data,N);
printf("after : ");
print_array(data,N);
return 0;
}
/* 単純ソート */
void simple_sort(int a[], int n)
{
int i,j,tmp;
for(i=0; i <size-1; i++){ // i番目の要素と
for(j=i+1; j<size; j++){ // それ以外の未ソートの要素を
if(a[i] > a[j]){ // 比較し、左側の要素が大きければ
tmp = a[i]; // 交換
a[i] = a[j];
a[j] = tmp
}
}
}
}
#include <stdio.h>
#define swap(a,b){ int tmp; tmp=a; a=b; b=tmp; }
int main(void)
{
int x=3,y=7;
swap(x,y);
/* swap(x,y);以下のように展開される
{ int tmp; tmp = x; x = y; y = tmp; };
*/
printf("%d %d\n",x,y);
return 0;
}
#include <stdio.h>
#define swap(a,b) { int tmp; tmp=a; a=b; b=tmp; }
int main(void)
{
int x=3, y=7;
if(x>y)
swap(x,y);
/* { int tmp; tmp=a; a=b; b=tmp; }; <--セミコロンでifが終了してしまう */
else
printf("Without the need to swap.\n");
printf("%d %d\n",x,y);
return 0;
}
このような場合の対応策として、do while文が利用できます。
#define swap(type, a,b) do{ type tmp; tmp=a; a=b; b=tmp; }while(0)
void ins_sort(int a[], int n)
{
int i,j,tmp;
for(i=1; i<n; i++){
tmp = a[i]; // 退避
for(j=i-1; j>=0 && a[j]>tmp; j--){ //前方のデータがtmpより大きい場合
a[j+1] = a[j]; // 後方へ移動
}
a[j+1] = tmp; // 挿入
}
}
void shell_sort(int a[], int n)
{
int i,j,k,h,x;
for(h=n/2; h>0; h/=2){ // 間隔を1になるまで半分に狭める
for(k=0; k<h; k++){ // グループ数分繰り返す
for(i=k+h; i<n; i+=h){ //以下挿入ソート
x = a[i];
for(j=i-h; j>=k && a[j]>x; j-=h)
a[j+h] = a[j];
a[j+h] = x; //挿入
}
}
}
}
#include <stdio.h>
void merge(int a[], int na, int b[], int nb, int c[])
{
int i=0,j=0,k=0;
while(i<na && j<nb)
c[k++] = a[i]<b[j] ? a[i++] : b[j++]; //小さい方の値を格納
while(i<na) c[k++] = a[i++]; //残った要素を格納
while(j<nb) c[k++] = b[j++];
}
int main(void)
{
int a[3] = {1,5,6};
int b[2] = {3,7};
int c[5];
int i;
merge(a,3,b,2,c);
for(i=0; i<5; i++) printf("%d,",c[i]);
printf("\n");
return 0;
}

#include <stdio.h>
#include <stdlib.h>
#define N 10
//プロトタイプ宣言
void merging(int left,int mid,int right);
void merge_sort(int left, int right);
void print_array(void);
int a[N] = {21,12,8,65,22,40,34,17,7,5};
int work[N]; //作業用(マージ結果格納用)
void merging(int left,int mid,int right)
{
int i,j,k;
i=left; //配列の左半分の先頭
j=mid+1; //配列の右半分の先頭
k=left; //マージ結果格納用配列のインデックス
while(i<=mid && j<=right)
work[k++] = a[i]<=a[j] ? a[i++] : a[j++]; //小さい方の値を格納
while(i<=mid) work[k++] = a[i++]; //残った要素を格納
while(j<=right) work[k++] = a[j++];
for(i=left; i<=right; i++) a[i] = work[i];
}
void merge_sort(int left, int right){
int mid;
if(left<right){
mid = (left+right)/2; //中央の位置を取得
merge_sort(left,mid); //左半分ソート(要素数が1になるまで再帰的に)
merge_sort(mid+1,right); //右半分ソート(要素数が1になるまで再帰的に)
merging(left,mid,right); //マージ
}
}
int main(void)
{
int i;
printf("Before :");
for(i=0; i<N; i++) printf(" %2d,",a[i]);
printf("\n");
merge_sort(0,N-1);
printf("After :");
for(i=0; i<N; i++) printf(" %2d,",a[i]);
printf("\n");
return 0;
}
void quick_sort(int a[], int left, int right)
{
int pl,pr,pivot;
if(left>=right) return; //交差していたら要素が1つだけと判断し終了
pivot = a[(left + right)/2]; //配列の中央の要素を枢軸とする
pl=left; //小さい値グループ(左側)のインデックス
pr=right; //大きい値グループ(右側)のインデックス
while(pl<=pr){
while(a[pl] < pivot) pl++; //右端Gから枢軸以上の値が現れるまで走査
while(a[pr] > pivot) pr--; //左端Gから枢軸以下の値が現れるまで走査
if(pl<=pr){ //走査が交差していなければ
swap(a[pl],a[pr]); //左右の要素を入れ替える
pl++;
pr--;
}
}
quick_sort(a,left,pr); //左側グループを再帰的にソート
quick_sort(a,pl,right); //右側グループを再帰的にソート
}
struct student{
int id;
char name[32];
int score;
}
#include <stdio.h>
#define swap(a,b) { int tmp=a; a=b; b=tmp; }
#define N 10
void select_sort_dec(int a[], int n);
void bubble_sort(int a[], int n);
void ins_sort_dec(int a[], int n);
void print_array(int a[],int n);
int main(void)
{
int a[] = {6,3,17,8,2,7,12,11,5,15};
printf("Before: ");
print_array(a,N);
//select_sort_dec(a,N);
//bubble_sort(a,N);
ins_sort_dec(a,N);
printf("After : ");
print_array(a,N);
return 0;
}
/* 単純選択ソート(降順) */
void select_sort_dec(int a[], int n)
{
int i,j;
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(a[i]<a[j]) swap(a[i],a[j]);
}
/* バブルソート */
void bubble_sort(int a[], int n)
{
int i,j;
for(i=0;i<n-1; i++){
for(j=n-1; j>i; j--)
if(a[j-1]>a[j]) swap(a[j-1],a[j]);
print_array(a,n);
}
}
/* 挿入ソート(降順) */
void ins_sort_dec(int a[], int n)
{
int tmp,i,j;
for(i=1; i<n; i++){
tmp = a[i];
for(j=i-1; j>=0 && a[j]<tmp; j--)
a[j+1] = a[j];
a[j+1] = tmp;
}
}
void print_array(int a[],int n)
{
int i;
for(i=0; i<n; i++)
printf("%d ",a[i]);
printf("\n");
}
#include <stdio.h>
#include <limits.h>
#define N 10
void print_array(int a[], int n);
int a[N] = {21,12,8,65,22,40,34,17,7,5};
int al[N],ar[N];
void merging(int left, int mid, int right)
{
int i,j=0,k=0;
for(i=left; i<=mid; i++) al[j++] = a[i];
al[j] = INT_MAX; //番兵
print_array(al,j);
for(i=mid+1; i<=right; i++) ar[k++] = a[i];
ar[k] = INT_MAX; //番兵
print_array(ar,k);
for(i=left,j=0,k=0; i<=right; i++)
a[i] = al[j] <ar[k] ? al[j++] : ar[k++];
}
void merge_sort(int left, int right)
{
int mid;
if(left < right){
mid = (left + right)/2;
merge_sort(left,mid);
merge_sort(mid+1,right);
merging(left,mid,right);
}
}
void print_array(int a[], int n)
{
int i;
for(i=0; i<n; i++)
printf("%d ",a[i]);
printf("\n");
}
int main(void)
{
printf("Before: ");
print_array(a,N);
merge_sort(0,N-1);
printf("After : ");
print_array(a,N);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#define N 10
//プロトタイプ宣言
void merging(int a[], int left,int mid,int right);
void _merge_sort(int a[], int left, int right);
int merge_sort(int a[], int n);
void print_array(int a[], int n);
int *work; //作業用領域
void merging(int a[], int left,int mid,int right)
{
int i,wi,j=0;
int k=left;
for(i=left,wi=0; i<=mid; i++,wi++) work[wi] = a[i]; //左半分のみコピー
//左半分workと右半分aを比較して、小さい方をaの先頭から格納する
while(i<=right && j<wi)
a[k++] = work[j]<=a[i] ? work[j++] : a[i++];
//workに残っている要素があればaに移す
while(j<wi) a[k++] = work[j++];
}
void _merge_sort(int a[], int left, int right)
{
int mid;
if(left<right){
mid = (left+right)/2; //中央の位置を取得
_merge_sort(a,left,mid); //左半分ソート
_merge_sort(a,mid+1,right); //右半分ソート
printf("--> %d %d %d\n",left,mid,right);
merging(a,left,mid,right); //マージ
}
}
int merge_sort(int a[], int n)
{
//作業用領域確保
if((work = calloc(n,sizeof(int))) == NULL) return -1;
_merge_sort(a,0,n-1); //マージソート呼び出し
free(work); //作業用領域解放
return 0;
}
void print_array(int a[], int n)
{
int i;
printf("[");
for(i=0; i<n; i++) printf(" %2d,",a[i]);
printf("]\n");
}
int main(void)
{
int a[N] = {21,12,8,65,22,40,34,17,7,5};
int i;
printf("Before ");
print_array(a,N);
merge_sort(a,N);
printf("After ");
print_array(a,N);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 10 //データ数
struct student_s {
int id;
char name[32];
int score;
};
typedef struct student_s Student;
void swap_student(Student *p, Student *q);
void simple_sort(Student *);
void simple_sort(Student *sp)
{
int i,j,max;
for(i=0; i<N-1; i++){
max = i;
for(j=i+1; j<N; j++){
if((sp+j)->score > (sp+max)->score)
max = j;
}
swap_student(sp+i, sp+max);
}
}
void swap_student(Student *p, Student *q)
{
int tmp;
char tmpc[32];
tmp = p->id;
p->id = q->id;
q->id = tmp;
strcpy(tmpc,p->name);
strcpy(p->name,q->name);
strcpy(q->name,tmpc);
tmp = p->score;
p->score = q->score;
q->score = tmp;
}
int main(void)
{
FILE *fp;
char filename[32] = "achievement.data";
Student *sp;
int i,j;
sp = (Student *)malloc(sizeof(Student)*N);
if((fp=fopen(filename,"r"))==NULL){
fprintf(stderr,"Can't open %s.\n",filename);
return EXIT_FAILURE;
}
printf("------ READ DATA ------\n");
for(i=0; i<N; i++){
fscanf(fp,"%d,%[^,],%d",&(sp+i)->id,(sp+i)->name,&(sp+i)->score);
printf("%d %s %d\n",(sp+i)->id,(sp+i)->name,(sp+i)->score);
}
fclose(fp);
simple_sort(sp);
printf("------ RESULT ------\n");
for(i=0; i<N; i++){
printf("%d %s %d\n",(sp+i)->id,(sp+i)->name,(sp+i)->score);
}
free(sp);
return 0;
}
今週の確認テスト テスト(PDF)
#include <stdio.h>
/*
挿入ソート(昇順)
a[]: 配列データ, n:データ数
*/
void ins_sort(int a[], int n)
{
// ここを埋める
}
/*
ソート済みデータへのデータの追加
a[]: 配列データ, n:データ数, x: 追加データ
*/
void ins_data(int a[], int n, int x)
{
//ここを埋める
}
/* 配列データの表示 */
void print_array(int a[], int n)
{
//ここを埋める
}
int main(void)
{
int data[10] = {19,7,34,78,40,65,21,83,51};
int a;
ins_sort(data,9);
printf("ソート済み:\n");
print_array(data,9);
printf("\n追加データ> ");
scanf_s("%d",&a);
ins_data(data,10,a);
print_array(data,10); //結果表示
return 0;
}
ソート済み: 7 19 21 34 40 51 65 78 83 追加データ> 68 7 19 21 34 40 51 65 68 78 83