• ベストアンサー

(構造体)双方向連結リストの作成!

ダミーノードを先頭に、双方向連結リストを作成したいのですがなかなかうまくできません。とりあえず、ダミーノード無しのものはなんとか出来ましたが、循環連結がうまくいっていない次第です。 どうかお力添え願います。 #include<stdio.h> #include<malloc.h> #include<process.h> typedef struct node{ struct node *left; char name[20]; int age; struct node *right; }NODE; NODE *memalloc(void); void main(void) { NODE *head, *tail, *p; tail = NULL; while(p = memalloc(), printf("名前 年齢入力(Ctrl + Zで終了)>"), scanf("%s %d", p -> name, &p -> age) != EOF){ p -> left = tail; tail = p; } p = tail; head = NULL; while(p != NULL){ p -> right = head; head = p; p = p -> left; } head -> left = tail; p = head; printf("リスト表示\n"); while(p != NULL){ printf("名前:%20s 年齢:%5d\n", p -> name, p -> age); p = p -> right; } } NODE *memalloc(void) { NODE *ptr; if((ptr = (NODE *)malloc(sizeof(NODE))) != NULL){ return ptr; } printf("\n動的メモリ割当に失敗しました。\n"); exit(1); return 0; }

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

No.1だとまったく入力がない時(いきなりCtrl+Zを入力した時)にheadが未定義、tailがNULLのままループ終了してしまうのでまずいですね。 参考まで、ダミーノード付きのプログラム(領域開放と入力文字数も考慮)を書いておきます。 #include<stdio.h> #include<stdlib.h> typedef struct node{ struct node *left; char name[20]; int age; struct node *right; }NODE; NODE *memalloc(void); void memfree(NODE *); int main(void) { NODE *head, *tail, *p; char buf[80]; /* 1行入力用 */ /* ダミー作成 */ if ((p = memalloc())==NULL) exit(1); head = tail = p->left = p->right = p; /* ノード入力 */ while(printf("名前 年齢入力(Ctrl + Zで終了)>"), fgets(buf, sizeof(buf), stdin) != NULL) { if ((p = memalloc())==NULL) { memfree(head); exit(1);} if (sscanf(buf,"%19s%5d", p->name, &p->age) != 2) { free(p); break;} tail -> right = p; p -> left = tail; /* pをtailとつなぐ */ head -> left = p; p -> right = head; /* pをheadとつなぐ */ tail = p; /* pは次のtail */ } /* 右回りに表示 */ p = head -> right; printf("リスト表示(右回り)\n"); while (p != head) { printf("名前:%20s 年齢:%5d\n", p -> name, p -> age); p = p -> right; } /* 領域開放 */ memfree(head); return 0; } /* メモリ領域を確保する */ NODE *memalloc(void) { NODE *ptr; if((ptr = (NODE *)malloc(sizeof(NODE))) == NULL){ printf("\n動的メモリ割当に失敗しました。\n"); } return ptr; } /* 確保したメモリ領域を開放する */ void memfree(NODE *head) { NODE *p, *pp; p = head->right; while ( p != head) { pp = p->right; /* 次のノードを一時的に保存 */ free(p); p = pp; } free(p); /* ダミーを開放 */ }

yukikundesuyo
質問者

お礼

メモリの解放のメソッドまで作成して頂いてありがとうございます。No1の方は不都合があるようなのでこちらを優先して参考させてもらいます。

その他の回答 (1)

  • kmb01
  • ベストアンサー率45% (63/138)
回答No.1

