[ํ์ ์คํฌ๋ฆฝํธ] ๊ฐ์ฒด์งํฅ์ ์ผ๋ก Generic Stack<T> ํด๋์ค ๊ตฌํํ๊ธฐ
ํ๋ก๊ทธ๋๋ฐ์ ๊ฝ, ๊ฐ์ฒด์งํฅ์ ๊ฝ ์ ๋ค๋ฆญ
์ ๋ค๋ฆญ์ ์ด๋ ๊ฐ๋ ํต์์ ์ผ๋ก ๋ณผ ์ ์๋ค.(์ฌ์ฌ์ฉ์ฑ์ด ๊ต์ฅํ ๋๊ธฐ ๋๋ฌธ)
์ด์ ํฌ์คํ stack์ ๋จ์ ์ ์ค๋ก์ง stringํ๋ง push, pop ํ ์ ์๋ค๋ ๊ฒ์ด๋ค.
๋ค์ํ ํ์ ์ push, pop ํ๊ณ ์ถ๋ค๋ฉด ์ ๋ค๋ฆญ์ ์ด์ฉํด์ ํ์ฉ์ฑ๊ณผ ์ฌ์ฌ์ฉ์ฑ์ ๋์ผ ์ ์๋ค.
์ ์ฐํ๊ณ ํ์ ๋ ๋ณด์ฅํ ์ ์๊ณ , ์ฌ์ฌ์ฉ์ ์ ๋ง ๋ง์ด ๋์ผ ์ ์๋ ์ ๋ค๋ฆญ์ ๋ง์คํฐํด๋ณธ๋ค.
(์คํ์์ค๋ API ๋ฌธ์๋ฅผ ๋ณผ ๋ ์ ๋ค๋ฆญ์ ์๊ณ ์๋ค๋ฉด ๋งํ์์ด ์ฝ์ ์ ์๋ค.)
๊ฐ์ข ์ ๋ค๋ฆญ ์๋ฃ๊ตฌ์กฐ๋ค๋ 'ํด๋์ค'์ด๋ค.
๊ฐ๋ น C#์ stack<T> ํด๋์ค๋ ๋ค์ ๋งํฌ์ ๊ฐ๋ค.
https://docs.microsoft.com/ko-kr/dotnet/api/system.collections.generic.stack-1?view=net-6.0
Stack<T> ํด๋์ค (System.Collections.Generic)
์ง์ ํ ๋์ผ ํ์์ ์ธ์คํด์ค๋ก ์ด๋ฃจ์ด์ง ๊ฐ๋ณ ํฌ๊ธฐ LIFO(ํ์ ์ ์ถ) ๋ฐฉ์์ ์ปฌ๋ ์ ์ ๋ํ๋ ๋๋ค.
docs.microsoft.com
์ ์
์ง์ ํ ๋์ผ ํ์์ ์ธ์คํด์ค๋ก ์ด๋ฃจ์ด์ง ๊ฐ๋ณ ํฌ๊ธฐ LIFO(ํ์ ์ ์ถ) ๋ฐฉ์์ ์ปฌ๋ ์ ์ ๋ํ๋ ๋๋ค.
public class Stack<T> : System.Collections.Generic.IEnumerable<T>, System.Collections.Generic.IReadOnlyCollection<T>, System.Collections.ICollection
ํ์ ๋งค๊ฐ ๋ณ์
์คํ์ ์๋ ์์์ ํ์์ ์ง์ ํฉ๋๋ค.
์์
๊ตฌํ
using System;
using System.Collections.Generic;
class Example
{
public static void Main()
{
Stack<string> numbers = new Stack<string>();
numbers.Push("one");
numbers.Push("two");
numbers.Push("three");
numbers.Push("four");
numbers.Push("five");
// A stack can be enumerated without disturbing its contents.
foreach( string number in numbers )
{
Console.WriteLine(number);
}
Console.WriteLine("\nPopping '{0}'", numbers.Pop());
Console.WriteLine("Peek at next item to destack: {0}",
numbers.Peek());
Console.WriteLine("Popping '{0}'", numbers.Pop());
// Create a copy of the stack, using the ToArray method and the
// constructor that accepts an IEnumerable<T>.
Stack<string> stack2 = new Stack<string>(numbers.ToArray());
Console.WriteLine("\nContents of the first copy:");
foreach( string number in stack2 )
{
Console.WriteLine(number);
}
// Create an array twice the size of the stack and copy the
// elements of the stack, starting at the middle of the
// array.
string[] array2 = new string[numbers.Count * 2];
numbers.CopyTo(array2, numbers.Count);
// Create a second stack, using the constructor that accepts an
// IEnumerable(Of T).
Stack<string> stack3 = new Stack<string>(array2);
Console.WriteLine("\nContents of the second copy, with duplicates and nulls:");
foreach( string number in stack3 )
{
Console.WriteLine(number);
}
Console.WriteLine("\nstack2.Contains(\"four\") = {0}",
stack2.Contains("four"));
Console.WriteLine("\nstack2.Clear()");
stack2.Clear();
Console.WriteLine("\nstack2.Count = {0}", stack2.Count);
}
}
/* This code example produces the following output:
five
four
three
two
one
Popping 'five'
Peek at next item to destack: four
Popping 'four'
Contents of the first copy:
one
two
three
Contents of the second copy, with duplicates and nulls:
one
two
three
stack2.Contains("four") = False
stack2.Clear()
stack2.Count = 0
*/
1. C# ์ฒ๋ผ ๋ชจ๋ ํ์ ๋ช ์ํด์ฃผ๋ฉด์ ์์ฑํด๋ณด๊ธฐ
string
interface Stack<T> {
readonly size: number;
push(value: T): void;
pop(): T;
}
type StackNode<T> = {
readonly value: T;
readonly next?: StackNode<T>;
};
class StackImpl<T> implements Stack<T> {
private _size: number = 0;
//head๋ StackNode๋ฅผ ๋ฐ๋ผ๋ณผ ์๋, ์ ๋ฐ๋ผ๋ณด๊ณ ์์ ์๋ ์์(StackNode|undefined ๋ก ์ฐ๋ ๋์ , optional๋ก ์ง์ )
private head?: StackNode<T>;
constructor(private capacity?: number) {}
get size() {
return this._size;
}
push(value: T): void {
//์ง๊ธ ์ฌ์ด์ฆ๊ฐ ์ ํด์ง ์ฉ๋๊ณผ ๋๊ฐ๋ค๋ฉด(๊ฝ ์ฐฌ ์ํ๋ผ๋ฉด ใ
ใ
)
if (this.capacity !== undefined) {
if (this.size === this.capacity) {
throw new Error("Stack is Full!!");
}
}
//node๋ StackNode(์ฌ์ฉ์ ์ง์ ๋
ธ๋)๋ผ๋ ๋ฐ์ดํฐํ์
์ ๋ฐ๋ผ๊ฐ๋ ๋
ธ๋๋ก,
//value๋ผ๋ ํค์ ์ ๋ฌ๋ฐ์ value๋ฅผ ํ ๋น๋ฐ๋๋ฐ ์ด๋ฆ์ด ๋๊ฐ์์ ๊ตณ์ด value:value๋ผ๊ณ ์ธ ํ์์์ด value๋ผ๊ณ ๋ง ์์ฑ
//next๋ head๊ฐ ๊ธฐ์กด์ ๋ฐ๋ผ๋ณด๊ณ ์๋ ๊ฒ์ ๊ฐ๋ฆฌํค๋ฉด ๋จ!!!
const node: StackNode<T> = { value, next: this.head };
//node๋ ์๋ก ๋ค์ด์จ ์์ด์ด๊ณ , head๋ ๋ค์ ์๋ก๋ค์ด์จ ๋
ธ๋๋ฅผ ๋ฐ๋ผ๋ณด๊ฒ ํ๋ค.
this.head = node;
this._size++;
}
pop(): T {
//์คํ์ด ๋น์ด์๋ ๊ฒฝ์ฐ์ node๊ฐ ์์ ์๋ ์๋ค.
//๊ทธ๋ฌ๋ API ์์ฒด์์ string | undefined๋ฅผ ํด์ฃผ๋ฉด ๋ค์ด๊ฐ ๋ ๋ง๋ค null check๋ฅผ ํ๊ฒ๋์ ๋ณ๋ก๊ณ ,(๊ฐ์ด ์๋์ง ์๋์ง ๋งค๋ฒ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ํ๋ ๊ผด)
//ํญ์ ์๊ณ , ๋ฆฌํดํ ์ค๋น๊ฐ ๋์ด์๋ค๊ณ ์ง์ ํ๋ ๋์ ์ ์๋ if๋ฌธ ์์ฑ
// null == undefined, null !== undefined
if (this.head == null) {
throw new Error("Stack is empty!");
}
//ํค๋๊ฐ ๋ฐ๋ผ๋ณด๊ณ ์๋ ๋
ธ๋์ value๋ฅผ ๋ฆฌํดํด์ฃผ๊ธฐ ์ํ ๊ธฐ์ด์์
(1)
const node = this.head;
//head๊ฐ ๋ค์ ์ด์ ๋
ธ๋๋ฅผ ๋ฐ๋ผ๋ณด๋๋ก ์ง์ (์ฌ์ค์ ์ฌ๊ธฐ์ ์ฐ๊ฒฐ๋๊น)
this.head = node.next;
//์คํ ์ฌ์ด์ฆ ์ค์ฌ์ฃผ๊ธฐ
this._size--;
//ํค๋๊ฐ ๋ฐ๋ผ๋ณด๊ณ ์๋ ๋
ธ๋์ value๋ฅผ ๋ฆฌํด(pop๋๊ณ ์ด์ ์ฌ์ค์ ๋ฌด์๋จ)
return node.value;
}
}
const stack: StackImpl<string> = new StackImpl<string>();
console.log(stack);
stack.push("๋ก๋ณถ์ด");
console.log(stack);
stack.push("์๋");
console.log(stack);
stack.push("ํผ์");
console.log(stack);
stack.push("๋ผ๋ฉด");
console.log(stack);
console.log(stack.pop());
console.log(stack);
console.log("์คํ์ ๋น์๋ด
์๋ค!");
while (stack.size != 0) {
console.log(stack.pop());
}
console.log(stack.pop());
2. ํ์ ์คํฌ๋ฆฝํธ ๊ฐ์ฑ์ผ๋ก ํ์ ์ฃผ์๋ง ๋ฌ๊ธฐ
object
interface Stack<T> {
readonly size: number;
push(value: T): void;
pop(): T;
}
type StackNode<T> = {
readonly value: T;
readonly next?: StackNode<T>;
};
class StackImpl<T> implements Stack<T> {
private _size: number = 0;
//head๋ StackNode๋ฅผ ๋ฐ๋ผ๋ณผ ์๋, ์ ๋ฐ๋ผ๋ณด๊ณ ์์ ์๋ ์์(StackNode|undefined ๋ก ์ฐ๋ ๋์ , optional๋ก ์ง์ )
private head?: StackNode<T>;
constructor(private capacity?: number) {}
get size() {
return this._size;
}
push(value: T): void {
//์ง๊ธ ์ฌ์ด์ฆ๊ฐ ์ ํด์ง ์ฉ๋๊ณผ ๋๊ฐ๋ค๋ฉด(๊ฝ ์ฐฌ ์ํ๋ผ๋ฉด ใ
ใ
)
if (this.capacity !== undefined) {
if (this.size === this.capacity) {
throw new Error("Stack is Full!!");
}
}
//node๋ StackNode(์ฌ์ฉ์ ์ง์ ๋
ธ๋)๋ผ๋ ๋ฐ์ดํฐํ์
์ ๋ฐ๋ผ๊ฐ๋ ๋
ธ๋๋ก,
//value๋ผ๋ ํค์ ์ ๋ฌ๋ฐ์ value๋ฅผ ํ ๋น๋ฐ๋๋ฐ ์ด๋ฆ์ด ๋๊ฐ์์ ๊ตณ์ด value:value๋ผ๊ณ ์ธ ํ์์์ด value๋ผ๊ณ ๋ง ์์ฑ
//next๋ head๊ฐ ๊ธฐ์กด์ ๋ฐ๋ผ๋ณด๊ณ ์๋ ๊ฒ์ ๊ฐ๋ฆฌํค๋ฉด ๋จ!!!
const node: StackNode<T> = { value, next: this.head };
//node๋ ์๋ก ๋ค์ด์จ ์์ด์ด๊ณ , head๋ ๋ค์ ์๋ก๋ค์ด์จ ๋
ธ๋๋ฅผ ๋ฐ๋ผ๋ณด๊ฒ ํ๋ค.
this.head = node;
this._size++;
}
pop(): T {
//์คํ์ด ๋น์ด์๋ ๊ฒฝ์ฐ์ node๊ฐ ์์ ์๋ ์๋ค.
//๊ทธ๋ฌ๋ API ์์ฒด์์ string | undefined๋ฅผ ํด์ฃผ๋ฉด ๋ค์ด๊ฐ ๋ ๋ง๋ค null check๋ฅผ ํ๊ฒ๋์ ๋ณ๋ก๊ณ ,(๊ฐ์ด ์๋์ง ์๋์ง ๋งค๋ฒ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ํ๋ ๊ผด)
//ํญ์ ์๊ณ , ๋ฆฌํดํ ์ค๋น๊ฐ ๋์ด์๋ค๊ณ ์ง์ ํ๋ ๋์ ์ ์๋ if๋ฌธ ์์ฑ
// null == undefined, null !== undefined
if (this.head == null) {
throw new Error("Stack is empty!");
}
//ํค๋๊ฐ ๋ฐ๋ผ๋ณด๊ณ ์๋ ๋
ธ๋์ value๋ฅผ ๋ฆฌํดํด์ฃผ๊ธฐ ์ํ ๊ธฐ์ด์์
(1)
const node = this.head;
//head๊ฐ ๋ค์ ์ด์ ๋
ธ๋๋ฅผ ๋ฐ๋ผ๋ณด๋๋ก ์ง์ (์ฌ์ค์ ์ฌ๊ธฐ์ ์ฐ๊ฒฐ๋๊น)
this.head = node.next;
//์คํ ์ฌ์ด์ฆ ์ค์ฌ์ฃผ๊ธฐ
this._size--;
//ํค๋๊ฐ ๋ฐ๋ผ๋ณด๊ณ ์๋ ๋
ธ๋์ value๋ฅผ ๋ฆฌํด(pop๋๊ณ ์ด์ ์ฌ์ค์ ๋ฌด์๋จ)
return node.value;
}
}
const stack: StackImpl<object> = new StackImpl();
stack.push({ name: "์ ์งฑ๊ตฌ" });
console.log(stack);
stack.push({ name: "์ ์งฑ์" });
console.log(stack);
stack.push({ name: "ํฐ๋ฅ์ด" });
console.log(stack);
stack.push({ name: "์ก์
๊ฐ๋ฉด" });
console.log(stack);
console.log(stack.pop());
console.log(stack);
console.log("์คํ์ ๋น์๋ด
์๋ค!");
while (stack.size != 0) {
console.log(stack.pop());
}
console.log(stack.pop());
3. ์ ๋ค๋ฆญ ํ์ ๋ง ํ์ ํด์ฃผ๊ธฐ
boolean ํ ํ ์คํธ
interface Stack<T> {
readonly size: number;
push(value: T): void;
pop(): T;
}
type StackNode<T> = {
readonly value: T;
readonly next?: StackNode<T>;
};
class StackImpl<T> implements Stack<T> {
private _size: number = 0;
//head๋ StackNode๋ฅผ ๋ฐ๋ผ๋ณผ ์๋, ์ ๋ฐ๋ผ๋ณด๊ณ ์์ ์๋ ์์(StackNode|undefined ๋ก ์ฐ๋ ๋์ , optional๋ก ์ง์ )
private head?: StackNode<T>;
constructor(private capacity?: number) {}
get size() {
return this._size;
}
push(value: T): void {
//์ง๊ธ ์ฌ์ด์ฆ๊ฐ ์ ํด์ง ์ฉ๋๊ณผ ๋๊ฐ๋ค๋ฉด(๊ฝ ์ฐฌ ์ํ๋ผ๋ฉด ใ
ใ
)
if (this.capacity !== undefined) {
if (this.size === this.capacity) {
throw new Error("Stack is Full!!");
}
}
//node๋ StackNode(์ฌ์ฉ์ ์ง์ ๋
ธ๋)๋ผ๋ ๋ฐ์ดํฐํ์
์ ๋ฐ๋ผ๊ฐ๋ ๋
ธ๋๋ก,
//value๋ผ๋ ํค์ ์ ๋ฌ๋ฐ์ value๋ฅผ ํ ๋น๋ฐ๋๋ฐ ์ด๋ฆ์ด ๋๊ฐ์์ ๊ตณ์ด value:value๋ผ๊ณ ์ธ ํ์์์ด value๋ผ๊ณ ๋ง ์์ฑ
//next๋ head๊ฐ ๊ธฐ์กด์ ๋ฐ๋ผ๋ณด๊ณ ์๋ ๊ฒ์ ๊ฐ๋ฆฌํค๋ฉด ๋จ!!!
const node: StackNode<T> = { value, next: this.head };
//node๋ ์๋ก ๋ค์ด์จ ์์ด์ด๊ณ , head๋ ๋ค์ ์๋ก๋ค์ด์จ ๋
ธ๋๋ฅผ ๋ฐ๋ผ๋ณด๊ฒ ํ๋ค.
this.head = node;
this._size++;
}
pop(): T {
//์คํ์ด ๋น์ด์๋ ๊ฒฝ์ฐ์ node๊ฐ ์์ ์๋ ์๋ค.
//๊ทธ๋ฌ๋ API ์์ฒด์์ string | undefined๋ฅผ ํด์ฃผ๋ฉด ๋ค์ด๊ฐ ๋ ๋ง๋ค null check๋ฅผ ํ๊ฒ๋์ ๋ณ๋ก๊ณ ,(๊ฐ์ด ์๋์ง ์๋์ง ๋งค๋ฒ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ํ๋ ๊ผด)
//ํญ์ ์๊ณ , ๋ฆฌํดํ ์ค๋น๊ฐ ๋์ด์๋ค๊ณ ์ง์ ํ๋ ๋์ ์ ์๋ if๋ฌธ ์์ฑ
// null == undefined, null !== undefined
if (this.head == null) {
throw new Error("Stack is empty!");
}
//ํค๋๊ฐ ๋ฐ๋ผ๋ณด๊ณ ์๋ ๋
ธ๋์ value๋ฅผ ๋ฆฌํดํด์ฃผ๊ธฐ ์ํ ๊ธฐ์ด์์
(1)
const node = this.head;
//head๊ฐ ๋ค์ ์ด์ ๋
ธ๋๋ฅผ ๋ฐ๋ผ๋ณด๋๋ก ์ง์ (์ฌ์ค์ ์ฌ๊ธฐ์ ์ฐ๊ฒฐ๋๊น)
this.head = node.next;
//์คํ ์ฌ์ด์ฆ ์ค์ฌ์ฃผ๊ธฐ
this._size--;
//ํค๋๊ฐ ๋ฐ๋ผ๋ณด๊ณ ์๋ ๋
ธ๋์ value๋ฅผ ๋ฆฌํด(pop๋๊ณ ์ด์ ์ฌ์ค์ ๋ฌด์๋จ)
return node.value;
}
}
const stack = new StackImpl<boolean>();
stack.push(true);
console.log(stack);
stack.push(false);
console.log(stack);
stack.push(true);
console.log(stack);
stack.push(false);
console.log(stack);
console.log(stack.pop());
console.log(stack);
console.log("์คํ์ ๋น์๋ด
์๋ค!");
while (stack.size != 0) {
console.log(stack.pop());
}
console.log(stack.pop());
4. ์ ๋ค๋ฆญ ํ์ , ํ์ ์ฃผ์ ์๋ตํ๊ณ ์์ ์ถ๋ก ์ํค๊ธฐ
number๋ก ํ ์คํธ
interface Stack<T> {
readonly size: number;
push(value: T): void;
pop(): T;
}
type StackNode<T> = {
readonly value: T;
readonly next?: StackNode<T>;
};
class StackImpl<T> implements Stack<T> {
private _size: number = 0;
//head๋ StackNode๋ฅผ ๋ฐ๋ผ๋ณผ ์๋, ์ ๋ฐ๋ผ๋ณด๊ณ ์์ ์๋ ์์(StackNode|undefined ๋ก ์ฐ๋ ๋์ , optional๋ก ์ง์ )
private head?: StackNode<T>;
constructor(private capacity?: number) {}
get size() {
return this._size;
}
push(value: T): void {
//์ง๊ธ ์ฌ์ด์ฆ๊ฐ ์ ํด์ง ์ฉ๋๊ณผ ๋๊ฐ๋ค๋ฉด(๊ฝ ์ฐฌ ์ํ๋ผ๋ฉด ใ
ใ
)
if (this.capacity !== undefined) {
if (this.size === this.capacity) {
throw new Error("Stack is Full!!");
}
}
//node๋ StackNode(์ฌ์ฉ์ ์ง์ ๋
ธ๋)๋ผ๋ ๋ฐ์ดํฐํ์
์ ๋ฐ๋ผ๊ฐ๋ ๋
ธ๋๋ก,
//value๋ผ๋ ํค์ ์ ๋ฌ๋ฐ์ value๋ฅผ ํ ๋น๋ฐ๋๋ฐ ์ด๋ฆ์ด ๋๊ฐ์์ ๊ตณ์ด value:value๋ผ๊ณ ์ธ ํ์์์ด value๋ผ๊ณ ๋ง ์์ฑ
//next๋ head๊ฐ ๊ธฐ์กด์ ๋ฐ๋ผ๋ณด๊ณ ์๋ ๊ฒ์ ๊ฐ๋ฆฌํค๋ฉด ๋จ!!!
const node: StackNode<T> = { value, next: this.head };
//node๋ ์๋ก ๋ค์ด์จ ์์ด์ด๊ณ , head๋ ๋ค์ ์๋ก๋ค์ด์จ ๋
ธ๋๋ฅผ ๋ฐ๋ผ๋ณด๊ฒ ํ๋ค.
this.head = node;
this._size++;
}
pop(): T {
//์คํ์ด ๋น์ด์๋ ๊ฒฝ์ฐ์ node๊ฐ ์์ ์๋ ์๋ค.
//๊ทธ๋ฌ๋ API ์์ฒด์์ string | undefined๋ฅผ ํด์ฃผ๋ฉด ๋ค์ด๊ฐ ๋ ๋ง๋ค null check๋ฅผ ํ๊ฒ๋์ ๋ณ๋ก๊ณ ,(๊ฐ์ด ์๋์ง ์๋์ง ๋งค๋ฒ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ํ๋ ๊ผด)
//ํญ์ ์๊ณ , ๋ฆฌํดํ ์ค๋น๊ฐ ๋์ด์๋ค๊ณ ์ง์ ํ๋ ๋์ ์ ์๋ if๋ฌธ ์์ฑ
// null == undefined, null !== undefined
if (this.head == null) {
throw new Error("Stack is empty!");
}
//ํค๋๊ฐ ๋ฐ๋ผ๋ณด๊ณ ์๋ ๋
ธ๋์ value๋ฅผ ๋ฆฌํดํด์ฃผ๊ธฐ ์ํ ๊ธฐ์ด์์
(1)
const node = this.head;
//head๊ฐ ๋ค์ ์ด์ ๋
ธ๋๋ฅผ ๋ฐ๋ผ๋ณด๋๋ก ์ง์ (์ฌ์ค์ ์ฌ๊ธฐ์ ์ฐ๊ฒฐ๋๊น)
this.head = node.next;
//์คํ ์ฌ์ด์ฆ ์ค์ฌ์ฃผ๊ธฐ
this._size--;
//ํค๋๊ฐ ๋ฐ๋ผ๋ณด๊ณ ์๋ ๋
ธ๋์ value๋ฅผ ๋ฆฌํด(pop๋๊ณ ์ด์ ์ฌ์ค์ ๋ฌด์๋จ)
return node.value;
}
}
const stack = new StackImpl();
stack.push(1);
console.log(stack);
stack.push(2);
console.log(stack);
stack.push(3);
console.log(stack);
stack.push(4);
console.log(stack);
console.log(stack.pop());
console.log(stack);
console.log("์คํ์ ๋น์๋ด
์๋ค!");
while (stack.size != 0) {
console.log(stack.pop());
}
console.log(stack.pop());