트리(Tree)

계층적 관계를 표현하는 자료구조이다.

 

트리의 활용

 - 기업 조직도

 - DBMS

 - 디렉터리 구조

 

트리 관련 용어

 

노드(Node): 트리의 구성요소

간선(Edge): 노드와 노드를 연결하는 연결선

루트 노드(Root Node): 트리 구조에서 최상위에 존재하는 노드

단말 노드(Terminal Node): 아래로 또 다른 노드가 연결되어 있지 않은 노드

내부 노드(Internal Node): 단말 노드를 제외한 모든 노드

 

트리의 종류

 

이진트리(Binary Tree): 모든 노드가 최대 2개의 서브 노드를 가지는 트리

서브트리(Sub Tree): 기존 트리에서 하위의 트리구조

포화 이진 트리(Full Binary Tree): 트리의 각 레벨에 노드가 가득 차있는 이진트리

완전 이진 트리(Complete Binary Tree): 트리의 마지막 레벨을 제외한 모든 레벨이 가득 차있는 이진트리

이진 탐색 트리(Binary Search Tree):  효율적인 탐색을 위한 이진트리 기반의 자료구조


이진 트리의 추상 자료형

 

데이터

 

연산

init(): 초기화

isEmpty(): 비어있는지 확인

createTree(): 이진 트리 생성

getRoot(): 이진 트리의 루트 노드 반환

getCount(): 이진트리의 노드 개수 반환

getLeafCount(): 이친트리의 단말 노드 개수 반환

getHeight(): 이진 트리의 높이 반환


 

'개인 공부 > 자료구조' 카테고리의 다른 글

우선순위 큐(Priority Queue), 힙(Heap)  (2) 2023.01.25
정렬(Sorting)#1  (0) 2023.01.18
덱(Deque)  (0) 2023.01.04
큐(Queue)  (0) 2023.01.04
스택(Stack)  (0) 2023.01.04

큐(Queue)

스택과 달리 선입선출의 구조를 가지는 자료구조이다.

 

큐의 특징

 - 먼저 집어 넣은 데이터가 먼저 나오는 선입선출(FIFO: First In First Out)의 구조를 가진다.

 - front 부분에서 삭제 연산, rear 부분에서 삽입 연산이 이루어진다.

 

선형 큐와 원형 큐

 

 - 선형 큐: 1차원 배열로 구성된 큐. front는 큐의 첫 번째 요소를 가리키고 rear는 큐의 마지막 요소를 가리킨다.

 - 원형 큐: 선형 큐의 문제점을 보완하기 위한 자료구조. front와 rear의 값이 배열의 끝에 도달하면 다음에 증가되는 값은 0이 된다.

 

큐의 활용

 - 먼저 들어온 순서대로 처리되어야 하는 작업 등 광범위하게 사용

 - 속도나 시간의 차이를 극복하기 위한 임시 기억 장치로 사용 = 버퍼(buffer)


큐의 추상 자료형

 

데이터

 

연산

init(): 큐의 초기화

isEmpty(): 큐가 비어있는지 확인

isFull(): 큐가 가득찾는지 확인

Enqueue(): 큐에 데이터를 저장

Dequeue(): 큐의 마지막 원소 삭제

Peek(): 저장 순서가 가장 앞선 데이터 반환 

size(): 요소의 개수 반환


c에서 연결 리스트를 기반으로 한 큐의 구현입니다.

#include <stdio.h>
#include <stdlib.h>

typedef int Data;

typedef struct LinkedNode {
	Data data;
	struct LinkedNode* link;
} Node;

Node* front = NULL;
Node* rear = NULL;

void init() {
	front = NULL;
	rear = NULL;
}

int isEmpty() {
	return front == NULL;
}

void Enqueue(Data data) {
	Node* p = (Node*)malloc(sizeof(Node));
	p->data = data;
	p->link = NULL;
	if (isEmpty()) front = rear = p;
	else {
		rear->link = p;
		rear = p;
	}
}

int Dequeue() {
	Node* p;
	Data data;

	p = front;
	data = p->data;
	front = front->link;

	if (front == NULL) rear = NULL;

	free(p);

	return data;
}

int peek() {
	return front->data;
}

int size() {
	Node* p;
	int count = 0;
	for (p = front; p != NULL; p = p->link) count++;

	return count;
}

int main() {
	init();
	printf("isEmpty : %d\n\n", isEmpty());

	for (int i = 0; i < 5; i++) {
		Enqueue(i);
		printf("Enqueue : %d\n", i);
	}

	printf("\nisEmpty : %d\n", isEmpty());
	
	printf("\nsize : %d\n", size());
	printf("peek : %d\n\n", peek());

	for (int i = 0; i < 2; i++) {
		printf("Dequeue : %d\n", Dequeue());
	}

	printf("\nsize : %d\n", size());
	printf("peek : %d\n", peek());

	return 0;
}

 

'개인 공부 > 자료구조' 카테고리의 다른 글

트리(Tree)  (0) 2023.01.04
덱(Deque)  (0) 2023.01.04
스택(Stack)  (0) 2023.01.04
리스트(List)#2  (1) 2023.01.04
리스트(List)#1  (0) 2022.12.30

연결 리스트(Linked List)

메모리의 동적 할당을 기반으로 하는 리스트

 

