SourceCode
int main(void) { int *x; int *y; x = malloc(sizeof(int)); *x = 42; *y = 13; }→ 초기화 되지 않은 *y는 오류를 발생시킬 수도 있다.
y = x; *y = 13;→ 추가하게 되면 y는 x와 같은 곳을 가리키게 되므로 13이 저장된다.
포인터를 초기화시키지 않고 값을 저장하면 어떤 오류를 발생할 수 있을까요?
→ 기존에 있는 데이터를 의도치 않게 변경하는 오류가 발생할 수 있다.
SourceCode
새로운 변수를 선언, 메모리할당한 후 값 복사#include <stdio.h> #include <stdlib.h> int main(void) { //int 자료형 3개로 이루어진 list 라는 포인터를 선언하고 메모리 할당 int *list = malloc(3 * sizeof(int)); // 포인터가 잘 선언되었는지 확인 if (list == NULL) { return 1; } // list 배열의 각 인덱스에 값 저장 list[0] = 1; list[1] = 2; list[2] = 3; //int 자료형 4개 크기의 tmp 라는 포인터를 선언하고 메모리 할당 int *tmp = malloc(4 * sizeof(int)); if (tmp == NULL) { return 1; } // list의 값을 tmp로 복사 for (int i = 0; i < 3; i++) { tmp[i] = list[i]; } // tmp배열의 네 번째 값도 저장 tmp[3] = 4; // list의 메모리를 초기화 free(list); // list가 tmp와 같은 곳을 가리키도록 지정 list = tmp; // 새로운 배열 list의 값 확인 for (int i = 0; i < 4; i++) { printf("%i\n", list[i]); } // list의 메모리 초기화 free(list); }realloc 함수로 값 복사
#include <stdio.h> #include <stdlib.h> int main(void) { int *list = malloc(3 * sizeof(int)); if (list == NULL) { return 1; } list[0] = 1; list[1] = 2; list[2] = 3; // tmp 포인터에 메모리를 할당하고 list의 값 복사 int *tmp = realloc(list, 4 * sizeof(int)); if (tmp == NULL) { return 1; } // list가 tmp와 같은 곳을 가리키도록 지정 list = tmp; // 새로운 list의 네 번째 값 저장 list[3] = 4; // list의 값 확인 for (int i = 0; i < 4; i++) { printf("%i\n", list[i]); } //list 의 메모리 초기화 free(list); }
이미 할당된 메모리 크기를 조절할 때 임시 메모리를 새로 할당해줘야 하는 이유는 무엇일까요?
→ 데이터는 연속적으로 저장되기 때문에 할당된 메모리 다음 공간에 저장된 데이터에 영향을 주지 않기 위해서

