Language/C

[C] 자료구조 큐(queue)

0so0 2023. 8. 9. 11:07
728x90
반응형
SMALL

자료구조 중 하나인 큐(queue), 덱(Deque)에 대한 설명 + c로 구현한 큐 코드에 대한 정리

 

■ 큐(queue)

먼저 들어온 데이터가 먼저 나가는 자료구조
선입 선출(FIFO  :First-In First Out)
객체 : n개의 요소들의 순서 있는 모임

연산 :

Create    ::= 큐 생성

Empty(q)    ::= 비어 있는지 검사

Full(q)    ::= 가득 차 있는지 검사

Enqueue(q, e)   ::= 큐의 뒤에 요소 e 추가

Dequeue(q)   ::= 큐의 앞에 있는 요소 반환 후 삭제

Peek(q)  ::= 큐에서 삭제하지 않고 앞에 있는 요소 반환

 

 삽입, 삭제 연산

 

 배열로 구현한 큐

  • 선형 큐

위와 같이 선형 큐로 구현할 경우, 삽입을 하기 위해서 요소들을 계속 이동시켜야 하는 문제 발생

데이터를 옮기는데에만 많은 연산을 수행하게 됨

따라서 아래와 같은 순환형식의 원형 큐를 이용하여 구현해야 함

 

  • 원형 큐

  • 구조체 선언
#include <stdio.h>

#define MAX_QUEUE_SIZE 10

typedef int Element;
typedef struct {
   Element EQueue[MAX_QUEUE_SIZE];
   int nFront;	//전단
   int nRear;	// 후단
} QueueType;
  • Error, Init
int Error(char *message)
{
   fprintf(stderr, "%s\n", message);
   return -1;
}
int Init(QueueType *pQue)
{
   pQue->nFront = pQue->nRear = 0;
   return 0;
}
  • Empty, Full
int Empty(QueueType *pQue)
{
   if (pQue->nFront == pQue->nRear) return 1;
   else return 0;
}

