스택의 검색
스택의 용도
큐의 삽입
void enqueue(int n){
s_nums[s_back] = n;
s_back = (s_back + 1) % MAX_NUMS; // 원형 큐를 만들어주는 연산, s_back+1 이 MAX_NUMS와 같으면 s_back은 0으로
s_num_count++;
}
큐의 삭제
int deque(void){
int ret;
ret = s_nums[s_front];
--s_num_count;
s_front = (s_front + 1) % MAX_NUMS;
return ret;
}
큐의 검색
큐의 용도
연결 리스트는 매우 훌륭한 면접문제
자료들이 메모리에 산재해 있다.
노드에 다음 데이터를 가리키는 포인터가 있다. (마지막은 노드는 널포인터)
연결 리스트의 검색
연결 리스트 전체를 출력하는 예제
typedef struct node {
int value;
node_t* next;
} node_t;
void print_node(const node_t* head){
node_t* p;
p = head;
while (p != NULL){
/* 출력 */
p = p->next
}
}
헤드 노드
NULL
(아직 가리킬 것이 없다)free()
를 생각연결리스트를 다 사용하고 할당받은 메모리를 해제할 코드
void destroy(node_t* head){
node_t* p = head;
while(p != NULL){
node_t* next = p->next;
free(p);
p = next;
}
}
a
, c
노드 사이에 b
노드를 추가하려면?a
노드의 포인터 -> b
위치로 변경b
노드의 포인터 -> c
위치로 변경연결 리스트 맨 앞에 삽입하는 코드
head
-> first_insert
head
-> second_insert
-> first_insert
3줄 요약
head
가 가리키던 주소를 new_node
의 next 값에 대입한다.head
가 가리키는 주소 값을 new_node
의 주소값으로 바꿔준다.// 맨 앞에 삽입하는 코드
void insert_front(node_t** phead, int n){
node_t* new_node;
new_node = malloc(sizeof(node_t));
new_node->value = n;
new_node->next = *phead;
*phead = new_node;
}
int main(void){
node_t* head = NULL;
insert_front(&head, 3);
destroy(head);
head = NULL;
}
왜 phead
는 이중 포인터인가?
main
함수에 선언된 head
변수의 원본 값을 변경해주기 위해서오름차순을 유지하면서 삽입하는 코드
void insert_soerted(node_t** phead, int n){
node_t** pp;
node_t* new_node;
new_node = malloc(sizeof(node_t));
new_node->value = n;
pp = phead;
while (*pp != NULL){
if((*pp)->value >= n){
break;
}
pp = &(*pp)->next;
}
new_node->next = *pp;
*pp = new_node;
}
int main(void){
node_t* head = NULL;
insert_front(&head, 2);
insert_front(&head, 5);
insert_front(&head, 3);
destroy(head);
head = NULL;
}
void remove(node_t** phead, int n){
node_t** pp;
pp = phead;
while (*pp != NULL){
if((*pp)->value == n){
node_t* tmp = *pp; // 삭제할 노드의 다음노드 임시저장
*pp = (*pp)->next;
free(tmp);
break;
}
pp = &(*pp)->next;
}
}
int main(void){
node_t* head = NULL;
remove(&head, 2);
remove(&head, 5);
destroy(head);
head = NULL;
}
해시테이블 만드는 과정
임의의 크기를 가진 데이터를 고정크기
의 값에 대응하게 하는 함수
32비트정수
입력값이 같으면 출력값은 언제나 같다.
입력값은 다른데 출력값이 같을 수 있다. (해시충돌)
데이터 -> 해시함수 -> 해시값
해시 충돌이 적을 수록 좋은 해시함수
키 배열, 값 배열 2개의 배열로 만들 수 있다.
같은 인덱스에 매핑되는 쌍이 저장되어있다.
해시충돌을 방지할 수 있다면?
char*
문자열을 저장하려고 동적메모리할당 안해도된다.
키값이 문자열로 구성된 해시테이블이라면, 키배열에 문자열을 저장하지 않아도 된다.
해시값만 저장해도된다(해시충돌이 없기때문에 가능)
해시충돌을 방지할 수 있는 조건?
찾은 색인 위치 이후에 빈 공간을 찾아 저장
배열에서 비어있는 위치를 알 수 있어야한다
실제 값을 저장해야함
#define TRUE(1)
#define FALSE(0)
#define SIZE(23) // 소수로 크기 설정
int s_numbers[SIZE];
void init_hashtable(void){
/* 극한 값 혹은 배열에 입력될 수 없는 값으로 초기화 */
}
// 해시테이블에 값이 있는지 찾는 코드
int has_value(int value){
int i;
int start_index;
start_index = value % SIZE;
if(start_index < 0){
start_index += SIZE;
}
i = start_index;
do {
if (s_number[i] == value){
return TRUE;
} else if (s_number[i] == INIT_VAL){
return FALSE;
}
i = (i+1) % SIZE;
}while(i != start_index);
return FALSE;
}
assert
로 잡고 배열크기 늘려주는 방식도 있다.