๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ“–CS/๐Ÿ“™Data Structure

[์ž๋ฃŒ๊ตฌ์กฐ] Chapter3. STACKS AND QUEUES(1)

by goguma.dev 2024. 10. 5.

โ€ป ์ด ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๊ธ€๋“ค์€ knu EK.Ryu ๊ต์ˆ˜๋‹˜์˜ <์ž๋ฃŒ๊ตฌ์กฐ> ์ˆ˜์—…์„ ๋“ฃ๊ณ  ๋‚˜๋ฆ„๋Œ€๋กœ ํ•„์ž๊ฐ€ ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.

โ€ป ๋ถ€์กฑํ•œ ์„ค๋ช…์ด ์žˆ๊ฑฐ๋‚˜, ์ž˜๋ชป ์•Œ๊ณ  ์ž‘์„ฑํ•œ ๋ถ€๋ถ„์ด ๋ณด์ธ๋‹ค๋ฉด ํŽธํ•˜๊ฒŒ ๋Œ“๊ธ€๋กœ ์•Œ๋ ค์ฃผ์‹œ๋ฉด ์ •๋ง ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค๐Ÿ˜Š

3.1 Stack

์Šคํƒ์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ์‚ญ์ œํ•˜๋Š”๋ฐ LIFO(Last In, First Out) ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•˜๋Š” ์ž๋ฃŒ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค. ์ฆ‰, ๋งˆ์ง€๋ง‰์— ๋“ค์–ด์˜จ ๋ฐ์ดํ„ฐ๊ฐ€ ๊ฐ€์žฅ ๋จผ์ € ๋‚˜๊ฐ€๋Š” ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.

์œ„ ๊ทธ๋ฆผ์—์„œ ๋ณด์ด๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, A, B, C, D, E ์ˆœ์„œ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ๊ณ , ์‚ญ์ œํ•  ๋•Œ๋Š” E๋ถ€ํ„ฐ ์ œ๊ฑฐ๋ฉ๋‹ˆ๋‹ค.

 

์Šคํƒ์— ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ๊ณ (push), ๋นผ๋Š”(pop) ํ•จ์ˆ˜์— ๋Œ€ํ•ด์„œ ์•„๋ž˜์—์„œ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

void push(element item) // ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€
{
    if (top >= MAX_STACK_SIZE - 1)
        stackFull();
    stack[++top] = item;
}

void stackFull() // ์Šคํƒ์ด ๊ฝ‰ ์ฐผ์„ ๋•Œ ์˜ค๋ฅ˜ ์ถœ๋ ฅ
{
    fprintf(stderr, "Stack is full, cannot add element");
    exit(EXIT_FAILURE);
}

element pop() // ์Šคํƒ์—์„œ ๋ฐ์ดํ„ฐ ๋ฝ‘๊ธฐ(๊ฐ€์žฅ ์œ„์— ์žˆ๋Š”!)
{
    if (top == -1)
        return stackEmpty();
    return stack[top--];
}

 

 

3.2 Stacks Using Dynamic Arrays

๋ฐฐ์—ด์„ ์ด์šฉํ•œ ์Šคํƒ์€ ๋ฐ์ดํ„ฐ๊ฐ€ ์Šคํƒ์˜ ์šฉ๋Ÿ‰์„ ๋„˜์–ด์„œ ์Œ“์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋™์  ํ• ๋‹น์„ ์ด์šฉํ•œ๋‹ค๋ฉด, ์Šคํƒ์˜ ํฌ๊ธฐ๊ฐ€ ๊ฐ€๋“ ์ฐฐ ๋•Œ ๋™์ ์œผ๋กœ ๋ฐฐ์—ด์„ ๋‘ ๋ฐฐ ๋Š˜๋ ค ์ด ๋ฌธ์ œ๋ฅผ ๊ทน๋ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

pop() ํ•จ์ˆ˜๋Š” ๊ทธ๋Œ€๋กœ์ด๊ณ , push() ํ•จ์ˆ˜์™€ stackFull() ํ•จ์ˆ˜๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๋ณ€๊ฒฝํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

void push(element item)
{
    if (top >= capacity - 1)
        stackFull();
    stack[++top] = item;
}

void stackFull()
{
    REALLOC(stack, 2 * capacity * sizeof(*stack));
    capacity *= 2;
}

 

 

3.3 Queues

ํ๋Š” FIFO(First In, First Out) ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•˜๋Š” ์ž๋ฃŒ๊ตฌ์กฐ๋กœ, ๋จผ์ € ๋“ค์–ด์˜จ ๋ฐ์ดํ„ฐ๊ฐ€ ๋จผ์ € ๋‚˜๊ฐ€๋Š” ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.

์‚ฝ์ž…์€ ํ์˜ ๋’ค์ชฝ(rear)์—์„œ ์ด๋ฃจ์–ด์ง€๊ณ , ์‚ญ์ œ๋Š” ์•ž์ชฝ(front)์—์„œ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค.

ํ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์—๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

1. 1์ฐจ์› ๋ฐฐ์—ด์„ ์ด์šฉํ•œ ํ

