자료구조/큐(Queue)

[자로구조] 링크드 큐(Linked Queue) - 코딩밥상

코딩밥상 2022. 12. 29. 17:24

링크드 리스트 기반으로 큐 구현하기

링크드 큐는 순환 큐보다 직관적으로 구현할 수 있습니다. 링크드 큐의 각 노드는 이전 노드에 대한 포인터를 이용해 연결되므로 삽입 연산을 할 떄는 삽입 하려는 노드에 후단을 연결하고, 제거 연산을 할 때는 전단 바로 다음 노드에서 전단에 대한 포인터를 거두기만 하면 됩니다.

링크드 큐와 순환 큐의 또 다른 한가지 점은 큐가 가득 찬 상태인지 확인할 필요가 없습니다. 배열 기반으로 구현한 순환큐와는 다르게 링크드 리스트 기반은 용량의 제한이 없기 때문입니다.

 

하지만 성능적으로 치면 순환 큐가 더 빠릅니다. 노드를 생성하고 삭제하기 위해 malloc()과 free()함수를 호출 할 필요가 없기 때문입니다.

따라서 필요한 큐의 크기를 미리 정할 수 있고 고성능이 요구되는 상황에서는 링크드 큐보다 순환 큐를 선택하는 것이 좋습니다.

반대로 큐의 크기가 필연적으로 변하는 경우에는 링크드 큐를 선택하면 되겠네요.

 

-노드와 링크드 큐의 구조체

typedef struct tagNode{ //노드 구조체
    char* Data;
    struct tagNode* NextNode;
} Node;

typedef struct tagCircularQueue{   //링크드 큐 구조체
    Node* Front;
    Node* Rear;
    int Count;
} LinkedQueue;

-노드의 생성과 소멸

Node* LQ_CreateNode(char* NewData){
    Node* NewNode = (Node*)malloc(sizeof(Node));
    NewNode->Data = (char*)malloc(strlen(NewData) + 1);
    
    strcpy(NewNode->Data, NewData);
    
    NewNode->NextNode = NULL;
    
    return NewNode;
}

void LQ_DestroyNode(Node* _Node){
    free(_Node->Data);
    free(_Node);
}

-링크드 큐의 생성과 소멸

void LQ_CreateQueue(LinkedQueue** Queue){   //Heap에 링크드 큐 할당(큐 생성)
    (*Queue) = (LinkedQueue*)malloc(sizeof(LinkedQueue));
    (*Queue)->Front = NULL;
    (*Queue)->Rear = NULL;
    (*Queue)->Count = 0;
}

void LQ_DestroyQueue(LinkedQueue* Queue){ //Heap에 할당되어있던 링크드 해제(큐 소멸)
    while (!LQ_IsEmpty(Queue)) {
        Node* Popped = LQ_Dequeue(Queue);
        LQ_DestroyNode(Popped);
    }
    
    free(Queue);
}

-노드 삽입 연산(Enqueue)

void LQ_Enqueue(LinkedQueue* Queue, Node* NewNode){    //삽입 연산(Enqueue)
    if(Queue->Front == NULL){
        Queue->Front = NewNode;
        Queue->Rear = NewNode;
        Queue->Count++;
    }
    else{
        Queue->Rear->NextNode = NewNode;
        Queue->Rear = NewNode;
        Queue->Count++;
    }
}

-노드 삭제 연산(Dequeue)

Node* LQ_Dequeue(LinkedQueue* Queue){   //삭제 연산(Dequeue)
    Node* Front = Queue->Front;
    
    if(Queue->Front->NextNode == NULL){
        Queue->Front = NULL;
        Queue->Rear = NULL;
    }
    else{
        Queue->Front = Queue->Front->NextNode;
    }
    
    Queue->Count--;
    
    return Front;
}

 

 

-큐 상태 반환(IsEmpty)

int LQ_IsEmpty(LinkedQueue* Queue){   //공백 상태 확인
    return (Queue->Front == NULL);
}