링크드 큐 

 

링크드 리스트로 만든 큐입니다.

배열로 만든 순환 큐와는 달리 공백/포화를 구분할 필요가 없습니다. 

 

head 노드에서 제거하고, tail 노드에서 삽입합니다. 

 

 

 

노드 선언과 큐 

 

노드는 링크드 리스트의 노드와 똑같습니다. 

링크드 큐 구조체는 전단과 후단을 가리킬 포인터와 총 노드 개수 변수를 가집니다. 

typedef struct Node {
	char* data;
	struct Node* nextNode;
};

typedef struct LQ {
	struct Node* front;
	struct Node* rear;
	int nodeCnt;
};

 

노드 생성과 메모리 해제

void CreateQueue(LQ** lq) {

	(*lq) = (LQ*)malloc(sizeof(LQ));
	(*lq)->front = NULL;
	(*lq)->rear = NULL;
	(*lq)->nodeCnt = 0;
}

 

삽입

/* 후단에 삽입 */
void Enqueue(LQ* lq, Node* newNode) {

	if (NULL == lq->front) {
		lq->front == newNode;
		lq->rear == newNode;
	}
	else {
		lq->rear->nextNode = newNode;
		lq->rear = newNode;
	}

	lq->nodeCnt++;

}

 

제거 

/* 전단에서 제거 */
Node* Dequeue(LQ* lq) {

	Node* out = lq->front;

	if (NULL == lq->front->nextNode) {
		lq->front = NULL;
		lq->rear = NULL;
	}
	else {
		lq->front = lq->front->nextNode;
	}

	lq->nodeCnt--;

	return out;
}

 

728x90

'알고리즘 > 알고리즘 C' 카테고리의 다른 글

이진 트리  (0) 2020.03.11
트리 기초  (0) 2020.03.11
순환 큐  (0) 2020.03.09
링크드 리스트로 구현하는 스택  (0) 2020.02.19
배열로 구현하는 스택  (0) 2020.02.18

 

큐는 먼저 들어온 일부터 먼저 처리하는 자료구조 입니다. 

선입 선출, First In First Out (FIFO) 라고 합니다. 

 

 

 

큐의 기능 

 

큐의 가장 앞 요소를 전단, 마지막 요소를 후단이라고 합니다. 

(스택은 최상위 노드가 있는 입구에서만 삽입/제거가 수행됩니다. )

큐는 전단에서 Dequeue (제거) 되고, 후단에서만 Enqueue (삽입) 됩니다. 

 

 

 

순환 큐 

 

유의할 점은 큐가 비었는지 가득찼는지 구분을 위해 큐를 실제 용량보다 1 크게 만드는 것입니다. 

 

용량이 7인 큐를 만든다고 하면, 

구현할 때는 8인 큐를 만듭니다. 

 

비었을 때는 전단과 후단이 같은 곳을 가리킵니다 

큐가 꽉 찼을 때는 후단 바로 다음이 전단이 됩니다. 

이렇게 후단과 전단 사이에 공간을 두어 큐의 상태를 구분합니다. 

 

후단은 실제 데이터가 있는 칸의 바로 다음칸을 가리키고 있음을 유의해야 합니다.

후단 인덱스는 항상 빈 칸을 가리키고 있어야 합니다. 

 


 

순환 큐 구현

 

노드와 큐 구조체를 선언합니다.

typedef struct Node {
	int data;
};

typedef struct Cqueue {
	int capacity;
	int front;
	int rear;
	Node* nodeArray;
};

Cqueue구조체에서 nodeArray 포인터는 자유저장소에 존재하는 배열의 첫번째 칸을 가리킵니다. 

공백과 포화를 구분하기 위해 실제 capacity + 1하기 위한 '더미 노드'를 하나 둡니다.  

 

 

 

큐를 만들고 메모리 해제하는 함수 

 

