2009/03/25 [長年日記 ]

キュー&スタック

会社でのC言語研修の問題として、定番だけどキュー&スタックを考えた。
キューとスタックはよく似ていて、違うのはデータの取出す順序が先に入れたものから取出す(キュー)のか、後から入れたものから取出す(スタック)ぐらい。
そこで、キューとスタックをまとめてあつかえるプログラムを作ってみた。きちんとエラー処理はしていないので、もし使うのであれば、その辺はきちんと作る必要がある。

《que.h》


#ifndef _QUE_H_
#define _QUE_H_

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

#define         GET_QUE         1
#define         GET_STACK       0

/* structuers   */
typedef struct que {
struct  que     *prev;
struct  que     *next;
        void    *data;
} QUE;

/* function prototype   */
int     que_init();
int     que_enque(void *data);
int     que_deque_first(void **data);
int     que_deque_last(void **data);

#endif  /* _QUE_H_      */

《que.c》


#include        "que.h"

static  QUE     root;

static  int     que_deque(void **data, int get_type);

int     que_init()
{
        memset (&root, 0, sizeof(root));
        root.prev = &root;
        root.next = &root;

        return(0);
}

int     que_enque(void *data)
{
        QUE     *p      = NULL;
        QUE     *last   = NULL;

        p = (QUE *) malloc (sizeof(QUE));

        if (root.next == &root || root.prev == &root) {
                root.next = p;
                root.prev = p;
                p->prev = &root;
        } else {
                last = root.prev;
                last->next = p;
                root.prev = p;
                p->prev = last;
        }

        p->next = &root;
        p->data = data;

        return(0);
}

int     que_deque_first(void **data)
{
        int     status;

        if (root.next == &root) {
                return(1);
        }

        status = que_deque(data, GET_QUE);

        return(status);
}

int     que_deque_last(void **data)
{
        int     status;

        if (root.prev == &root) {
                return(1);
        }

        status = que_deque(data, GET_STACK);

        return(status);
}

static  int     que_deque(void **data, int get_type)
{
        QUE     *p      = NULL;

        if (get_type) {
                p = root.next;
                p->next->prev = p->prev;
                root.next = p->next;
        } else {
                p = root.prev;
                p->prev->next = p->next;
                root.prev = p->prev;
        }

        *data = p->data;
        free(p);

        return(0);
}

que_deque()内で、キューまたはスタックの切替えを行っている。使用する場合は、ラッパーであるque_deque_first()、que_deque_last()でキューまたはスタックを選択する。