質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

Q&A

解決済

2回答

6868閲覧

線形リストに対して二分探索をしたいのですが,リストから関数への値の渡し方が分かりません。

Cstdy_sun8

総合スコア8

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

0グッド

1クリップ

投稿2017/11/21 14:06

###前提・実現したいこと
C言語で,線形リストに対して二分探索をするプログラムを作りたいです.
リストはcsvファイルから読み込んで作成します.

###発生している問題・エラーメッセージ
リストを作成(し表示して確認も)するところまでは出来たのですが,
二分探索で使う,リストの先頭・末尾・中央の値をどうやって関数に渡したらいいのかが分からず,リストを作成しただけで作業が止まってしまいました.

###該当のソースコード

C言語

1#include <stdio.h> 2#include <malloc.h> 3#include <string.h> 4 5#define DATA_FILE "test_search.csv" 6 7typedef struct _Node { 8 int data; 9 struct _Node *next; 10} Node; 11 12Node *make_node(void); 13int make_list(void); 14int disp_list(void); 15 16Node *head; 17Node *tail; 18Node *center; 19//リストの末尾と先頭,中央 20 21 22int main(void){ 23 24 make_list();//リスト作成 25 view_list();//リスト閲覧(確認用) 26 27 return 0; 28} 29 30 31//リスト作成 32int make_list(void) 33{ 34 Node *p; 35 FILE *fp; 36 char *data_file=DATA_FILE; 37 38 if((fp=fopen(data_file,"r"))==NULL){ 39 printf("%s can not be open\n",data_file); 40 return 1; 41 } 42 head=NULL; 43 while(p=make_node(),fscanf(fp,"%d",&p->data)!=EOF){ 44 p->next=head; 45 head=p; 46 } 47 48 return 0; 49} 50 51int view_list(void)//リスト表示(確認用) 52{ 53 Node *p; 54 55 p=head; 56 printf("\n"); 57 while(p!=NULL){ 58 printf("%d\n",p->data); 59 p=p->next; 60 61 62 } 63 64 return 0; 65} 66 67 68Node *make_node(void) 69{ 70 return (Node *)malloc(sizeof(Node)); 71}

さらに,csvファイルは昇順で並んでいるのですが,このプログラムだと表示するときに降順で表示されてしまいます.何故でしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

このプログラムだと表示するときに降順で表示されてしまいます.何故でしょうか

1番目に読み込んだデータと2番目に読み込んだデータがどうつながるかといった点をよく把握しておられない気がします。紙と鉛筆でデータの繋がりを書いてみればこうなることに気づけるはずです。

head -> 2番目のデータ -> 1番目のデータ (tail)

view_listはheadからtailに向かって順に出力しているので逆順に印字されるわけです。

コードの文面を見るだけでなく、そのコードがどのようなデータ構造を生み出すかをビジュアルにイメージできるよう訓練することをお勧めします。

線形リストに対して二分探索

書けなくはないですが「線形リストは二分探索には向かない構造」であることを認識しておられるでしょうか?そうではない気がします。

二分探索を採用する条件は以下です。

(1) ソートされている(必須条件)
(2) ある範囲を決めたとき、ちょうど真ん中にあるデータに即座にアクセスできる

(2)の条件を満たすものとして思いつくのは以下の2つぐらいです。

(2-A) 配列のようなもの
ランダムアクセスできるので中央にも即座にアクセスできる。

(2-B) ニ分木のようなもの
ニ分木で任意のノードの左右にぶら下がるデータ数がほぼ一致するなら二分探索に向いています。

線形リストはランダムアクセス性がありません。また先頭や末尾は管理できたとしても中央は管理しないのが普通です。よって中央値を求めるとすれば、リストの端から順番に探すしかなく、それをするぐらいなら目的の要素を最初から線形探索したほうが自然だと思います。

投稿2017/11/21 15:16

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Cstdy_sun8

2017/11/27 13:44

回答ありがとうございました。 元々実装には向いておらず理解があやふやなままでは難しかったようです。
guest

0

さらに,csvファイルは昇順で並んでいるのですが,このプログラムだと表示するときに降順で表示されてしまいます.何故でしょうか?

headに保存した前のアドレスを新線形(構造体)のnext(次)に登録している事になり、最後のもののアドレスがheadに入ります。 (新)->(旧)

線形の部分のみのサンプルです。

c

1#include <stdio.h> 2#include <malloc.h> 3#include <string.h> 4 5#define DATA_FILE "test_search.csv" 6 7typedef struct _Node { 8 int data; 9 struct _Node *next; 10} Node; 11 12Node *make_node(void); 13int make_list(void); 14int disp_list(void); 15 16Node *head; 17Node *tail; 18Node *center; 19//リストの末尾と先頭,中央 20 21int main(void){ 22 23 make_list();//リスト作成 24 view_list();//リスト閲覧(確認用) 25 26 return 0; 27} 28 29 30//リスト作成 31int make_list(void) 32{ 33 Node *p; 34 FILE *fp; 35 char *data_file=DATA_FILE; 36 37 if((fp=fopen(data_file,"r"))==NULL){ 38 printf("%s can not be open\n",data_file); 39 return 1; 40 } 41 head=make_node(); 42 p=head; 43 while(fscanf(fp,"%d",&p->data)!=EOF){ 44 p->next=make_node(); 45 tail=p; 46 p=p->next; 47 } 48 tail->next=NULL; 49 free(p); 50 51 return 0; 52} 53 54int view_list(void)//リスト表示(確認用) 55{ 56 Node *p; 57 58 p=head; 59 printf("\n"); 60 while(p!=NULL){ 61 printf("%d\n",p->data); 62 p=p->next; 63 } 64 65 return 0; 66} 67 68 69Node *make_node(void) 70{ 71 return (Node *)malloc(sizeof(Node)); 72} 73

二分探索ですが、真ん中を見つける方法が、線形リストだと良い方法が浮かびませんでした。

投稿2017/11/21 23:02

編集2017/11/21 23:13
A.Ichi

総合スコア4070

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yohhoy

2017/11/28 08:29 編集

関連する参考情報という程度の位置づけですが:シンプルな単方向線形リストでの探索コストO(n)を緩和する「スキップリスト(skip list)」というデータ構造も存在します。計算量は二分探索のコストに近づきますが、ポインタを追加するため空間オーバーヘッドは増えてしまいます。 https://ja.wikipedia.org/wiki/%E3%82%B9%E3%82%AD%E3%83%83%E3%83%97%E3%83%AA%E3%82%B9%E3%83%88
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問