총 10분 중 11분
2001
시즌 2개, 그리고 영화
시즌 2: 5화 “아일랜드”
출연: 이나영, 김민준, 김민정, 현빈
장르: 애초에 역경을 딛고 이룩하는 숭고한 사랑이란 없다. 그 역경 자체가 사랑이다.
프로그램 특징: 그 곳에서 살아남는 사랑이 어떤 모습으로 걸어오는지 기다려 보고 싶다.
Algorithm/Data Structure [Linked List] Queue

Queue

Fisrt In First Out

<---- the other end (the front) ㅁ ㅁ ㅁ ㅁ ㅁ  one end(the rear) <----

<-- dequeue from the front --------<---  enqueue from the rear 

방향 진짜 중요하다 무조건 왼쪽으로 ~~ !!

enqueue, dequeue 모두 rear와 front를 가리키는 인덱스를 +1 해 item을 넣고 빼게 된다.
이때, rear idx가 [max]인 경우 front idx 부터 할당된 어레이까지 공간이 남아도 더 이상 enqueue가 되지 않는다는 한계가 있다.

Circular Queue

어레이를 동그랗게 이어서 여분 공간을 사용할 수 있도록 한다.

dequeue : 값을 내보내고 front = front  + 1 한다. 

enqueue: rear = rear + 1 에 넣는다.

보다시피 Empty, Full 모두 front == rear + 1 로 표현되는 문제가 있다.

Reserved space

Front가 가리키는 공간을 Reserved space로 두고, dequeue 시에는 front + 1 를 내보낸다.

front = (front + 1) % max_queue; 
result = queue[front]
  • Full Queue
    (rear + 1) % maxQueue == front
  • Empty Queue
    front == rear

Linked List

포인터는 변수다. 포인터가 가리키는 대상에 따라 포인터가 특정 **타입** 을 가지게 된다.

우리는 NodeType의 주소를 가져야 하기 때문에 포인터는 모두 NodeType* ptr; 를 가진다. (int* 아닌 이유가 궁금했다.)

template<class ItemType>
struct NodeType {
	ItemType value;
    NodeType * next;
}

template<class ItemType>
class QueueType 
{
private:
	NodeType<ItemType> * pFront;
    NdoeType<ItemType> * pRear;
    
public:
	QueueType();
    ~QueueType();
    void enqueue(ItemType value);
    void dequeue(ItemType & value);
    void clear();
    int size() const;
    bool isFull() const;
    bool isEmpty() const;
}

-> 해석하는 방법

이런식으로 접근하면 헷갈린다. 잊지 말아야 할 건 new_node가 포인터라는 거다. 포인터는 가리키는 객체 멤버에 접근할 때 무조건 -> 을 이용한다. new_node.value = new_value; 를 할 수 없는 이유 또한 new_node가 포인터이기 때문이다. 객체 중에서 멤버를 고를 때 .(점 연산자)를 이용하는데 포인터는 객체 상자를 가리키고 있기에 . 을 쓰면 컴파일 오류가 난다.  

void QueueType::enqueue(ItemType new_value){
	NodeType* new_node;
    new_node = new NodeType;
    
    new_node -> value = new_value; 
    new_node -> next = nullptr;
    /*
    pRear -> next = new_node; //지금 가리키는 (직전 마지막)의 next를 최신으로 이어놓고
    pRear = new_node; // 자신은 최신을 가리킨다.
    */
    
    // edge condition : Empty()
    // when the queue is empty, pFront should be updated to point to new_node !
 	if (! isEmpty()){ // 비어있었다면 직전 노드가 없어서 next가 없다. 
    	pRear->next = new_node;
    } else { pFront = new_node;};
    pRear = new_node;
}

뇌 빼고 있다보니 왜 새 객체 new_node 를 포인터로 가지는 지 백지 코딩할 때 이유를 못 찾았다.

 Dynamic Allocation: 

힙은 프로그램 실행(런타임) 중에 메모리를 할당받기 때문에 할당된 메모리의 주소를 저장할 필요가 있다. 그때 주소를 저장할 수 있는 변수가 포인터고 !! 그래서 new 는 항상 포인터로 생성하고 delete 하는 것을 잊지 말자!! 

void QueueType::dequeue(ItemType & ret_value){
	NodeType* tempPtr;
    tempPtr = pFront;
    
    ret_value = pFront -> value;
    pFront = pFront -> next;
    delete tempPtr;
    
    //edege : Empty 
    if (isEmpty()){ pRear = nullptr; }
}

dequeue하면 front는 -1 일까 +1 일까?

이게 왜 자꾸 헷갈리는 지 모르겠는데.. 뭔가 내보내니까 -1 (어레이적 관점) 해야 할 것 같아서 pFront = pFront -> next 가 아니라 이전 노드의 next를 nullptr로 업데이트해줘야 할 것만 같다. (심지어 가능한 구현인지도 모르겟슴)

아무튼 큐는 앞으로 앞 뒤가 없는 친구니까 !! ㅁㅁㅁㅁㅁ <- 요 놈을 내보낸다고 생각하지 말고  

이 놈을 잡아 뺀다고 생각해야 한다. -> ㅁㅁㅁㅁㅁ / 넣을 때는 ㅁㅁㅁㅁㅁ<- 얘를 넣은 거다

큐는 들어가고 나오는 공간이 다르니까 구분하려다보니 더 헷갈려졌다. 방향만 잘 잡으면 안 헷갈리겠다. <- 왼쪽으로 넣고 빼세요 

 

'Algorithm > Data Structure' 카테고리의 다른 글

[Contiguous data structures] List  (1) 2024.10.20
Algorithm/Data Structure [Linked List] Queue