int Full(QueueType *pQue)
{
   if ((pQue->nRear + 1) % MAX_QUEUE_SIZE == pQue->nFront return 1;
   else return 0;
}
  • Enqueue
int Enqueue(QueueType *pQue, Element EData)
{
   if (Full(pQue) == 1) {
      Error("큐 포화");
   }
else {
   pQue->nRear = (pQue->nRear + 1) % MAX_QUEUE_SIZE;
   pQue->EQueue[pQue->nRear] = EData;
}
   return 0;
}
  • Dequeue
Element Dequeue(QueueType *pQue)
{
   if (Empty(pQue) == 1) {
   Error("큐 공백");
}
else {
   pQue->nFront = (pQue->nFront + 1) % MAX_QUEUE_SIZE;
}

   return pQue->EQueue[pQue->nFront];
}

 

연결리스트로 구현한 큐

  • 노드 정의
typedef int Element;
typedef struct _queuenode {
   Element EData;
   struct _queuenode *link;
} QueueNode;

typedef struct {
   QueueNode *front;
   QueueNode *rear;
} QueueType;

 

  • Init, Empty
int Init(QueueType *pQue)
{
   pQue->front = pQue->rear = NULL;

   return 0;
}
int Empty(QueueType *pQue)
{
   if (pQue->front == NULL) return 1;
   else return 0;
}

 

  • Enqueue

int Enqueue(QueueType *pQue, Element EData)
{
   QueueNode *pNew = (QueueNode *)malloc(sizeof(QueueNode));

   if (pNew == NULL) Error("메모리 할당 불가");
   else {
      pNew->EData = EData;	// 데이터 저장
      pNew->link = NULL;	// 마지막에 삽입
         if (Empty(pQue) == 1) {
            pQue->front = pNew;
            pQue->rear = pNew;
         }
         else {
            pQue->rear->link = pNew;
            pQue->rear = pNew;
          }
   }
   return 0;
}

 

  • Dequeue

Element Dequeue(QueueType *pQue)
{
   QueueNode *pRemove = NULL; 
   Element EData = 0;

   pRemove = pQue->front;

   if ( Empty(pQue) == 1) {
      Error("큐 공백");
   }
   else {
      EData = pRemove->EData;
      pQue->front = pQue->front->link;
      if (pQue->front == NULL) {
         pQue->rear = NULL;
      }
      free(pRemove); pRemove = NULL;
      return EData;
   }
}

 

 덱(Deque)

Double-ended-queue
전단과 후단에서 모두 삽입 & 삭제
add_rear(dq, e) =  Enqueue(dq, e)   ::= 덱의 뒤에 요소 e 추가

delete_front(dq, e) = Dequeue()   ::= 덱의 앞에 있는 요소 반환 후 삭제

delete_rear(dq, e) = Pop()  ::= 덱의 마지막 요소 반환 후 삭제

add_front(dq, e)   ::= 덱의 앞에 요소 e 추가

 

 덱(Deque)의 연산

  • 노드 정의
typedef int Element;

typedef struct _listnode {
   Element EData;
   struct _listnode *Llink;
   struct _listnode *Rlink;
} ListNode;

typedef struct _dequetype {
   ListNode *pHead;
   ListNode *pTail;
} DequeType;

 

  • Init, Empty
int Init(DequeType *pDeque)
{
   pDeque->pHead = pDeque->pTail = NULL;
}
int Empty(DequeType *pDeque)
{
   if (pDeque->pHead == NULL) return 1;
   else return 0;
}

 

  • 노드 생성
ListNode *CreateNode(ListNode *Llink, Element EData, ListNode *Rlink)
{
   ListNode *pNode = (ListNode *)malloc(sizeof(ListNode));
   if (pNode == NULL) {
      Error("메모리 할당 오류");
   }
   pNode->Llink = Llink;
   pNode->EData = EData;
   pNode->Rlink = Rlink;
   return pNode;
}

 

  • Add rear

int Add_Rear(DequeType *pDeque, Element EData)// 마지막에 추가
{
   ListNode *pNew = NULL;
   pNew = CreateNode(pDeque->pTail, EData, NULL);
   if (Empty(pDeque) == 1) {
      pDeque->pHead = pNew;
   }
   else {
      pDeque->pTail->Rlink = pNew;
   }
   pDeque->pTail = pNew;
   return 0;
}

 

  • Add front

int Add_Front(DequeType *pDeque, Element EData)// 처음에 추가
{
   ListNode *pNew = NULL;
   pNew = CreateNode(NULL, EData, pDeque->pHead);
   if (Empty(pDeque) == 1) {
      pDeque->pTail = pNew;
   }
   else {
      pDeque->pHead->Llink = pNew;
   }
   pDeque->pHead = pNew;
   return 0;
}

 

  • Delete front

Element Delete_Front(DequeType *pDeque)
{
   Element EData = 0;
   ListNode *pRemove = NULL;

   if (Empty(pDeque) == 1) {
      Error("덱 공백");
   }
   else {
      pRemove = pDeque->pHead;		// 제거할 노드
      EData = pRemove->EData;			// 제거 데이터 저장
      pDeque->pHead = pRemove->Rlink;		// 제거 노드의 R링크가 덱의 헤드가 됨
      //pDeque->pHead = pDeque->pHead->Rlink;	
      free(pRemove); pRemove = NULL;		// 반환
      if (pDeque->pHead == NULL) {		// 공백 상태
         pDeque->pTail = NULL;			// tail도 공백
      }
      else {
         pDeque->pHead->Llink = NULL;		 // 공백이 아니면- head Llink = NULL
      }
    }
   return EData;
}

 

  • Delete rear

Element Delete_Rear(DequeType *pDeque)
{
   Element EData = 0;
   ListNode *pRemove = NULL;

   if (Empty(pDeque) == 1) {
      Error("덱 공백");
   }
   else {
      pRemove = pDeque->pTail;			// 제거할 노드
      EData = pRemove->EData;			// 제거 데이터 저장
      pDeque->pTail = pRemove->Llink;		// 제거 노드의 L링크가 덱의 tail이 됨
      //pDeque->pTail = pDeque->pHead->Llink;	
      free(pRemove); pRemove = NULL;		// 반환
      if (pDeque->pTail == NULL) {		// 공백 상태
         pDeque->pHead = NULL;			// head도 공백
      }
      else {
         pDeque->pTail->Rlink = NULL;		// 공백이 아니면 – tail Rlink = NULL;
      }
   }
   return EData;
}
728x90
반응형
LIST

'Language > C' 카테고리의 다른 글

[C] Compile/Build 과정  (0) 2023.09.07
[C] 공용체(union) 사용법 및 예제  (0) 2023.08.28
[C] 자료구조 스택(stack)  (0) 2023.08.16
[C] memset 사용법 및 예제  (0) 2023.07.26