|
任意の配列を対象とするマージソート関数を書いてみました。ご参考にどうぞ。
学校の課題のようですから詳しい解説はしません。悪しからず。
また、バグがないことを保証するものでもありません(バグの指摘などのツッコミは歓迎します)。
# ウェブ上でこの課題に関する質問を見るのは3〜4回目です。
# 先生に指導を仰ぐか、すでに仕上げた同級生に尋ねる方が早く解決すると思うのですが、
# いかがなもんでしょう > この課題の質問者の'みなさん'
// ■マージソート関数の実装例:
#include <stdlib.h>
#include <memory.h>
void merge_sort( void* beg, void* end, size_t sz, int(*cmp)( const void*, const void* ) )
{
size_t diff = ( (char*)end - (char*)beg ) / sz;
if( diff > 2 ){
char* mid;
char* seq;
char* pos;
char* it1;
char* it2;
mid = (char*)beg + diff / 2 * sz;
merge_sort( beg, mid, sz, cmp );
merge_sort( mid, end, sz, cmp );
pos = seq = malloc( (char*)end - (char*)beg );
for( it1 = beg, it2 = mid; it1 != mid || it2 != end; pos += sz ){
if( it1 == mid ){
memcpy( pos, it2, sz );
it2 += sz;
}
else if( it2 == end || cmp( it1, it2 ) <= 0 ){
memcpy( pos, it1, sz );
it1 += sz;
}
else{
memcpy( pos, it2, sz );
it2 += sz;
}
}
memcpy( beg, seq, (char*)end - (char*)beg );
free( seq );
}
else if( diff == 2 ){
void* tmp = malloc( sz );
void* it1 = beg;
void* it2 = (char*)beg + sz;
if( cmp( it1, it2 ) > 0 ){
memcpy( tmp, it1, sz );
memcpy( it1, it2, sz );
memcpy( it2, tmp, sz );
}
free( tmp );
}
}
// ■merge_sortを使ったサンプルプログラム:
#include <stdio.h>
#include <string.h>
#define MAX_LENGTH 80
struct recordL{
char str[ MAX_LENGTH + 1 ];
struct recordL* next;
};
int record_length_cmp( const struct recordL* lhs, const struct recordL* rhs );
void sort_records( struct recordL* top, int (*cmp)( const struct recordL*, const struct recordL* ) );
int main( void )
{
struct recordL* top = NULL;
struct recordL* pos;
struct recordL* tmp;
char buff[ MAX_LENGTH + 1 ];
int a;
while( ( a = getc( stdin ) ) != EOF ){
// 1行読み込み(最大80文字)
int i = 0;
if( a != '\n' ){
for( ; i < MAX_LENGTH && a != '\n' && a != EOF; a = getc( stdin ) ){
buff[ i++ ] = a;
}
for( ; a != '\n' && a!= EOF; a = getc( stdin ) ){
;
}
}
buff[i] = '\0';
// レコードデータの作成とリストへの追加
tmp = (struct recordL*)malloc( sizeof( struct recordL ) );
strcpy( tmp->str, buff );
tmp->next = NULL;
if( top == NULL ){
top = pos = tmp;
}
else{
pos = pos->next = tmp;
}
}
// 文字数の昇順でソート
sort_records( top, &record_length_cmp );
// 結果出力
for( pos = top; pos != NULL; pos = pos->next ){
if( strlen( pos->str ) > 0 ){
printf( "%s\n", pos->str );
}
}
// リストの解体(メモリ解放)
for( pos = top; pos != NULL; ){
tmp = pos;
pos = pos->next;
free( tmp );
}
return 0;
}
int record_length_cmp( const struct recordL* lhs, const struct recordL* rhs )
{
unsigned lhs_len = strlen( lhs->str );
unsigned rhs_len = strlen( rhs->str );
if( lhs_len < rhs_len ){
return -1;
}
else if( lhs_len == rhs_len ){
return 0;
}
else{
return 1;
}
}
void sort_records( struct recordL* top, int (*cmp)( const struct recordL*, const struct recordL* ) )
{
struct recordL* rec;
struct recordL* pos;
int size, i;
for( size = 0, pos = top; pos != NULL; pos = pos->next ){
size++;
}
rec = (struct recordL*)malloc( sizeof( struct recordL ) * size );
for( i = 0, pos = top; i < size; i++, pos = pos->next ){
strcpy( rec[i].str, pos->str ); // from list to array
}
merge_sort( rec, rec + size, sizeof( struct recordL ), (int(*)( const void*, const void* ))cmp );
for( i = 0, pos = top; i < size; i++, pos = pos->next ){
strcpy( pos->str, rec[i].str ); // from array to list
}
free( rec );
}
|