void CreateCqueue(Cqueue** cqueue, int capacity) {

	(*cqueue) = (Cqueue*)malloc(sizeof(Cqueue));

	(*cqueue)->capacity = capacity;
	(*cqueue)->front = 0;
	(*cqueue)->rear = 0;
	(*cqueue)->nodeArray = (Node*)malloc(sizeof(Node) * (capacity + 1));

}

 

nodeArray 라는 이름의 배열은 사용자가 요구한 용량보다 1개 크게 만들어집니다. 더미 노드를 포함하기 때문입니다. 

 

void FreeCqueue(Cqueue* cqueue) {

	free(cqueue->nodeArray);
	free(cqueue);
}

 

 

삽입(Enqueue)

 

뒤에서 삽입하니까 rear를 관리합니다. 

 

rear는 항상 삽입'할' 타겟 인덱스를 가리키고 있습니다.

즉, 빈 공간을 가리키고 있다는 뜻입니다. 

capacity + 1인 인덱스는 공백/포화를 구분할 더미노드의 위치입니다. 

void Enqueue(Cqueue* cqueue, int data) {

	int position = 0;

	if (cqueue->capacity + 1 == cqueue->rear) {
		position = cqueue->rear;
		cqueue->rear = 0;
	}
	else {
		position = cqueue->rear++;
	}

	cqueue->nodeArray[position].data = data;
}

 

 

제거(Dequeue)

 

앞에서 제거하니까 front를 관리합니다. 

 

front와 capacity가 같은 상황은 전단이 배열 맨 끝에 와있다는 것입니다. 

노드를 하나 제거 하면, 인덱스를 0으로 돌려놔야 합니다. 

이 경우를 제외하면 front를 하나 감소시키면 됩니다.

int Dequeue(Cqueue* cqueue) {

	int position = cqueue->front;

	if (cqueue->front == cqueue->capacity ) {
		cqueue->front = 0;
	}else{
		cqueue->front++;
	}
	
	return cqueue->nodeArray[position].data;
}

 

 

큐의 공백과 포화 확인하기 

 

공백 : front 와 rear 가 같은 곳을 가리키고 있습니다. 

int IsEmpty(Cqueue* cqueue) {
	return 	(cqueue->front == cqueue->rear);
}

 

포화: rear의 바로 다음이 front 입니다. 또는 rear에서 front를 빼면 그 길이가 capacity가 됩니다. 

int IsFull(Cqueue* cqueue) {
	if (cqueue->front < cqueue->rear) {
		return (cqueue->rear - cqueue->front == cqueue->capacity);
	}
	else {
		return (cqueue->front == cqueue->rear + 1);
	}
}

 

 

메인함수 - 삽입/제거 해보기 

 

5개를 저장할 수 있는 배열을 만들고, 8번 삽입, 6번 제거해봤습니다. 

삽입 전에 포화인지 검사하고 포화이면 탈출합니다. 

제거 전에 비었는지 검사하고 비었으면 탈출합니다. 

 

콘솔 결과

 

int main(void) {

	int i = 0; 
	Cqueue* queue;

	// 5개를 저장할 수 있는 배열 
	CreateCqueue(&queue, 5);

	// 8번 삽입 
	for (int cnt = 1; cnt < 9; cnt++) {
		if (!IsFull(queue)) {
			printf("%d를 삽입.\n", cnt);
			Enqueue(queue, cnt);
		}
		else {
			printf("큐가 꽉 찼습니다.\n");
			break;
		}
	}

	// 6번 제거
	for (int cnt = 1; cnt < 7; cnt++) {
		if (!IsEmpty(queue)) {
			printf("%d 를 제거.\n", Dequeue(queue));
		}
		else {
			printf("큐가 비었습니다.\n");
			break;
		}
	}

	return 0;
}
728x90

'알고리즘 > 알고리즘 C' 카테고리의 다른 글

트리 기초  (0) 2020.03.11
링크드 큐  (0) 2020.03.10
링크드 리스트로 구현하는 스택  (0) 2020.02.19
배열로 구현하는 스택  (0) 2020.02.18
환형 링크드 리스트  (0) 2020.02.17

+ Recent posts