ノードを追加するごとに正しくleftとrightを設定すればいい。 こんな感じだと思う。 void main(void) { NODE *head, *tail, *p; tail = NULL; while(p = memalloc(), printf("名前 年齢入力(Ctrl + Zで終了)>"), scanf("%s %d", p -> name, &p -> age) != EOF){ if (tail == NULL) { p->left = p->right = p; // 最初に作成したノードをheadにする。 head = tail = p; } else { // どんどん右に追加していく。新規ノードのleftはtailを指し、tailのrightは新規ノードを指す。 p->left = tail; tail->right=p; // tailを更新 tail = p; } } // headとtailをつなげて循環参照にする tail->right = head; head->left = tail; printf("リスト表示\n"); if (head) { p = head; do { printf("名前:%20s 年齢:%5d\n", p -> name, p -> age); p = p -> right; }while(p != head); } }

yukikundesuyo
質問者

お礼

ありがとうございます。 なんとか考えて、一応自分で完成にこぎつけることができました。

関連するQ&A

  • (構造体)ループ条件のscanf文が処理されない!?

    ループのscanf文を入力していないのに勝手にループの中に入って処理をしています。なぜでしょうか? #include<stdio.h> #include<malloc.h> #include<process.h> typedef struct node{ struct node *left; char name[20]; int age; struct node *right; }NODE; NODE *memalloc(void); void main(void) { NODE *head, *p, *old; /*ダミーノード作成*/ p = memalloc(); head = p; p -> left = p; p -> right = p; old = head; p = memalloc(); printf("名前 年齢入力 >"); scanf("%s, %d", p -> name, &p -> age); old -> left = p; old -> right = p; p -> left = old; p -> right = old; while(p = memalloc(), old = p, printf("名前 年齢入力 >"), scanf("%s, %d", p -> name, &p -> age) != EOF){ printf("確認\n"); old -> right = p; p -> left = old; head -> left = p; p -> right = head; } p = head -> right; while(head -> left != p -> right){ printf("名前:%20s 年齢:%5d\n", p -> name, p -> age); p = p -> right; } } NODE *memalloc(void) { NODE *ptr; if((ptr = (NODE *)malloc(sizeof(NODE))) != NULL){ return ptr; } printf("\n動的メモリ割当に失敗しました。\n"); exit(1); return(0); }

  • リストの削除について(構造体)

    リストの削除のプログラムを実行して行ってみると、リストの削除処理中にプログラムが終わって変更後処理がうまく表示されません。どこが間違っているかが分からないしだいです。返答のほどよろしくお願いいたします。 #include<stdio.h> #include<malloc.h> #include<string.h> struct list{ char name[20]; int age; struct list *next; }; void main(void) { struct list *head, *p, *n, *old; char key[20]; /*ダミーノード作成*/ head = (struct list*)malloc(sizeof(struct list)); old = head; while(p = (struct list*)malloc(sizeof(struct list)), printf("name age入力\n"), scanf("%s %d", p -> name, &p -> age) != EOF){ old -> next = p; old = p; } free(p); old -> next = NULL; p = head -> next; printf("変更前リスト\n"); while(p != NULL){ printf("name:%s age:%d\n",p -> name, p -> age); p = p -> next; } printf("削除key入力(name)\n"); gets(key); n = head; while(n != NULL){ old = n; n = n -> next; //printf("n -> name %s\n", n -> name); if(strcmp(n -> name, key) == 0){ printf("%s削除\n", key); //printf("n -> name %s old -> name %s\n", n -> name, old -> name); old -> next = n -> next; } } p = head -> next; printf("変更後リスト\n"); while(p != NULL){ printf("name:%s age:%d\n", p -> name, p -> age); p = p -> next; } }

  • list構造。。。

    リストの末尾にデータを追加すると、最後に追加したデータで今までのリストのデータが上書きされてしまいます。。 以下に、ソースを掲載させていただきます。 void SetNode(List* node_first, List* node_second, int *data) { node_first->move = data; node_first->next = node_second; return ; } /*末尾に挿入*/ void Insert_Tail(List **head, int* data) { List *ptr = *head; if(ptr == NULL){ *head = (List*)calloc(1,sizeof(List)); SetNode(*head, NULL, data); return ; }else{ while(ptr->next != NULL){ ptr = ptr->next; } ptr->next = (List*)calloc(1,sizeof(List)); SetNode(ptr->next, NULL, data); } return ; } void show_list(List *list) { List *ptr = list; while(ptr != NULL){ printf("%d\n",*(ptr->move)); ptr = ptr->next; } return ; } int main(int argc, char** argv) { /*宣言*/ Node* root; /**/ List* top; /* 手順のリスト */ int judge; top = NULL; do{ printf("num:"); scanf("%d",&judge); switch(judge){ case 1: /*データを末尾に追加*/ printf("mem:"); scanf("%d",mem); root->board = mem; Insert_Tail(&top, root->board); break; case 2: /*リストを頭から表示*/ show_list(top); break; default: break; } }while(judge != 0); return 0; } 自分は最後のリストまでたどって、callocしたつもりなのですが、どうもそうではないようで、困っています。 どうか、御指導の程、お願いします。

  • List構造

    Listの尻にノードを追加する関数で困っています。 以下に、ソースの一部を掲載させていただきます。 typedef struct __node{ int data; struct __node *next; }Node; ... /*リストの尻にノードを追加する関数 * 引数: head. リストの先頭ノードのポインタ data. リストの尻に追加したいint型の変数*/ void Insert_Tail(Node *head, int data) { Node *ptr = head; if(ptr == NULL){ /*<ノードが存在しない時には追加されない>*/ /*領域の確保*/      head = (Node*)calloc(1,sizeof(Node)); /*データをセット*/ head->data = data; head->next = NULL; return ; }else{ /*<ノードが存在するときには正常に動作>*/ while(ptr->next != NULL){ ptr = ptr->next; } /*領域の確保*/ ptr->next = (Node*)calloc(1,sizeof(Node));      /*データのセット*/ ptr->next->data = data; ptr->next->next = NULL; } } コメントアウトにも書かせていただきましたが、ノードがすでに存在するときには、正常にノードの最後に追加してくれるのですが、ノードが存在しない時にはリストに追加してくれません。 どうかご指導、ご指摘の程お願いします。

  • アルゴリズム 線形リスト

    最近リストについて習い始めました。入力したデータと同順に並ぶリストを作成しようと思い、コードを打ったのですが…動作中止の表示がでてしまいました。どこが間違っているのか、ずっと悪戦苦闘して組んでいるのですが、全く出口が見えてきません。何が間違えているのか、はたまた根本的に違うのか、ご指導して頂けると有難いです。 以下、コードです。 #include <stdio.h> #include <stdlib.h> #include <string.h> struct hito{ char name[20]; int age; struct hito *next; }; void main(void){ struct hito *p, *head, *dummy; char new_name[20]; int new_age; dummy = (struct hito *)malloc(sizeof(struct hito)); head = dummy; dummy->next = p; dummy = p; while (scanf("%s %d" , new_name, &new_age) != EOF) { p = (struct hito *)malloc(sizeof(struct hito)); strcpy(p->name, new_name); p->age = new_age; p->next = head; head = p; } while(p != NULL) { printf("\t%-20s %3d\n" , p->name, p->age); p = p->next; } }

  • 双方向リストのバブルソートについて

    双方向リストをバブルソートを用いてソートしたいです。 下記がプログラム(一部)ですが、ソートした後にリスト表示すると 無限ループに陥ります。 どこがいけないのでしょうか。 #include <stdio.h> #include <stdlib.h> struct cell{ int data; struct cell *next, *prev; }; void insert_head(struct cell **head, int num){ struct cell *p, *p1; p = *head; p1 = make_cell(); *head = p1; p1->data = num; p1->next = p; if(p1->next != (struct cell *)NULL){ p1->next = p; p->prev = p1; } } void print_list(struct cell *head){ struct cell *p; p = head; printf("data = \n"); while(p != (struct cell *)NULL){ printf("%d\n", p->data); p = p->next; } } void sort_list(struct cell **head){ struct cell *p, *p2; int i, n; n = 0; p = *head; while(p->next != (struct cell *)NULL){ p = p->next; n++; } for(i = 0, p = *head; i < n-2; i++){ if(p->data > p->next->data){ if(p == *head){ *head = p->next; }else{ p->prev->next = p->next; } p2 = p->next; p->next = p->next->next; p->next->next = p; p->next->next->prev = p; p->next->prev = p->prev; p->prev = p2; }else p = p->next; } } int main(void){ struct cell *head = (struct cell *)NULL; int n; while(1){ printf("1:Insert head 2:Insert tail 3:Delete 4:List 5:Sort 6:Exit\n"); scanf("%d", &n); switch(n){ case 1: printf("num = "); scanf("%d", &n); insert_head(&head, n); break; case 2: printf("num = "); scanf("%d", &n); insert_tail(&head, n); break; case 3: printf("num = "); scanf("%d", &n); delete_cell(&head, n); break; case 4: print_list(head); break; case 5: sort_list(&head); break; case 6: return 0; break; } } }

  • C言語 リスト

    (1) /* list.c */ #include <stdio.h> #include <stdlib.h> struct node { int num; struct node *next; }; main() { struct node *head, *p; int x; head = NULL; while(scanf("%d",&x) != EOF) { p = (struct node *)malloc(sizeof(struct node)); p->num = x; p->next = head; head = p; } // リストの要素のnumの値を先頭から順に表示する p=head; while(p!=NULL) { printf("%d\n" ,p->num); p = p->next; } } (2) struct node *q; q = head; while(q->next != NULL) q = q->next; (1)を(2)を使い新しいノードをリストの最後に追加するようにしたいのですが どう書いたら良いのか教えていただきたいです

  • 連結リストによるデータ管理プログラムの解説

    ★から★までのプログラムが、各行ごとにどのような動きをしているのか簡潔な言葉で説明を書いていただきたいのです。必要がないと判断した行はとばして下さって構いません。 (例) printf("hello!"); …hello!と表示 if(a==0){ …aが0なら #include <stdio.h> #include <stdlib.h> struct CELL{ struct CELL *next; char data; }; /* Head CELL CELL CELL +-------+ +-------+ +-------+ +-------+ | ? | *----> | 5 | *----> | 6 | *----> | 8 | / | +-------+ +-------+ +-------+ +-------+ */ main(void){★ struct CELL head; struct CELL *p, *wp; char a; head.next=NULL; printf("?\n"); scanf("%c %*c",&a); while(a!='0'){ printf("mode?\n"); scanf("%c",&mode); if(mode=="a"){ p=&head; while(p->next!=NULL){ p=p->next; } wp=(struct CELL *)malloc(sizeof(struct CELL)); if(wp==NULL){ printf("cannot allocate enough memory.\n"); return 0; } p->next=wp; p->next->data=a; p->next->next=NULL; printf("?\n"); scanf("%c %*c",&a); } if(mode=="p"){ printf("\n\nNow...\n"); p=&head; while(p->next!=NULL){ printf("%c --> \n",p->next->data); p=p->next; } printf("NULL\n"); if(mode=="d"){ p=&head; while(p->next->data==a){ p=p->next; } if(p==NULL) break; wp=p->next->next; while(p->next->data==a) p=wp;★ } } return 0; }

  • 解析木

    ノードの中身を表示しながらトラバースする関数 void preorder(NodePointer node); void inorder(NodePointer node); void postorder(NodePointer node); を再帰を使って書きなさい。 という問題がとけません。どなたかアドバイスをください。 ちなみに、この関数以外は下のように作りました。 #include <stdio.h> #include <stdlib.h> struct node { struct node *right; char key; struct node *left; }; typedef struct node * NodePointer; void treeinitialize(void); NodePointer makenode(char c); void preorder(NodePointer node); void inorder(NodePointer node); void postorder(NodePointer node); NodePointer head, tail; int main(){ treeinitialize(); //テスト用の木を作成 head->right=makenode('+'); head->right->left=makenode('1'); head->right->right=makenode('*'); head->right->right->left=makenode('2'); head->right->right->right=makenode('3'); //トラバース printf("preorder: "); preorder(head->right); printf("\n"); printf("inorder: "); inorder(head->right); printf("\n"); printf("postorder: "); postorder(head->right); printf("\n"); return 0; } void treeinitialize(void){ head=makenode(-1); tail=makenode(-1); head->right=tail; head->left=tail; } //ノードを作成し、そのノードへのポインタを返す。 NodePointer makenode(char c){ NodePointer x; x=malloc(sizeof(struct node)); x->key=c; x->right=tail; x->left=tail; return x; } void preorder(NodePointer node){ } void inorder(NodePointer node){ } void postorder(NodePointer node){ }

  • 双方向リストのプログラミングのチェック

    指定したファイルを読み込み、一行ずつ構造体に保存し、表示させる。その後、キーボードから指定した行を削除し、処理後の結果を表示させる・・・といったプログラミングを作成しています。 通常の表示の部分はできましたが、後は指定した行の削除の部分ができません。 あらかじめHPで調べてあるので、削除するときは、その削除したい行をまたいで、前後のリストを繋げるといった概念的なのは大体理解できました。 自分なりに考えたり調べて、下のように打ちました。 ですが、キーボードから入力した値をどう関数に対応させていくのか、 delete_head,delete_tailの関数の部分に出る、head,tailは使えない的なエラーの対処の仕方がわからなく、詰まってます。 アドバイス、他にも直す場所等ありましたらお願いします。 #include<stdio.h> #include<stdlib.h> #define LINE 1000 typedef struct num{ char line[LINE]; struct num *next; struct num *prev; }Num; void normal(Num **,Num **,char *); void reverse(Num *,Num *,char *); void delete_head(void); void delete_tail(void); void delete(Num *target); int main(int argc,char *argv[]) { FILE *fp; char line[LINE]; int i=0,j; Num *head,*tail,*p; head=NULL; tail=NULL; fp=fopen("test.txt","r"); if(fp==NULL){ fprintf(stdout,"File not found.\n"); exit(1); } while(fgets(line,LINE,fp)!=NULL) { normal(&head,&tail,line); } p=head; while(p!=tail){ printf("%s\n",p->line); p=p->next; } printf("%s\n",p->line); p=tail; while(p!=head){ printf("%s\n",p->line); p=p->prev; } printf("%s\n",p->line); printf("input number\n"); scanf("%d",&j); p=head; for(i=0;i<=j;i++);{ p=p->next; } if(p==head){ delete_head(void); } else if(p==tail){ delete_tail(void); } else{ delete(p->prev); } p=head; while(p!=tail){ printf("%s\n",p->line); p=p->next; } printf("%s\n",p->line); fclose(fp); return 0; } void normal(Num **s,Num **e,char *g){ Num *tmp; int i; if(*s==NULL){ *s=(Num *)malloc(sizeof(Num)*1); (*e)=(*s); for(i=0;((g[i]!='\0')&&(g[i]!='\n'));i++){ (*s)->line[i]=g[i];} (*s)->next=*e; (*s)->prev=*s; } else{ tmp=(Num *)malloc(sizeof(Num)*1); for(i=0;((g[i]!='\0')&&(g[i]!='\n'));i++){ tmp->line[i]=g[i];} tmp->prev=(*e); (*e)->next=tmp; tmp->next=(*e); (*e)=tmp; } return ; } void reverse(Num *kan1,Num *kan2,char *g){ Num *tmp; int i; tmp=(Num *)malloc(sizeof(Num)*1); for(i=0;((g[i]!='\0')&&(g[i]!='\n'));i++){ tmp->line[i]=g[i];} tmp->prev=kan1; kan1->next=tmp; tmp->next=kan2; kan2->prev=tmp; return ; } void delete_head(void){ Num *second=head->next; if(secound==NULL){ free(head); head=NULL; tail=NULL; } else{ second->prev=NULL; free(head); head=second; } } void delete_tail(void){ Num *second_last=head->prev; if(second_last==NULL){ free(tail); head=NULL; tail=NULL; } else{ second_last->next=NULL; free(tail); tail=second_last; } } void delete(Num *target){ Num *after_target; Num *before_target; after_target=target->next; before_target=target->prev; after_target->prev=target->prev; before_target->next=target->next; free(target); }