본문 바로가기
[알고리즘 + 자료구조]

[자료구조] Double ended queue

by Hevton 2020. 10. 15.
반응형

양방향 대기열 = deck = deque = double ended queue

시작과 끝 지점에서 양쪽으로 데이터를 인큐하거나 디큐하는 자료구조

 

 

배열 구현한 예시

요소는 int형

 

+ 링 버퍼 구조 기반 예시

 

[double_ended_queue.h]

//
//  double_ended_queue.h
//  helloC
//
//  Created by Hevton on 2020/10/15.
//

#ifndef double_ended_queue_h
#define double_ended_queue_h
// 이 또한 링 버퍼 기반
typedef struct {
    int max; // 큐의 최대 용량
    int num; // 현재 요소 개수
    int front; // 맨 앞 요소
    int rear; // 링 버퍼 기반에선, 맨 뒤 요소 + 1임. 정답소스 오타인듯..
    int *que; // 큐를 가리키는 포인터
} IntDequeue;

int Initialize(IntDequeue *q, int max);

int EnqueFront(IntDequeue *q, int x);

int EnqueRear(IntDequeue *q, int x);

int DequeFront(IntDequeue *q, int *x);

int DequeRear(IntDequeue *q, int *x);

int PeekFront(const IntDequeue *q, int *x);

int PeekRear(const IntDequeue *q, int *x);

void Clear(IntDequeue *q);

int Capacity(const IntDequeue *q);

int Size(const IntDequeue *q);

int IsEmpty(const IntDequeue *q);

int IsFull(const IntDequeue *q);

int Search(const IntDequeue *q, int x);

int Search2(const IntDequeue *q, int x);

void Print(const IntDequeue *q);

void Terminate(IntDequeue *q);

#endif /* double_ended_queue_h */

 

 

[double_ended_queue.c]

//
//  double_ended_queue.c
//  helloC
//
//  Created by Hevton on 2020/10/15.
//

#include <stdio.h>
#include <stdlib.h>
#include "double_ended_queue.h"
// 이것도 링 버퍼 기반.
// 덱 = dequeue = double_ended_queue 초기화
int Initialize(IntDequeue *q, int max) {
    
    q->num = q->front = q->rear = 0;
    if((q->que = calloc(max, sizeof(int))) == NULL) {
        q->max = 0;
        return -1;
    }
    q->max = max;
    return 0;
    
}

// 맨 앞의 데이터를 인큐
int EnqueFront(IntDequeue *q, int x) {
    if(q->num >= q->max)
        return -1;
    else {
        q->num++;
        if(--q->front <0)
            q->front = q->max - 1;
        q->que[q->front] = x;
        return 0;
    }
}

// 맨 뒤의 데이터를 인큐
int EnqueRear(IntDequeue *q, int x) {
    if(q->num >= q->max)
        return -1;
    else {
        q->num++;
        q->que[q->rear++] = x;
        if(q->rear == q->max)
            q->rear = 0;
        return 0;
    }
}

// 맨 앞의 데이터를 디큐
int DequeFront(IntDequeue *q, int *x) {
    if(q->num <=0)
        return -1;
    
    else {
        q->num --;
        *x = q->que[q->front++];
        if(q->front==q->max)
            q->front=0;
        return 0;
    }
}

// 맨 뒤의 데이터를 디큐
int DequeRear(IntDequeue *q, int *x) {
    if(q->num <=0)
        return -1;
    else {
        q->num--;
        if(--q->rear <0)
            q->rear = q->max - 1;
        *x = q->que[q->rear];
        return 0;
    }
}

// 맨 앞의 데이터를 피크
int PeekFront(const IntDequeue *q, int *x) {
    if(q->num <= 0)
        return -1;
    else {
        *x = q->que[q->front];
        return 0;
    }
}

// 맨 뒤의 데이터를 피크 2021.03.10 오류 수정.
int PeekRear(const IntDequeue *q, int *x) {
    int temp;
    
    if(d->num <= 0)
        return -1;
    
    if((temp = q->rear - 1) < 0)
        temp = q->max - 1;
    
    *v = q->que[temp];
    return 0;
}

// 모든 데이터 삭제
void Clear(IntDequeue *q) {
    q->num = q-> front = q->rear = 0;
}

// 큐의 최대 용량
int Capacity(const IntDequeue *q) {
    return q->max;
}

// 큐에 저장된 데이터의 수
int Size(const IntDequeue *q) {
    return q->num;
}

// 큐가 비어있는지 확인
int IsEmpty(const IntDequeue *q) {
    return q->num <=0;
}

