
クイックソートの比較交換回数を変数countで計算し、表示させようとしているのですがうまくいきません。
改善策を教えていただけないでしょうか。
/* クイックソート */
void quickSort(randomlist_t data[],int n){ /* 実質的な処理は何もせず、クイックソートを実際に行う関数を呼び出すのみ */
int count = 0;
quickSort_1(data,0,n-1,count);
printf("count:%d\n",count);
}
/* 実際にクイックソートを行う関数 */
void quickSort_1(randomlist_t data[],int l,int r,int count){
int v;
if(l >= r) /* 整列する要素が1つなら、何もしないでリターンする */
return;
v = partition(data,l,r,count); /* 枢軸vを基準に分割する */
quickSort_1(data,l,v-1,count); /* 左の部分の配列a[l]~a[v-1]を整列する */
quickSort_1(data,v+1,r,count); /* 右の部分の配列a[v+1]~a[r]を整列する */
}
/* 配列a[l]~a[r]を分割する。枢軸の添え字を返す */
int partition(randomlist_t data[],int l,int r,int count){
int i,j,pivot;
randomlist_t t;
i = l - 1; j = r; /* ポインタiとjを初期化する */
pivot = data[r].no; /* 一番右端の要素を枢軸にする */
for(;;){ /* ポインタiとjとがぶつかるまで繰り返す */
while(data[++i].no < pivot)
count++; /* ポインタiを右へ進める */
while(i < --j && pivot < data[j].no)
count++; /* ポインタjを左へ進める */
if(i >= j)
break; /* ポインタiとjがぶつかったらループを抜ける */
t = data[i]; data[i] = data[j], data[j] = t; /* iの指す要素とjの指す要素を交換する */
count++;
}
t = data[i]; data[i] = data[r]; data[r] = t; /* a[i]と枢軸を交換する */
count++;
return i;
}
No.2ベストアンサー
- 回答日時:
「値渡し」、聞いたこと無いですか?
Cの関数の引数は「値渡し」といって、値のコピーを作ります。
void quickSort_1(randomlist_t data[],int l,int r,int count)
と宣言した中の変数countは
quickSort_1(data,0,n-1,count);
と呼び出した変数 count のコピーでしかありません。コピーを書き換えてもオリジナルには変化はありません。
オリジナルを変えたかったら、ポインタを使ってオリジナルのアドレスを渡して、関数側でその実体にアクセスするようにします。
では、dataがなぜソートされるか、というと、Cではほとんどの場合、配列とポインタは同等に扱われます。そのため、添字を使って配列の中を操作するのは、ポインタを使って実体を操作するのと同じことになるからです。
この回答への補足
全てcountをポインタを使った表現にしてみましたが、結果は変わりませんでした…
/* クイックソート */
void quickSort(randomlist_t data[],int n){ /* 実質的な処理は何もせず、クイックソートを実際に行う関数を呼び出すのみ */
int *count = 0;
quickSort_1(data,0,n-1,*count);
printf("count:%d\n",*count);
}
/* 実際にクイックソートを行う関数 */
void quickSort_1(randomlist_t data[],int l,int r,int *count){
int v;
if(l >= r) /* 整列する要素が1つなら、何もしないでリターンする */
return;
v = partition(data,l,r,*count); /* 枢軸vを基準に分割する */
quickSort_1(data,l,v-1,*count); /* 左の部分の配列a[l]~a[v-1]を整列する */
quickSort_1(data,v+1,r,*count); /* 右の部分の配列a[v+1]~a[r]を整列する */
}
/* 配列a[l]~a[r]を分割する。枢軸の添え字を返す */
int partition(randomlist_t data[],int l,int r,int *count){
int i,j,pivot;
randomlist_t t;
i = l - 1; j = r; /* ポインタiとjを初期化する */
pivot = data[r].no; /* 一番右端の要素を枢軸にする */
for(;;){ /* ポインタiとjとがぶつかるまで繰り返す */
while(data[++i].no < pivot)
(*count)++; /* ポインタiを右へ進める */
while(i < --j && pivot < data[j].no)
(*count)++; /* ポインタjを左へ進める */
if(i >= j)
break; /* ポインタiとjがぶつかったらループを抜ける */
t = data[i]; data[i] = data[j], data[j] = t; /* iの指す要素とjの指す要素を交換する */
(*count)++;
}
t = data[i]; data[i] = data[r]; data[r] = t; /* a[i]と枢軸を交換する */
(*count)++;
return i;
}
教えていただいてありがとうございます。
説明を丁寧にしていただいたのにもかかわらず、自分の勉強不足のためにさらに説明していただくという形になって申し訳ありませんでした。
それにもかかわらず、さらに基本について分かりやすいように丁寧に説明していただけて感謝しています。
ポインタについては再度しっかり勉強し直したいと思います。
No.5
- 回答日時:
> 全てcountをポインタを使った表現にしてみましたが、結果は変わりませんでした…
変わったでしょ。「エラーになってコンパイルが通らない」っていうように。
あるいは、エラーの出る箇所が変わるとか。
patition関数の定義自体は正しいですが、それを呼び出す側が間違ってます。
int * p
と宣言したら
p はポインタで、アドレスが入っている。関数では int * で受ける。
*p は pが示す実体で int型
int c
と宣言したら
cは変数で int型。
&cはcのアドレスで、 p=&cとポインタに代入できるし、関数では int * で受ける
このあたりの対応がバラバラですよね?
何と何が対応しているとかをよく考えて使いましょう。
わからないようなら、とりあえずはグローバル変数でやってもいいですけど。
ポインタはCやる上で避けて通れないので、どこかでちゃんと勉強しましょう。
ポインタについては理解不足なので、今回はグローバル変数でやることにしました。
ポインタについてほとんど理解できていなかったのですが、この投稿によって理解が深まりました。
今後、しっかり勉強しようと思います。
ありがとうございました。
No.4
- 回答日時:
「ポインタを使った」て....
全く理解できていないポインタを無理に使おうとせず, #3 で言われるように大域変数で回避したら?
おっしゃる通りです。
全く間違ったポインタ使い方をしてしまい、お恥ずかしい限りです。
ポインタを使う前に、ポインタについて理解することに取り組みたいと思います。
全く理解していない投稿のせいで、不愉快な思いをさせてしまっていたら、本当に申し訳ありませんでした。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 10個の実数に対する降順ソート結果を出力するプログラムを作りたいのですが、以下のプログラムをどう直せ 1 2022/07/09 22:16
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- C言語・C++・C# プログラミング c言語 4 2023/03/07 01:05
- PHP PHPでCookieを使った訪問回数について 1 2023/05/28 14:10
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# C言語 3 2022/11/09 13:27
- Ruby 【JAVA】数字をひし形に出力するプログラムについて 2 2022/07/11 23:32
- C言語・C++・C# このプログラミングの問題を教えて欲しいです。 キーボードから整数kを入力し、kが配列aの中に何個存在 2 2022/12/19 22:50
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
高校1年です。情報技術基礎のシ...
-
init関数の意味
-
C言語のポインタに直接アドレス...
-
セグメントエラー
-
コンストラクタでnewを失敗した...
-
CWnd::EnableWindow()の扱い方
-
アドレスとポインタがどうして...
-
C言語の文字列?処理 strcpyやl...
-
可変長のリスト
-
C言語、配列とポインタとアスタ...
-
objective-cでの、「*」の意味
-
C#で、C言語で作ったdllに文字...
-
VB6でポインタ?
-
ポインタ引数をさらにポインタ...
-
C++ Builderでのnewコマンドに...
-
C言語のバグの警告文について
-
C#,C++/CLI,MFCにおけるデータ...
-
アプリを32bitから64bit移行
-
自作DLLの引数について、ポイン...
-
ポインタのポインタを引数にも...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語のポインタに直接アドレス...
-
fopne で失敗する原因
-
戻り値で構造体を返すことは可...
-
LPSTR型の初期化について
-
Run-Time Check Failure #3とい...
-
ExcelVBAでのkernel32(64bit)
-
参照型で受け取った引数をポイ...
-
init関数の意味
-
セグメントエラー
-
アプリを32bitから64bit移行
-
ハンドルはポインタか
-
ハンドル、アドレス、ポインタ...
-
C言語でのconstを返す関数
-
C++で関数ポインタから関数名を...
-
パスからファイル名を抽出
-
ReadFileの読み込みエラーについて
-
#define NULL ((void *)0) の弊害
-
CImage GetBitsメソッドについて
-
ポインタ変数の疑問
-
Cで作成したDLL関数をVBから呼...
おすすめ情報