배열 포인터
#include <stdio.h>
int main() {
int arr[6] = {1, 2, 3, 4, 5, 6};
int* parr = arr;
printf("Sizeof(arr) : %d \n", sizeof(arr));
printf("Sizeof(parr) : %d \n", sizeof(parr));
}
/*
Sizeof(arr) : 24
Sizeof(parr) : 8
*/
&
)와 사용될 때 경우를 빼면, 배열의 이름을 사용시 암묵적으로 첫 번째 원소를 가리키는 포인터로 타입이 변환되기때문!#include <stdio.h>
int main() {
int arr[3] = {1, 2, 3};
int (*parr)[3] = &arr;
printf("arr[1] : %d \n", arr[1]);
printf("parr[1] : %d \n", (*parr)[1]);
}
&arr
은 주소값 연산자가 앞에 붙었기때문에 암묵적 변환이 일어나지 않는다. 그래서 더블포인터가 아님. arr이 크기가 3인 배열이기 때문에 &arr
을 보관할 포인터는 크기가 3인 배열을 가리키는 포인터가 되어야함.int(*parr)[3]
는 배열 포인터다.*
연산자를 통해 원래의 arr을 참조해야함. 따라서 (*parr)[1]
과 arr[1]
은 같은게 된다.함수
int (*pmax)(int, int);
→ 함수 포인터 pmax의 정의 → ‘이 함수 포인터 pmax는 함수 리턴값이 int형이고, 인자 두 개가 각각 int인 함수를 가리킨다. (인자가 없으면 괄호 안을 비워두면 됨)pmax = max
문자열
getchar()
: stdin 에서 한개의 문자를 읽어와서 그 값을 리턴한다. → scanf()
에서 %c
형식으로 사용하게 될때(권장 하진 않지만, 간혹 써야할 때) 다음 scanf()
를 쓰기 위해 버퍼를 비워줄때 쓴다.(이전 scanf()
에서 엔터때문에 개행이 버퍼에 남아있음)char*
가 아닌 const char *
로 가리켜야한다.전역변수
정적변수(static)
동적할당(malloc)
void *
형이다. 그래서 자료형 *
형변환 해주면 된다.free()
는 할당받은 메모리를 다 쓰고 난 후에 메모리 영역을 다시 컴퓨터에게 돌려주는 역할.free()
를 제대로 하지 않아 발생되는 문제를 메모리 누수라고 한다.이진 탐색 트리
이진탐색트리란 다음과 같은 특징을 갖는 이진트리를 말한다. (이진트리 - 각 노드의 자식 노드가 최대 2개인 트리)
이진 탐색 트리는 기존 이진트리보다 탐색이 빠르다. 이진 탐색 트리의 탐색 연산은 트리의 높이가 h이라면 O(h)의 시간 복잡도를 갖는다.
이진 탐색 트리의 탐색 과정
이진 탐색 트리 삽입 과정
이진 탐색 트리 삭제 과정
Red-Black-Tree
개념
속성
rb트리 균형잡는 법
rb트리 삽입 방식
삽입되는 노드는 항상 red다. → why? 삽입 후에도 5번 속성을 만족하기 위해
노드를 삽입할 때 두 nil노드의 색은 black으로 고정한다. → 그러면 자연스럽게 3번 속성을 만족
red로 삽입했기 때문에 2번 속성 위반한다. → 그래서 루트 노드를 black으로 바꾸면 해결
case 3 : 4번 속성(노드가 red라면 자녀들은 black)을 위반할 때 → 구조를 바꿔준 뒤에 BST 특징 또한 유지되어야 한다. → 구조를 바꾸면서도 BST의 특징을 유지시키는 방법은 회전이다.
회전을 어떻게 사용할까? → 20과 50의 색깔을 바꿔준다 → 50을 기준으로 오른쪽으로 회전한다. → 해결 → rbtree 조건 모두 해결
case2 : 꺾인 부분을 펴줘서 case3과 같은 형태로 만들고 case3와 같은 방식으로 해결 가능
20기준으로 왼쪽으로 회전한다. → 회전 후 case3형태가 됨 → 40과 50의 색을 바꾸고 → 50기준으로 오른쪽 회전한다. → rbtree 조건 모두 해결
case1 : red 삽입 후 4번 속성을 위반했을 때 → 삽인된 red 노드의 부모도 red & 삼촌(부모의 형제)도 red라면 부모와 삼촌을 black으로 바꾸고 할아버지를 red로 바꾼 뒤 할아버지에서 다시 확인을 시작한다. → 할아버지 색깔이 레드였는데 루트면 블랙으로 바꿔주어야한다.
rbtree의 삭제방식
삭제 전 rb트리 속성 만족한 상태
삭제 방식은 일반적은 BST와 동일
삭제 후 rb 트리 속성 위반 여부 확인
rb 트리 속성을 위반했다면 재조정
rb 트리 속성을 다시 만족
cf) rb트리에서 노드를 삭제할 때 어떤 색이 삭제 되는지가 속성 위반 여부를 확인할 때 매우 중요
rbtree의 삭제에서 속성 위반 여부 확인은 삭제되는 색을 통해 알수 있다. (여기서 자녀는 유효한 값을 가진 자녀)
속성 위반 여부 확인
위반 해결하기
노드 위치 옮기기 (transplant)
실질적으로 특성을 유지시키는 것은 CASE 2와 4이고, CASE 1은 CASE 2,3에 맞게 변환시켜주는 역할, CASE 3은 CASE 4에 맞게 변환 시켜주는 역할이다.
이번 주엔 드디어 C언어가 시작되었다. RED-BLACK-TREE 자료구조를 구현해보면서 익숙하지 않다는 걸 느꼈다. 구조체에 대한 개념이 많이 부족했었는데, BST, RB-TREE를 하면서 확실히 익숙해진 것 같다. 과제 테스트 케이스는 통과했는데 제출용 테스트 케이스를 통과하지 못해서 당황했다. 그래서 kantwang님과 함께 어디서 잘못된건지 찾아보면서 오류를 잡았다. 오류를 찾는 재미도 있었고 찾으면서 헷갈렸던 malloc, calloc에 대해서도 복기하게 되었다. 사실 RB-TREE 개념에 대해서는 RB-TREE 구조를 유지하면서 노드를 삽입, 삭제하려면 RB-TREE를 유지하기 위한 규칙들이 위반되는 케이스들이 있는데 이 위반 케이스들을 해결하려면 이런 방법들이 있구나 정도만 이해하고 넘어갔다. 왜냐하면 내가 생각한 이번과제의 목표는 기계친화적인 C언어를 하면서 컴퓨터와 친해지는 것이라 생각했기 때문이다. RB-TREE 구조를 완벽히 이해하는 것 보다 복잡한 자료구조를 구현해보면서 malloc-lab, 웹 프록시, pintos프로젝트들을 하기위해 이번주 과제를 하는 것이라 생각했다. 확실히 C언어가 익숙해졌다!
단체 회식이 이번주에 있었는데, 코치님과 많은 대화를 할 수 있었다. 대화를 하며 내가 정글이 목표로 하는 방향으로 잘 가고 있다는 생각이 들었다. 어제 몰랐던걸 오늘은 알게되며 매일 성장중이다. 성장속도가 빠르진 않지만 확실히 어제보단 나은 오늘을 실천하며 살고있다. 오늘에 최선을 다하면 분명 내일은 오늘보다 나을 것이다. 조바심을 갖지말고 꾸준함이 중요하다라는걸 어느때보다 크게 느낀 한 주였다.
WEEK05 구현 소스코드 - https://github.com/yeopto/rbtree-lab/blob/main/src/rbtree.c