연결 리스트의 구조

 - 노드(Node): 아래 그림의 상자 같은 데이터 덩어리, 데이터 필드(data field)와 링크 필드(link field)로 구성

연결 리스트에서의 노드의 구조
int형을 저장하는 노드 구조체

 - 헤드 포인터(Head Pointer): 첫 번째 노드의 주소를 저장하는 포인터

 

연결 리스트의 특징

 

 - 노드들은 메모리의 어느 곳에나 위치할 수 있다. => 노드들의 주소가 연결 리스트 상의 순서와 동일하지 않다.

 - 연속적인 기억공간이 없어도 데이터를 저장하는 것이 가능하며, 동적으로 생성하기에 미리 공간을 확보할 필요가 없다.

 - 링크필드를 위한 추가 공간이 필요하다.

 - 배열에 비해 연산의 구현이나 사용 방법이 복잡하다.

 - 오류가 없더라도 메모리의 동적 할당과 해제가 빈번하게 일어나면 프로그램이 느려질 수 있다.

 

연결 리스트의 종류

 

단순 연결 리스트(Singly Linked List): 하나의 방향으로만 연결

원형 연결 리스트(Circular Linked List): 단순 연결 리스트와 같으나 마지막 노드의 링크 값이 첫 번째 노드를 가리킴

이중 연결 리스트(Doubly Linked List): 각 노드마다 포인트가 2개씩 존재하여 선행 노드와 후속 노드를 모두 가리키는게 가능

연결 리스트의 3가지 종류


연결 리스트의 추상 자료형

 

데이터

같은 타입의 요소들이 순서를 가지고 저장된 데이터

 

연산

init(): 리스트의 초기화

insert(): 요소 삽입

delete(): 요소 삭제

get(): 요소 반환

isEmpty(): 리스트가 비어있는지 확인

replace(): 요소 교체

size(): 요소의 개수 반환

find(): 요소가 있는지 확인

clear(): 리스트를 비움


아래는 c에서의 단순 연결 리스트의 구현입니다.

#include <stdio.h>
#include <stdlib.h>

typedef int Data;

typedef struct LinkedNode {
	Data data;
	struct LinkedNode* link;
} Node;

Node* head = NULL;

void init() {
	head = NULL;
}

int isEmpty() {
	return head == NULL;
}

void insert_next(Node* before, Node* node) {
	if (node != NULL) {
		node->link = before->link;
		before->link = node;
	}
}

Node* get_entry(int pos) {
	Node* p = head;
	for (int i = 0; i < pos; i++) {
		if (p == NULL) return NULL;
		p = p->link;
	}

	return p;
}

void insert(int pos, Data data) {
	Node* newNode, * prev;
	
	newNode = (Node*)malloc(sizeof(Node));
	newNode->data = data;
	newNode->link = NULL;

	if (pos == 0) {
		newNode->link = head;
		head = newNode;
	}
	else {
		prev = get_entry(pos - 1);
		if (prev != NULL)
			insert_next(prev, newNode);
		else free(newNode);
	}
}

Node* remove_next(Node* before) {
	Node* removed = before->link;
	if (removed != NULL)
		before->link = removed->link;
	return removed;
}

void delete(int pos) {
	Node* prev, * removed;

	if (pos == 0 && !isEmpty()) {
		removed = head;
		head = head->link;
		free(removed);
	}
	else {
		prev = get_entry(pos - 1);
		if (prev != NULL) {
			removed = remove_next(prev);
			free(removed);
		}
	}
}

int get_data(int pos) {
	Node* p = head;
	for (int i = 0; i < pos; i++) {
		if (p == NULL) return -1;
		p = p->link;
	}

	return p->data;
}

void replace(int pos, Data data) {
	Node* p = get_entry(pos);
	if (p != NULL)
		p->data = data;
}

int size() {
	int count = 0;
	for (Node* p = head; p != NULL; p = p->link) count++;

	return count;
}

Node* find(Data data) {
	Node* p;
	for (p = head; p != NULL; p = p->link)
		if (p->data == data) return p;
	return NULL;
}

void clear() {
	while (!isEmpty()) delete(0);
}

int main() {
	init();

	printf("isEmpty : %d\n\n", isEmpty());

	for (int i = 0; i < 5; i++) {
		printf("Insert : %d\n", i * 10);
		insert(i, i * 10);
	}

	printf("\nisEmpty : %d\n\n", isEmpty());
	printf("size : %d\n\n", size());

	printf("get_data(3) : %d\n\n", get_data(3));

	printf("delete\n");
	delete(0); delete(0);

	printf("\nsize : %d\n", size());
	for (int i = 0; i < size(); i++) {
		printf("print data : %d\n", get_data(i));
	}

	printf("\nclear list\n");
	clear();

	printf("\nisEmpty : %d\n", isEmpty());
	printf("size : %d", size());

	return 0;
}

결과

 

'개인 공부 > 자료구조' 카테고리의 다른 글

덱(Deque)  (0) 2023.01.04
큐(Queue)  (0) 2023.01.04
스택(Stack)  (0) 2023.01.04
리스트(List)#1  (0) 2022.12.30
추상 자료형(Abstract Data Type, ADT)  (1) 2022.12.29

+ Recent posts