// 큐가 가득 찼는지 확인
int IsFull(const IntDequeue *q) {
    return q->num >= q->max;
}

// 큐 검색
int Search(const IntDequeue *q, int x) {
    int i, idx;
    
    for(i=0; i< q->num; i++) {
        if(q->que[idx = (i+q->front)%q->max] == x)
            return idx;
    }
    return -1;
}

// 큐 검색(논리적 검색)
int Search2(const IntDequeue *q, int x) {
    int i;
    
    for(i=0; i< q->num; i++) {
        if(q->que[(i+q->front)%q->max] == x)
            return i;
    }
    return -1;
}

// 전체 데이터 출력
void Print(const IntDequeue *q) {
    int i;
    
    for(i=0; i< q->num; i++) {
        printf("%d ", q->que[(i+q->front)%q->max]);
    }
    putchar('\n');
}

// 큐 삭제
void Terminate(IntDequeue *q) {
    if(q->que !=NULL)
        free(q->que);
    
    q->max = q->num = q->front = q->rear = 0;
}

 

[main.c]

#include <stdio.h>
#include "double_ended_queue.h"

int main() {
    IntDequeue que;
    
    if(Initialize(&que, 64) == -1) {
        puts("큐 생성 실패");
        return -1;
    }
    
    while(1) {
        int m, x;
        int idx;
        
        printf("현재 데이터의 수 : %d / %d\n", Size(&que), Capacity(&que));
        printf("(1)맨 앞에 데이터 인큐 (2)맨 앞의 데이터 디큐 (3)맨 앞 피크 (4)출력\n"
               "(5)맨 뒤에 데이터 인큐 (6)맨 뒤의 데이터 디큐 (7)맨 뒤 피크 (8)검색\n"
               "(9)초기화 (10)비어 있는 상태 / 가득 찬 상태 (0)종료 : ");
        scanf("%d", &m);
        
        if(m == 0) break;
        
        switch(m) {
            case 1: // 맨 앞에 데이터 인큐
                printf("데이터 : "); scanf("%d", &x);
                if(EnqueFront(&que, x) == -1)
                    puts("\a오류 : 인큐 실패");
                break;
                
            case 2: // 맨 앞의 데이터 디큐
                if(DequeFront(&que, &x) == -1)
                    puts("\a오류 : 디큐 실패");
                else
                    printf("디큐한 데이터는 %d입니다.\n", x);
                break;
                
            case 3: // 맨 앞 피크
                if(PeekFront(&que, &x) == -1)
                    puts("\a오류 : 피크 실패");
                else
                    printf("피크한 데이터는 %d입니다.\n", x);
                break;
                
            case 4: // 덱 출력
                Print(&que);
                break;
                
            case 5: // 맨 뒤에 데이터 인큐
                printf("데이터 : "); scanf("%d", &x);
                if(EnqueRear(&que, x) == -1)
                    puts("\a오류 : 인큐 실패");
                break;
                
            case 6: // 맨 뒤의 데이터 디큐
                if(DequeRear(&que, &x) == -1)
                    puts("\a오류 : 디큐 실패");
                else
                    printf("디큐한 데이터는 %d입니다.\n", x);
                break;
                
            case 7: // 맨 뒤 피크
                if(PeekRear(&que, &x) == -1)
                    puts("\a오류 : 피크 실패");
                printf("피크한 데이터는 %d입니다.\n", x);
                break;
                
            case 8: // 검색
                printf("검색 데이터 : ");
                scanf("%d", &x);
                if((idx=Search(&que, x)) == -1)
                    puts("\a오류 : 검색 실패");
                else {
                    printf("데이터는 인덱스 %d 위치에 있습니다.\n", idx);
                    printf("큐의 맨 앞에서 %d만큼 뒤에 위치합니다.\n", Search2(&que, x));
                }
                break;
                
            case 9: // 초기화
                Clear(&que);
                break;
                
            case 10: //  빈 상태 / 가득 찬 상태 판단
                printf("큐가 비어 있%s.\n", IsEmpty(&que)?"습니다":"지 않습니다");
                printf("큐가 가득 %s.\n", IsEmpty(&que)?"찼습니다":"차지 않았습니다");
                break;
        }
    }
    Terminate(&que);
    return 0;
}

 

반응형

'[알고리즘 + 자료구조]' 카테고리의 다른 글

[알고리즘] Factorial / 팩토리얼  (0) 2020.11.04
[자료구조] 링 버퍼  (0) 2020.10.15
[자료구조] Queue  (0) 2020.10.15
[자료구조] 다중 STACK  (0) 2020.10.14
[자료구조] STACK  (0) 2020.10.14