SourceCode
연결리스트를 간단한 구조체로 정의typedef struct node { int number; struct node *next; } node;→ number는 각 node가 가지는 값
→ *next는 다음 node를 가리키는 포인터
→ typedef struct가 아닌 typedef struct node 라고 명시하는 것은 구조체 안에서 node를 사용하기 위함 !
연결 리스트를 배열과 비교하였을 때 장단점은 무엇이 있을까요?
→ 배열에 비해 삽입과 삭제가 용이하다는 장점과 다음 배열의 주소도 함께 저장해야해서 추가적으로 메모리가 더 필요하다는 단점이 있다.
SourceCode
구조체로 연결 리스트 구현#include <stdio.h> #include <stdlib.h> //연결 리스트의 기본 단위가 되는 node 구조체를 정의합니다. typedef struct node { //node 안에서 정수형 값이 저장되는 변수를 name으로 지정합니다. int number; //다음 node의 주소를 가리키는 포인터를 *next로 지정합니다. struct node *next; } node; int main(void) { // list라는 이름의 node 포인터를 정의합니다. 연결 리스트의 가장 첫 번째 node를 가리킬 것입니다. // 이 포인터는 현재 아무 것도 가리키고 있지 않기 때문에 NULL 로 초기화합니다. node *list = NULL; // 새로운 node를 위해 메모리를 할당하고 포인터 *n으로 가리킵니다. node *n = malloc(sizeof(node)); if (n == NULL) { return 1; } // n의 number 필드에 1의 값을 저장합니다. “n->number”는 “(*n).numer”와 동일한 의미입니다. // 즉, n이 가리키는 node의 number 필드를 의미하는 것입니다. // 간단하게 화살표 표시 ‘->’로 쓸 수 있습니다. n의 number의 값을 1로 저장합니다. n->number = 1; // n 다음에 정의된 node가 없으므로 NULL로 초기화합니다. n->next = NULL; // 이제 첫번째 node를 정의했기 떄문에 list 포인터를 n 포인터로 바꿔 줍니다. list = n; // 이제 list에 다른 node를 더 연결하기 위해 n에 새로운 메모리를 다시 할당합니다. n = malloc(sizeof(node)); if (n == NULL) { return 1; } // n의 number와 next의 값을 각각 저장합니다. n->number = 2; n->next = NULL; // list가 가리키는 것은 첫 번째 node입니다. //이 node의 다음 node를 n 포인터로 지정합니다. list->next = n; // 다시 한 번 n 포인터에 새로운 메모리를 할당하고 number과 next의 값을 저장합니다. n = malloc(sizeof(node)); if (n == NULL) { return 1; } n->number = 3; n->next = NULL; // 현재 list는 첫번째 node를 가리키고, 이는 두번째 node와 연결되어 있습니다. // 따라서 세 번째 node를 더 연결하기 위해 첫 번째 node (list)의 // 다음 node(list->next)의 다음 node(list->next->next)를 n 포인터로 지정합니다. list->next->next = n; // 이제 list에 연결된 node를 처음부터 방문하면서 각 number 값을 출력합니다. // 마지막 node의 next에는 NULL이 저장되어 있을 것이기 때문에 이 것이 for 루프의 종료 조건이 됩니다. for (node *tmp = list; tmp != NULL; tmp = tmp->next) { printf("%i\n", tmp->number); } // 메모리를 해제해주기 위해 list에 연결된 node들을 처음부터 방문하면서 free 해줍니다. while (list != NULL) { node *tmp = list->next; free(list); list = tmp; } }
연결 리스트의 중간에 node를 추가하거나 삭제하는 코드는 어떻게 작성할 수 있을까요?
→ 다음 값을 가리키는 주소를 변경해주면 된다.
ex) 이전 노드 before, 추가하거나 변경할 노드 now, 다음 노드 next라고 정의하자.
배열이 정렬되어 있지 않은 경우의 검색 소요 시간을 연결 리스트의 검색 시간과 비교해보세요.
→ 둘 다 하나씩 탐색해봐야하므로 O(n)이라고 생각한다.

SourceCode
이진 검색 함수
(이진 검색 트리의 노드 구조체와 50을 검색)//이진 검색 트리의 노드 구조체 typedef struct node { // 노드의 값 int number; // 왼쪽 자식 노드 struct node *left; // 오른쪽 자식 노드 struct node *right; } node; // 이진 검색 함수 (*tree는 이진 검색 트리를 가리키는 포인터) bool search(node *tree) { // 트리가 비어있는 경우 ‘false’를 반환하고 함수 종료 if (tree == NULL) { return false; } // 현재 노드의 값이 50보다 크면 왼쪽 노드 검색 else if (50 < tree->number) { return search(tree->left); } // 현재 노드의 값이 50보다 작으면 오른쪽 노드 검색 else if (50 > tree->number) { return search(tree->right); } // 위 모든 조건이 만족하지 않으면 노드의 값이 50이므로 ‘true’ 반환 else { return true; } }
값을 검색할 때 이진 검색 트리가 기본 연결 리스트에 비해 가지는 장점과 단점은 무엇이 있을까요?
→ 검색 범위를 반으로 줄여나갈 수 있는 장점이 있고 삽입과 삭제가 복잡하다는 단점이 있다.

해시 함수는 어떻게 만들 수 있을까요?
→ 분류 기준을 만들고 함수를 만들면 될 것 같다.
: 기본적으로 트리 형태의 자료 구조이다.

문자열의 길이에 한정된다.트라이가 해시 테이블에 비해 가지는 장점과 단점은 무엇일까요?
→ 검색이 용이하다는 장점이 있지만 메모리가 많이 필요하다는 단점이 있다.
선입 선출 or FIFO(First In First Out) 방식을 따름후입 선출 or ‘LIFO(Last In First Out) 방식을 따름키와 값이라는 요소로 구성됨키를 어떻게 정의할 것인지가 중요함