스택과 스택의 노드 

 

링크드 리스트는 배열과 달리 인덱스로 노드에 접근할 수 없습니다. 

리스트를 쓰면 배열과는 달리 용량에 제한을 두지 않아도 된다는 장점이 있습니다. 

그러나 '인덱스'가 없기 때문에 자신의 위에 위치하는 노드를 가리키는 포인터가 필요합니다. 

( 자신의 위에 위치한다: 스택 구조에서 자기 노드를 기준으로 최상위 노드 방향을 '위'라고 한 것입니다. )

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

 

스택의 구조체입니다. 

배열과는 다르게 최대길이, 최상위 노드의 인덱스가 필요 없습니다. 

그 대신 리스트의 헤드와 테일을 가리키는 포인터가 필요합니다. 

스택의 구조체에서 

헤드는 리스트의 '시작점'을 뜻하고, 테일은 '최상위 노드'를 가리킵니다. 

 

typedef struct LLStack {
	Node* list;
	Node* top;
}LLStack;

 

 

스택생성

 

먼저, 스택을 자유저장소(==스택메모리)에 생성하는 CreateStack() 함수를 만듭니다. 

 

void CreateStack(LLStack** stack) {

	(*stack) = (LLStack*)malloc(sizeof(LLStack));
	(*stack)->list = NULL;
	(*stack)->top = NULL;

}

 

 

노드 생성 

노드 만큼의 메모리를 할당 합니다. 

문자열의 길이와 NULL문자에 필요한 1을  포함한 길이의 메모리를 할당받습니다. 

그곳을 newNode의 data가 가리키도록 합니다. 

자유저장소에 문자열을 저장해야 하므로, strcpy()를 이용하여 저장합니다. 

strcpy() 와 strlen() 함수를 쓰려면 #include <string.h> 선언이 필요합니다.  

Node* CreateNode(char* data) {

	Node* newNode = (Node*)malloc(sizeof(Node));
	newNode->data = (char*)malloc(strlen(data) + 1);
	strcpy(newNode->data, data);
	newNode->nextNode = NULL;

	return newNode;
}

 

 

노드를 메모리에서 해제 

문자열을 가리키는 포인터를 메모리에서 해제 후, 노드를 메모리에서 해제합니다. 

void FreeNode(Node* targetNode) {
	free(targetNode->data);
	free(targetNode);
}

 

스택을 메모리에서 해제 

 

스택 제거에 앞서 노드들을 메모리에서 전부 해제합니다.

마지막으로 스택을 메모리 해제 합니다. 

// 스택의 메모리해제 
void FreeStack(LLStack* targetStack) {

	while (!IsEmpty(targetStack)) {
		Node* popped = Pop(targetStack);
		FreeNode(popped);
	}

	free(targetStack);
}

 

 

 

Push 연산 

 

스택이 비었다면 새 노드가 헤드노드가 됩니다. 

그렇지 않다면, 테일 노드를 찾아서 그 뒤에 새 노드를 붙입니다. 

/* Push */
void Push(LLStack* stack, Node* newNode) {
	printf("[ Push ] %s 삽입 \n", newNode->data);

	if (NULL == stack->list) { // 스택이 비었다면, 뉴노드가 헤드.
		stack->list = newNode;
	}
	else {
		// 테일 노드를 찾아서, 그 뒤에 뉴 노드를 붙인다.

		Node* tempNode = stack->list;

		while (NULL != tempNode->nextNode) {
			tempNode = tempNode->nextNode;
		}

		tempNode->nextNode = newNode;
	}

	stack->top = newNode;
}

 

 다음과 같이 'top' 뒤에 새노르를 추가해도 됩니다. 

void Push(LLStack* stack, Node* newNode) {

	if (stack->top == NULL) {
		stack->list = newNode;
	}
	else {  // 테일 뒤에 붙인다 
		stack->top->nextNode = newNode;
	}

	stack->top = newNode;
}

 

 

 

Pop 연산

 

Pop 연산은 두 가지 경우를 처리합니다.  

헤드가 탑인 경우 (스택에 노드가 하나 밖에 없다)

탑 직전 노드를 찾아야 하는 경우 (탑 직전 노드를 탑 노드로 갱신해준다)

Node* Pop(LLStack* stack) {

	Node* topNode = stack->top;
	   
	Node* current = stack->list;

	if (current == topNode) { // 헤드가 탑이라면, 1개 남은 노드를 제거하는 상황.
		stack->top = NULL;
		stack->list = NULL;
	}
	else { 	// top의 직전 노드를 찾는다

		while (current->nextNode != stack->top) {
			current = current->nextNode;
		}

		current->nextNode = NULL;
		stack->top = current;		//top 갱신
	}
	
	return topNode;
}

 

 

스택이 비어있는지 확인 

int IsEmpty(LLStack* stack) {
	return (NULL == stack->list);
}

 

 

스택에 노드가 몇개 있는지 확인 

int GetSize(LLStack* stack) {
	
	Node* temp = stack->list;
	int count = 0;

	while (temp != NULL) {

		temp = temp->nextNode;
		count++;

	}

	return count;
}

 

728x90

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

링크드 큐  (0) 2020.03.10
순환 큐  (0) 2020.03.09
배열로 구현하는 스택  (0) 2020.02.18
환형 링크드 리스트  (0) 2020.02.17
더블 링크드 리스트  (0) 2020.02.14

+ Recent posts