🚝 Queue

hyukimΒ·2020λ…„ 5μ›” 5일
0

데이터ꡬ쑰둠

λͺ©λ‘ 보기
5/6

자료 ꡬ쑰 μ€‘μ—μ„œ 데이터와 링크둜 κ΅¬μ„±λœ μ—°κ²° 리슀트(Linked List)λΌλŠ” 것이 μžˆλ‹€. 이 μ—°κ²°λ¦¬μŠ€νŠΈλ₯Ό μ–΄λ–»κ²Œ ν™œμš©ν•˜μ—¬ λ§Œλ“œλŠλƒμ— λ”°λΌμ„œ μ—¬λŸ¬ 자료 ꡬ쑰λ₯Ό λ§Œλ“€ 수 μžˆλ‹€. μ΄λ²ˆμ—” κ·Έ μ€‘μ—μ„œ Queue에 λŒ€ν•΄μ„œ μ–˜κΈ°ν•˜κ² λ‹€.

Queue(큐)

  • λ¦¬μŠ€νŠΈν˜• 데이터 ꡬ쑰 μ€‘μ—μ„œ ν•œ μͺ½μ—μ„œλ§Œ 데이터λ₯Ό μΆ”κ°€ν•˜κ³  λ‹€λ₯Έ ν•œ μͺ½μ—μ„œλ§Œ μ‚­μ œν•  수 μžˆλŠ” FIFO(First In First Out; μ„ μž…μ„ μΆœ)식 데이터 ꡬ쑰이닀.
  • λ‹¨μ–΄μ˜ 본래 사전적 의미처럼 쀄을 μ„œλŠ” λͺ¨μ–‘κ³Ό κ°™λ‹€. λ¨Όμ € λ“€μ–΄μ˜¨ 데이터가 λ¨Όμ € λ‚˜κ°€λŠ” ν˜•μ‹μ΄λ‹€.
  • μ‚½μž…μ΄ μΌμ–΄λ‚˜λŠ” μͺ½μ€ rear, μ‚­μ œκ°€ μΌμ–΄λ‚˜λŠ” μͺ½μ„ front라고 ν•œλ‹€.
  • 큐의 μ—°μ‚°
    • insert, enqueue, offer, push : rear에 μƒˆλ‘œμš΄ μ•„μ΄ν…œμ„ μΆ”κ°€
    • remove, poll, pop : front에 μžˆλŠ” μ•„μ΄ν…œμ„ μ‚­μ œν•˜κ³  λ°˜ν™˜
    • peek, front : front에 μžˆλŠ” μ›μ†Œλ₯Ό μ œκ±°ν•˜μ§€ μ•Šκ³  λ°˜ν™˜
    • is_empty : 큐가 λΉ„μ–΄μžˆμœΌλ©΄ true(1)을 리턴
  • 큐의 κ΅¬ν˜„
    • 배열을 ν™œμš©ν•œ μ„ ν˜• 큐
    • 배열을 ν™œμš©ν•œ μ„ ν˜• 큐
    • λ§ν¬λ“œ 리슀트λ₯Ό ν™œμš©ν•œ 큐
  • 큐의 μ’…λ₯˜
    • μ„ ν˜• 큐(Linear Queue)
    • μ›ν˜• 큐(Circular Queue)
    • 데큐(Dequeue)
    • μš°μ„  μˆœμœ„ 큐(Priority Queue) β†’ λ‚˜μ€‘μ— λ”°λ‘œ λ‹€λ£Έ

μ„ ν˜• 큐(Linear Queue / 일반 큐)

  • 미리 지정해둔 QUEUE_MAX_SIZE크기의 배열에 값을 λ„£λŠ” ν˜•νƒœμ˜ 큐이닀.
  • pushν•˜λ©΄ rearκ°€ λ’€λ‘œ 밀리고 popν•˜λ©΄ frontκ°€ λ’€λ‘œ λ°€λ¦°λ‹€.
  • 점점 갈수둝 rear와 frontκ°€ λ’€λ‘œ 밀리기 λ•Œλ¬Έμ— 점점 μ‚¬μš©ν•  수 μžˆλŠ” 큐의 크기가 μž‘μ•„μ§„λ‹€.
  • frontκ°€ QUEUE_MAX_SIZEλ₯Ό λ„˜κΈ°λ©΄ 큐 μ˜€λ²„ν”Œλ‘œμš°(Queue Overflow)κ°€ μΌμ–΄λ‚œλ‹€.
  • Linear Queue κ΅¬ν˜„
# define QUEUE_MAX 10

static size_t   front = 0;
static size_t   rear = 0;
  • pop κ΅¬ν˜„
int     pop(int queue[])
{
    queue[front] = 0;
    front++;
}
  • push κ΅¬ν˜„
