アプリ版:「スタンプのみでお礼する」機能のリリースについて

2つの線形リストから交互に先頭の要素を外して新しいリストに繋ぎかえる操作を考える。
プログラム全体の動作は以下のようにする。まず端末から要素数を入力すると、プログラム内で 101 から昇順に数が並んだ線形リストを作る。それを半分の長さで分割し list1, list2 という2つのリス トに分け、確認のため要素の並びを表示する。続いて、各リストからそれぞれ先頭の要素を外して新し いリストに繋ぐことを繰り返して、元の要素が交互に並んだリストを作成し、要素の並びを表示する。
関数 list_len は引数で与えられたリストの要素数を返す。
関数 list_show はリスト中の要素の並びを表示する。
関数 add_top は第一引数で指定されたリストの先頭にノード(第二引数で指定された値を持つ)を追
加し、追加後のリストを返す。
関数 divide は与えられたリストを、先頭から指定個数の要素を持つ前半と、残りの要素からなる後
半に分割し、後半のリストを返す。以下の方針で作成せよ。
・空のリストには空を返す。 ・分割位置が1なら、先頭の一要素のみのリストとそれ以降のリストに分割し、後者のリストを返す。 ・位置が1より大きい場合は、先頭要素を外したリストについて、位置を1減らし divide を再帰的に
呼び出す。
・なお引数で指定される分割位置は1以上としてよい。
関数 merge は、再帰的に2つのリストから要素を交互に取って合体させたリストを作成し、出来たリ ストを返す。以下の方針で作成せよ。
・引数で与えられた2つのリストの片方が空なら、他方のリストを返す。 ・そうでなければ(どちらにも1つ以上の要素があるので)、それぞれの先頭要素を外して繋ぎ、その
後ろに残りを merge したものを再帰的に繋ぐ。この関数が merge(a,b)と呼ばれたら、 a が先頭の一要素 ah と残りのリスト at(要素数ゼロの NULL もあり得る)に分割でき、b も bh と bt に分割できるとして、ah の後ろ に bh を繋ぎ、その後ろに at と bt を merge したものを繋いだリストを作って返せばよい。
問題:関数 divide (分割)、関数 merge を完成させよ。ソースコードと、入力として 11 と 12 を与えた2通りの実行結果を提出せよ
#include <stdio.h>
#include <stdlib.h>

struct node {
int val;
struct node *next;
};
typedef struct node *LIST;
LIST divide(LIST x, int p) ;
LIST merge(LIST x, LIST y) ;

int list_len(LIST x) {//リストの要素数を求める関数
if (x == NULL) return 0;
return 1 + list_len(x->next);
}
void list_show(char *m, LIST x) {//リストにある値を表示する関数
printf("%s:", m);
while (x != NULL) {
printf("%d ", x->val);
x = x->next;
}
printf("\n");
}
LIST add_top(LIST x, int v) {//リストxの先頭に、値vを繋げたリストを返す関数
LIST t;
t = (LIST) malloc(sizeof(struct node));
if (t == NULL) {
printf("malloc failed");
exit(-1);
}
t->val = v;
t->next = x;
return t;
}
int main(void) {
int i, len;
LIST list1 = NULL, list2, mix;
printf("length: ");fflush(stdout);
scanf("%d", &len);
for (i = len; i >= 1; i--)
list1 = add_top(list1, 100+i);
list2 = divide(list1, list_len(list1) / 2);
list_show("list1", list1);
list_show("list2", list2);
mix = merge(list2, list1);
list_show("mixed", mix);
return 0;
}

LIST divide(LIST x, int p) {//長さp でリストを分割する関数
//// ここを完成させる
}
LIST merge(LIST x, LIST y) {//二つのリストをマージする関数
//// ここを完成させる
}
divide関数のところには
for(p=0;p>1;p--)
if(x=NULL){
return 0;
}else if(p==1){
return x=x->next;


marge関数のところを教えていただきたいです。またdivide関数のところも不備があれば教えて教えていただきたいです。

A 回答 (3件)

あ、返すもんが違った。


merge(,) の最終行
return dummy->next; に修正して。

ついでに、リストを分けるとこ
LIST split(LIST x) {
LIST y, ynext;
int n = 0;
for( y = x; x != NULL; x = x->next )
if( n++ & 1 ) y = y->nex;
ynext = y->next;
y->next = NULL;
return ynext;
}
    • good
    • 0

marge関数のところ


ここも普通、再起は使わないでしょ。
LIST merge(LIST x, LIST y) {
struct node dummy;
LIST ztail = &dymmy, xrest;
while( x != NULL ) {
ztail->next = x;
xrest = x->next;
// x->next = NULL;
x = y;
y = xrest;
}
ztail->next = y;
return &dummy;
}
    • good
    • 0

divide関数のところ


for(p=0;p>1;p--) では、引数の p 回じゃなく
INT_MAX 回ループすることになる。
それにしても、なぜここで再起を使おうと思ったのだろう?
出題者は LISP 出身なのだろうか。
    • good
    • 0
この回答へのお礼

ありがとうございます!

お礼日時:2022/12/22 10:39

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!