2. 1์ฐจ์› ๋ฐฐ์—ด์„ ์›ํ˜•์œผ๋กœ ์—ฐ๊ฒฐํ•˜์—ฌ ์ด์šฉํ•˜๋Š” ์›ํ˜• ํ

 

(1) 1์ฐจ์› ๋ฐฐ์—ด ํ

๋จผ์ € 1์ฐจ์› ๋ฐฐ์—ด ํ๋ฅผ ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

void addq(element item)
{
	// add an item to the queue
    if (rear == MAX_QUEUE_SIZE - 1)
        queueFull();
	queue[++rear] = item;
}

element deleteq()
{
	// remove element at the front of the queue
	if (front == rear)
		return queueEmpty();
	return queue[++front];
}

์ด 1์ฐจ์› ๋ฐฐ์—ด ํ์—๋Š” ์ž‘์—…์„ ์ง„ํ–‰ํ•˜๋ฉด์„œ ํ๊ฐ€ ์ ์  ์˜ค๋ฅธ์ชฝ์œผ๋กœ ์ด๋™ํ•˜๊ฒŒ ๋œ๋‹ค๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ฐฐ์—ด์˜ ๋ชจ๋“  ์›์†Œ๋ฅผ ์™ผ์ชฝ์œผ๋กœ ์ด๋™์‹œํ‚ค๋Š” ๋ฐฐ์—ด ์ด๋™(array shifting) ์ž‘์—…์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด ์ž‘์—…์—๋„ ์‹œ๊ฐ„ ๋ณต์žก๋„๊ฐ€ O(MAX_QUEUE_SIZE)๋กœ ๋งค์šฐ ๋น„ํ˜ธ์œจ์ ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋Œ€์•ˆ์œผ๋กœ ์›ํ˜•ํ๋ผ๋Š” ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

 

(2) ์›ํ˜• ํ Circular Queue

์›ํ˜• ํ๋Š” ๋ฐฐ์—ด์˜ ๋์—์„œ ๋‹ค์‹œ ๋ฐฐ์—ด์˜ ์ฒ˜์Œ์œผ๋กœ ๋Œ์•„๊ฐˆ ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„๋˜์–ด, ๋ฐฐ์—ด์˜ ๋์— ๋„๋‹ฌํ–ˆ์„ ๋•Œ ์ „์ฒด๋ฅผ ๋‹ค์‹œ ์ด๋™์‹œํ‚ค์ง€ ์•Š๊ณ ๋„ ํšจ์œจ์ ์œผ๋กœ ํ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด ์ค๋‹ˆ๋‹ค.

์•„๋ž˜ ์ฝ”๋“œ์—์„œ ์›ํ˜• ํ์˜ ์‚ฝ์ž…, ์‚ญ์ œ ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•ด ๋ด…์‹œ๋‹ค.

void addq(element item)
{
	rear = (rear + 1) % MAX_QUEUE_SIZE;
	if (front == rear)
		queueFull();
	queue[rear] = item;
}

element deleteq()
{
	if (front == rear)
		return queueEmpty();
	front = (front + 1) % MAX_QUEUE_SIZE;
	return queue[front];
}

์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์›ํ˜• ํ์˜ ํŠน์ง•์„ ํ•˜๋‚˜ ์•Œ ์ˆ˜ ์žˆ๋Š”๋ฐ, ํ๋Š” ๊ฝ‰ ์ฐผ์„ ๋•Œ๋„ ๋ฆฌ์ŠคํŠธ์˜ ํ•œ ์ž๋ฆฌ๊ฐ€ ๋น„์–ด์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ด๋Š” ์›ํ˜• ํ์—์„œ front์™€ rear๊ฐ€ ๋™์ผํ•  ๋•Œ ํ๊ฐ€ ๋น„์–ด์žˆ๋Š” ์ƒํƒœ์™€ ๊ฐ€๋“ ์ฐฌ ์ƒํƒœ๋ฅผ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

 

3.4 Circular Queues using Dynamic Arrays

์›ํ˜• ํ๊ฐ€ ๊ฐ€๋“ ์ฐผ์„ ๋•Œ ๋ฐ์ดํ„ฐ๋ฅผ ๋” ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ๋™์ ํ• ๋‹น์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

์œ„ ์ด๋ฏธ์ง€๋Š” ์›ํ˜• ํ๊ฐ€ ๊ฐ€๋“ ์ฐผ์„ ๋•Œ๋ฅผ ํ‘œํ˜„ํ•œ ๊ฒƒ์œผ๋กœ, ์‹ค์ œ๋กœ ์›ํ˜• ํ๋Š” 1์ฐจ์› ๋ฐฐ์—ด ํ˜•ํƒœ์ด๊ธฐ ๋•Œ๋ฌธ์— (b)์˜ ํ˜•ํƒœ๋ฅผ ๊ฐ–๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