void    push(int queue[], int item)
{
    queue[rear] = item;
    rear++;
}
  • seek κ΅¬ν˜„
int     seek(int queue[])
{
    return (queue[front]);
}
  • is_empty κ΅¬ν˜„
int     is_empty(int queue[])
{
    return (front == rear);
}

μ›ν˜• 큐(Circular Queue / μˆœν™˜ 큐)

  • 미리 지정해둔 QUEUE_MAX_SIZE크기의 배열에 값을 λ„£λŠ” ν˜•νƒœμ˜ 큐이닀.
  • μ„ ν˜• 큐와 같이 push와 pop에 μ˜ν•΄μ„œ rear 와 frontκ°€ λ’€λ‘œ λ°€λ¦°λ‹€.
  • ν•˜μ§€λ§Œ rearλ‚˜ frontκ°€ QUEUE_MAX_SIZE 값일 λ•Œ, pushλ‚˜ pop을 ν•˜λ©΄ 0이 λΌμ„œ μˆœν™˜ν•œλ‹€.
  • κ·Έλ ‡κΈ° λ•Œλ¬Έμ— 항상 μ΅œλŒ€ QUEUE_MAX_SIZE 만큼의 μ•„μ΄ν…œμ„ κ°€μ§ˆ 수 μžˆλ‹€.
  • μ„ ν˜• νμ™€λŠ” λ‹€λ₯΄κ²Œ rear의 μœ„μΉ˜λŠ” λ§ˆμ§€λ§‰ μ›μ†Œμ˜ λ’€ μΈλ±μŠ€μ΄λ‹€.
    β†’ κ·Έλ ‡κ²Œ κ΅¬ν˜„ν•˜μ§€ μ•ŠμœΌλ©΄ fullκ³Ό emptyλ₯Ό κ΅¬λΆ„ν•˜κΈ° νž˜λ“¬
  • Circular Queue κ΅¬ν˜„
# define QUEUE_MAX 10

static size_t   front = 0;
static size_t   rear = 0;
  • pop κ΅¬ν˜„
int     pop(int queue[])
{
    int val;
    if (is_empty(queue))
        return (0);
    val = queue[front];
    front = (front + 1) % QUEUE_MAX;
    return (val);
}
  • push κ΅¬ν˜„
void    push(int queue[], int item)
{
    if (is_full(queue))
        return ;
    queue[rear] = item;
    rear = (rear + 1) % QUEUE_MAX;
}
  • seek κ΅¬ν˜„
int     seek(int queue[])
{
    return (queue[front]);
}
  • is_empty κ΅¬ν˜„
int     is_empty(int queue[])
{
    return (front == rear);
}
  • is_full κ΅¬ν˜„
int     is_full(int queue[])
{
    if (front <= rear)
        return (front == 0 && rear == QUEUE_MAX);
    return (front == rear + 1);
}

μ—°κ²° 리슀트둜 κ΅¬ν˜„ν•œ 큐

  • 미리 정해두지 μ•Šκ³  λ™μ μœΌλ‘œ ν•„μš”ν•  λ•Œ 값을 μΆ”κ°€ν•˜μ—¬ μ‚¬μš©ν•œλ‹€.
  • κ·Έλ ‡κΈ° λ•Œλ¬Έμ— λ©”λͺ¨λ¦¬ λ‚΄μ—μ„œ μ‚¬μš©ν•œλ‹€λ©΄ 크기의 μ œμ•½μ΄ 거의 μ—†λ‹€.
  • λ§Œλ“€λ €λ©΄ μ—°κ²° λ¦¬μŠ€νŠΈλ‘œλ„ μ›ν˜•νλ₯Ό λ§Œλ“€ 수 μžˆκ² μ§€λ§Œ ꡳ이 μ‚¬μ΄μ¦ˆ μ œμ•½μ„ 두면 λ§Œλ“€ μ΄μœ λŠ” μ—†λŠ”κ±° κ°™λ‹€.
  • Linked Queue κ΅¬ν˜„
typedef struct s_linked_queue
{
	int data;
	struct s_linked_queue *next;
} t_linked_queue;
  • pop κ΅¬ν˜„
int     pop(t_linked_queue *queue)
{
    t_linked_queue  *node;
    int             ret_val;

    if (!queue || !queue->next)
        return ;
    node = queue->next;
    ret_val = node->data;
    queue->next = node->next;
    free(node);
    return (ret_val);
}
  • push κ΅¬ν˜„
void    push(t_linked_queue *queue, int item)
{
    t_linked_queue *node;
    t_linked_queue *new;

    if (!queue)
        return ;
    if ((new = (t_linked_queue *)malloc(sizeof(t_linked_queue))) == 0)
        return ;
    node = queue;
    while (node->next)
        node = node->next;
    new->data = item;
    new->next = NULL;
    node->next = new;
}
  • peek κ΅¬ν˜„
