C言語関係掲示板

過去ログ

No.511.線形リスト

[戻る] [ホームページ]
No.3939

線形リスト
投稿者---ピンチな人(2002/12/18 02:14:05)


下の問題ですが全く見当が付きません。助けてください。

線形リストを用いて、以下の動作ができるように。
1)入力した要素をリストの先頭に追加
2)入力した要素をリストの末尾に追加
3)入力した要素を昇順に整列したリストに追加
4)入力した要素を降順に整列したリストに追加
5)リストの先頭要素を取り出し
6)リストの末尾要素を取り出し
7)リストを空にする
8)リストの表示
9)終了

注意
・必ず自己参照的構造体によるリストを用いる。(配列等では不可)
・1)〜8)はそれぞれ独立の関数として実装する。
・3)4)は、すでに整列済みのリストに対して用いた時のみ意味を持つ。
・空のリストからさらに取り出そうとした時は-1を返し、処理を続行する。
・5)〜7)で使用を終えたメモリは必ず解放する。
・大域変数は使わない。


No.3971

Re:線形リスト
投稿者---かずま(2002/12/20 19:38:41)


> 問題の丸投げに解答するのはあまり好ましくないかなと思いますが?
> ある程度ご自分で出来る所までやってみませんか?

質問者に対しては好ましくないかもしれませんが、この掲示板を読んでいる他の
人たちにとっては、プログラミングの参考になっていいんじゃないでしょうか。


> これだけしっかり”仕様書”が出ているのですから。

要素が何か(数値か文字列か、...)はっきりしませんが。


>> 線形リストを用いて、以下の動作ができるように。
>> 1)入力した要素をリストの先頭に追加
>> 2)入力した要素をリストの末尾に追加
>> 3)入力した要素を昇順に整列したリストに追加
>> 4)入力した要素を降順に整列したリストに追加
>> 5)リストの先頭要素を取り出し
>> 6)リストの末尾要素を取り出し
>> 7)リストを空にする
>> 8)リストの表示
>> 9)終了

>  ただ5)6)8)に関しては順不同のリストに対して行うものなのかソート済み
> のリストに対して行うものなのかあるいは両方かははっきりしませんね。

3)と 4)がソート済みのリストに対して行うこと以外は、何でもいいんじゃ
ないでしょうか。


>>・5)〜7)で使用を終えたメモリは必ず解放する。

> 開放しちゃったら他の”追加”の問題が出来なくなっちゃうしな。
> 変なの。

5)と 6) で取り出したものは捨てるというだけで、リストの残りの要素に対して
追加も削除もできるのではありませんか。

#include <stdio.h>
#include <stdlib.h>

typedef struct Node Node;
struct Node {
    int  data;
    Node *next;
};

void *Malloc(size_t n)
{
    void *p = malloc(n);
    if (p == 0) puts("out of memory"), exit(1);
    return p;
}

void push_front(Node **head, int data)
{
    Node *np = Malloc(sizeof(Node));
    np->data = data;
    np->next = *head;
    *head = np;
}

void push_back(Node **head, int data)
{
    Node *p, *np = Malloc(sizeof(Node));
    np->data = data;
    np->next = NULL;
    if (*head == NULL)
        *head = np; 
    else {
        for (p = *head; p->next; p = p->next)
            ;
        p->next = np;
    }
}

void add_a(Node **head, int data)
{
    Node *p, *np = Malloc(sizeof(Node));
    np->data = data;
    if (*head == NULL || data <= (*head)->data) {
        np->next = *head; *head = np; return;
    }
    for (p = *head; p->next && data > p->next->data; p = p->next)
        ;
    np->next = p->next;
    p->next = np;
}

void add_d(Node **head, int data)
{
    Node *p, *np = Malloc(sizeof(Node));
    np->data = data;
    if (*head == NULL || data >= (*head)->data) {    
        np->next = *head; *head = np; return;
    }
    for (p = *head; p->next && data < p->next->data; p = p->next)
        ;
    np->next = p->next;
    p->next = np;
}

int pop_front(Node **head)
{
    Node *p;
    if (*head == NULL) return -1;
    p = *head;
    *head = (*head)->next;
    free(p);
    return 0;
}

int pop_back(Node **head)
{
    Node *p;
    if (*head == NULL) return -1;
    if ((*head)->next == NULL) {
        free(*head); *head = NULL; return 0;
    }
    for (p = *head; p->next->next; p = p->next)
        ;
    free(p->next);
    p->next = NULL;
    return 0;
}

void clear(Node **head)
{
    Node *p = *head;
    while (p) { Node *t = p; p = p->next; free(t); }
    *head = NULL;
}

void display(Node **head)
{
    Node *p;
    for (p = *head; p; p = p->next) printf(" %d", p->data);
    printf("\n");
}

int main()
{
    Node *head = NULL;  int command, data;

    for (;;) {
        puts("1:先頭, 2:末尾, 3:昇順, 4:降順, 5:頭削, 6:尾削, "
            "7:空, 8:表示, 9:終了, 0:ヘルプ");
        for (;;) {
            if (scanf("%d%*c", &command) != 1) return 1;
            switch (command) {
            case 1: if (scanf("%d%*c", &data) != 1) return 1;
                    push_front(&head, data); continue;
            case 2: if (scanf("%d%*c", &data) != 1) return 1;
                    push_back(&head, data); continue;
            case 3: if (scanf("%d%*c", &data) != 1) return 1;
                    add_a(&head, data); continue;
            case 4: if (scanf("%d%*c", &data) != 1) return 1;
                    add_d(&head, data); continue;
            case 5: if (pop_front(&head) < 0) puts("empty"); continue;
            case 6: if (pop_back(&head) < 0) puts("empty"); continue;
            case 7: clear(&head); continue;
            case 8: display(&head); continue;
            case 9: return 0;
            default: break;
            }
            break;
        }
    }
}
【実行結果】
1:先頭, 2:末尾, 3:昇順, 4:降順, 5:頭削, 6:尾削, 7:空, 8:表示, 9:終了, 0:ヘルプ
1 11; 1 22; 1 33; 1 44; 8
 44 33 22 11
2 55; 2 66; 2 77; 8
 44 33 22 11 55 66 77
5; 8
 33 22 11 55 66 77
6; 8
 33 22 11 55 66
7; 8

3 88; 3 55; 3 99; 3 11; 8
 11 55 88 99
7
4 88; 4 55; 4 99; 4 11; 8
 99 88 55 11
9