(b)์˜ ์ƒํƒœ์—์„œ realloc์„ ํ•˜์—ฌ ์›ํ˜• ํ์˜ ํฌ๊ธฐ๋ฅผ 2๋ฐฐ ๋Š˜๋ฆฐ๋‹ค๋ฉด, ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์›ํ˜• ํ์˜ ํŠน์ง•์„ ๊ณ ๋ คํ•˜์ง€ ์•Š์•„, (c)์˜ ๊ทธ๋ฆผ์—์„œ ๋ณด์ด๋“ฏ์ด ๊ฐ€์šด๋ฐ์— ํฐ ๋นˆ ๊ณต๊ฐ„์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

(d): ์ด๋ฅผ ์˜ˆ๋ฐฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” 6, 7๋ฒˆ index์— ๋“ค์–ด์žˆ๋Š” ๊ฐ’๋“ค์„ ์˜ค๋ฅธ์ชฝ ๋์œผ๋กœ shifting ์‹œ์ผœ ํ•ด๊ฒฐํ•˜๊ฑฐ๋‚˜,

(e): ๊ฝ‰ ์ฐฌ ๋ฐฐ์—ด์˜ ๊ฐ’๋“ค์„ ๋ณต์‚ฌ ํ›„, malloc์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

์›ํ˜• ํ์˜ ํฌ๊ธฐ๋ฅผ ๋™์ ํ• ๋‹น์œผ๋กœ ๋Š˜๋ฆฌ๋Š” ๋‘ ๋ฐฉ๋ฒ•์„ ๋น„๊ตํ•ด ๋ด…์‹œ๋‹ค: realloc --> shifting vs malloc

๋จผ์ €, ์ฒซ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์„ ์ด์šฉํ•˜๋ฉด ๋ฐฐ์—ด์„ 2๋ฐฐ๋กœ ํ™•์žฅํ•˜๊ณ  ์›์†Œ๋ฅผ ์˜ค๋ฅธํŽธ์œผ๋กœ ๋ฏธ๋Š” ๊ฒƒ์„ ๋‹ค ํ•ฉ์ณค์„ ๋•Œ ์ตœ๋Œ€ 2 * capacity - 2์˜ ์›์†Œ๋ฅผ ๋ณต์‚ฌํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

๋‘ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์—์„œ๋Š” ๋ฐฐ์—ด ํฌ๊ธฐ๋ฅผ malloc์„ ์ด์šฉํ•ด์„œ ๋ฐฐ๊ฐ€ํ•  ๋•Œ ๊ฐ’๋“ค์„ ์ž˜ ๋ณต์‚ฌํ•ด์„œ ๋„ฃ์Œ์œผ๋กœ์จ capacity-1๋กœ ๋ณต์‚ฌํ•  ์›์†Œ ์ˆ˜๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๋‘ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์˜ ์ฝ”๋“œ๋ฅผ ํ•œ ๋ฒˆ ์ž‘์„ฑํ•ด๋ด…์‹œ๋‹ค.

์ด ์ฝ”๋“œ์—์„œ ํ•จ์ˆ˜ copy(a, b, c)๋Š” ์œ„์น˜ a์—์„œ b-1๊นŒ์ง€์˜ ์›์†Œ๋ฅผ c์—์„œ ์‹œ์ž‘ํ•˜๋Š” ์œ„์น˜๋กœ ๋ณต์‚ฌํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

void addq(element item)
{
	rear = (rear + 1) % MAX_QUEUE_SIZE;
	if (front == rear)
		queueFUll();
	queue[rear] = item;
}

void queueFUll()
{
	// ์ด์ „ ํ์˜ ํฌ๊ธฐ๋ฅผ ๋‘ ๋ฐฐ๋กœ ํ™•์žฅ
	element* newQueue;
	MALLOC(newQueue, 2 * capacity * sizeof(*queue));

	// ํ์˜	๋ฐ์ดํ„ฐ๋ฅผ ์ƒˆ๋กœ์šด ํ๋กœ ๋ณต์‚ฌ
	int start = (front + 1) % capacity;
	if (start < 2)
		copy(queue + start, queue + start + capacity - 1, newQueue);
	else
	{
		copy(queue + start, queue + capacity, newQueue);
		copy(queue, queue + rear + 1, newQueue + capacity - start);
	}

	// ์ƒˆ๋กœ์šด ํ์˜ ์ •๋ณด๋ฅผ ์—…๋ฐ์ดํŠธ
	front = 2 * capacity - 1;
	rear = capacity - 2;
	capacity *= 2;
	free(queue);
	queue = newQueue;
}

์›ํ˜• ํ๊ฐ€ ๋ฆฌ์ŠคํŠธ์—์„œ ํ•˜๋‚˜์˜ segment์ผ ๊ฒฝ์šฐ

 

์›ํ˜• ํ๊ฐ€ ๋ฆฌ์ŠคํŠธ์—์„œ ๋‘ ๊ฐœ์˜ ์„ธ๊ทธ๋จผํŠธ๋กœ ๋‚˜๋ˆ ์งˆ ๊ฒฝ์šฐ

 

 

๋‹ค์Œ ์žฅ์—์„œ๋Š” ์Šคํƒ๊ณผ ํ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฌธ์ œ๋“ค์„ ๊ณต๋ถ€ํ•ด๋ด…์‹œ๋‹ค.๐Ÿ˜†