int     peek(t_linked_queue *queue)
{
    return (queue->next->data);
}
  • is_empty κ΅¬ν˜„
int     is_empty(t_linked_queue *queue)
{
    if (!queue)
        return (1);
    return (!queue->next);
}

덱(Dequeue; Double-Ended Queue / 데큐)

  • 끝이 두 개인 νλΌμ„œ double-ended queue이닀.
  • front, rearμ—μ„œ push, pop λͺ¨λ‘ κ°€λŠ₯ν•˜λ‹€.
  • stackκ³Ό queue의 νŠΉμ§•μ„ λͺ¨λ‘ 가지고 μžˆλ‹€.
  • λ…Έλ“œκ°€ 데이터(data), 이전 λ…Έλ“œ(prev), λ‹€μŒ λ…Έλ“œ(next)둜 이루어진닀.
  • 슀크둀 (Scroll) : μž…λ ₯이 ν•œ μͺ½ 끝으둜만 κ°€λŠ₯ν•˜λ„λ‘ μ œν•œν•œ 덱
  • μ…Έν”„ (Shelf) : 좜λ ₯이 ν•œ μͺ½μœΌλ‘œλ§Œ κ°€λŠ₯ν•˜λ„λ‘ μ œν•œν•œ 덱
  • Dequeue κ΅¬ν˜„
typedef struct      s_node
{
    int             data;
    struct s_node   *next;
    struct s_node   *prev;
}                   t_node;

typedef struct      s_dequeue
{
    t_node          *head;
    t_node          *tail;
}                   t_dequeue;
  • init_dequeue κ΅¬ν˜„
t_dequeue               *init_dequeue(void)
{
    t_dequeue   *dequeue;

    if ((dequeue = (t_dequeue *)malloc(sizeof(t_dequeue))) == 0)
        return (NULL);
    dequeue->head = NULL;
    dequeue->tail = NULL;
    return (dequeue);
}
  • pop_back κ΅¬ν˜„
int                     pop_back(t_dequeue *dequeue)
{
    t_node  *node;
    t_node  *tmp;
    int     ret_val;

    if (!dequeue)
        return (0);
    node = dequeue->tail;
    ret_val = node->data;
    if (dequeue_size(dequeue) == 1)
    {
        free(node);
        dequeue->head = NULL;
        dequeue->tail = NULL;
    }
    else
    {
        tmp = node->prev;
        node->prev->next = NULL;
        free(node);
        dequeue->tail = tmp;
    }
    return (ret_val);
}
  • push_back κ΅¬ν˜„
void                    push_back(t_dequeue *dequeue, int item)
{
    t_node  *new_node;

    if (!dequeue)
        return ;
    if ((new_node = (t_node *)malloc(sizeof(t_node))) == 0)
        return ;
    new_node->data = item;
    new_node->prev = dequeue->tail;
    new_node->next = NULL;
    if (is_empty(dequeue))
        dequeue->head = new_node;
    else
        dequeue->tail->next = new_node;
    dequeue->tail = new_node;
}
  • pop_front κ΅¬ν˜„
int                     pop_front(t_dequeue *dequeue)
{
    t_node  *node;
    t_node  *tmp;
    int     ret_val;

    if (!dequeue)
        return (0);
    node = dequeue->head;
    ret_val = node->data;
    if (dequeue_size(dequeue) == 1)
    {
        free(node);
        dequeue->head = NULL;
        dequeue->tail = NULL;
    }
    else
    {
        tmp = node->next;
        tmp->prev = NULL;
        free(node);
        dequeue->head = tmp;
    }
    return (ret_val);
}
  • push_front
void                    push_front(t_dequeue *dequeue, int item)
{
    t_node  *new_node;

    if (!dequeue)
        return ;
    if ((new_node = (t_node *)malloc(sizeof(t_node))) == 0)
        return ;
    new_node->data = item;
    new_node->prev = NULL;
    new_node->next = dequeue->head;
    if (is_empty(dequeue))
        dequeue->tail = new_node;
    else
        dequeue->head->prev = new_node;
    dequeue->head = new_node;
}
  • is_empty κ΅¬ν˜„
int                     is_empty(t_dequeue *dequeue)
{
    return (dequeue->head == NULL);
}
  • dequeue_size κ΅¬ν˜„
size_t                  dequeue_size(t_dequeue *dequeue)
{
    size_t  cnt;
    t_node  *node;

    if (!dequeue)
        return (0);
    if (is_empty(dequeue))
        return (0);
    cnt = 1;
    node = dequeue->head;
    while (node->next)
    {
        node = node->next;
        cnt++;
    }
    return (cnt);
}

Reference

profile
πŸ’ͺ πŸ₯© 🍺 ✈ πŸ’»

0개의 λŒ“κΈ€