๊ฐ์ ํ์ ์ ๋ฐ์ดํฐ๋ฅผ ์ฐ์๋ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ์ ์ฅํ๋ ์๋ฃ๊ตฌ์กฐ
๋ฐฐ์ด: int arr[5] = {10, 20, 30, 40, 50};
๋ฉ๋ชจ๋ฆฌ:
์ฃผ์ | 1000 | 1004 | 1008 | 1012 | 1016 |
--------|------|------|------|------|------|
์ธ๋ฑ์ค | 0 | 1 | 2 | 3 | 4 |
๊ฐ | 10 | 20 | 30 | 40 | 50 |
์ฐ์๋ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ์ ์ฅ โ
// ์ ์ธ
int arr[5];
// ์ ์ธ๊ณผ ๋์์ ์ด๊ธฐํ
int arr[5] = {10, 20, 30, 40, 50};
// ๋ถ๋ถ ์ด๊ธฐํ (๋๋จธ์ง๋ 0)
int arr[5] = {10, 20}; // {10, 20, 0, 0, 0}
// ๋ชจ๋ 0์ผ๋ก ์ด๊ธฐํ
int arr[5] = {0};
// ํฌ๊ธฐ ์๋ต (์ปดํ์ผ๋ฌ๊ฐ ์๋ ๊ณ์ฐ)
int arr[] = {10, 20, 30}; // ํฌ๊ธฐ: 3
int arr[5] = {10, 20, 30, 40, 50};
// ์ฝ๊ธฐ
int value = arr[2]; // 30
// ์ฐ๊ธฐ
arr[2] = 100; // {10, 20, 100, 40, 50}
// ์๊ฐ๋ณต์ก๋: O(1) โ (์ธ๋ฑ์ค๋ก ์ง์ ์ ๊ทผ)
์ธ๋ฑ์ค ๊ณ์ฐ ๊ณต์:
์ฃผ์ = ์์์ฃผ์ + (์ธ๋ฑ์ค ร ๋ฐ์ดํฐํฌ๊ธฐ)
arr[2]์ ์ฃผ์ = 1000 + (2 ร 4) = 1008
(int๋ 4๋ฐ์ดํธ)
// ์ ํ ํ์ (Linear Search)
int search(int arr[], int size, int key) {
for (int i = 0; i < size; i++) {
if (arr[i] == key) {
return i; // ์ฐพ์ ์ธ๋ฑ์ค ๋ฐํ
}
}
return -1; // ๋ชป ์ฐพ์
}
// ์๊ฐ๋ณต์ก๋: O(N)
์์:
arr[] = {10, 20, 30, 40, 50}
key = 30 ์ฐพ๊ธฐ
๋น๊ต 1: arr[0] = 10 โ 30
๋น๊ต 2: arr[1] = 20 โ 30
๋น๊ต 3: arr[2] = 30 = 30 โ ์ฐพ์!
์ต์
์ ๊ฒฝ์ฐ: N๋ฒ ๋น๊ต (๋งจ ๋ ๋๋ ์์)
int arr[10] = {10, 20, 30, 40, 50};
int size = 5;
// ๋งจ ๋ค์ 60 ์ฝ์
arr[size] = 60;
size++;
// ๊ฒฐ๊ณผ: {10, 20, 30, 40, 50, 60}
// ์๊ฐ๋ณต์ก๋: O(1) โ
void insertAt(int arr[], int *size, int index, int value) {
// ๋ค์์๋ถํฐ ํ ์นธ์ฉ ์ด๋
for (int i = *size; i > index; i--) {
arr[i] = arr[i - 1];
}
arr[index] = value;
(*size)++;
}
// ์๊ฐ๋ณต์ก๋: O(N) โ
์์: ์ธ๋ฑ์ค 2์ 25 ์ฝ์
์ด๊ธฐ: {10, 20, 30, 40, 50}
0 1 2 3 4
1๋จ๊ณ: ๋ค์์๋ถํฐ ์ด๋
{10, 20, 30, 40, 50, 50} // 50 ๋ณต์ฌ
{10, 20, 30, 40, 40, 50} // 40 ๋ณต์ฌ
{10, 20, 30, 30, 40, 50} // 30 ๋ณต์ฌ
2๋จ๊ณ: ํด๋น ์์น์ ์ฝ์
{10, 20, 25, 30, 40, 50}
0 1 2 3 4 5
์ด๋ ํ์: 3๋ฒ (size - index)
int arr[10] = {10, 20, 30, 40, 50};
int size = 5;
// ๋งจ ๋ค ์ญ์
size--;
// ๊ฒฐ๊ณผ: {10, 20, 30, 40} (50์ ๋ฌด์๋จ)
// ์๊ฐ๋ณต์ก๋: O(1) โ
void deleteAt(int arr[], int *size, int index) {
// ์์ผ๋ก ํ ์นธ์ฉ ์ด๋
for (int i = index; i < *size - 1; i++) {
arr[i] = arr[i + 1];
}
(*size)--;
}
// ์๊ฐ๋ณต์ก๋: O(N) โ
์์: ์ธ๋ฑ์ค 2 ์ญ์
์ด๊ธฐ: {10, 20, 30, 40, 50}
0 1 2 3 4
1๋จ๊ณ: ์์ผ๋ก ์ด๋
{10, 20, 40, 40, 50} // arr[2] = arr[3]
{10, 20, 40, 50, 50} // arr[3] = arr[4]
2๋จ๊ณ: ํฌ๊ธฐ ๊ฐ์
{10, 20, 40, 50}
0 1 2 3
์ด๋ ํ์: 2๋ฒ (size - index - 1)
arr[100] = 10; // O(1) - ์ธ๋ฑ์ค๋ก ๋ฐ๋ก ์ ๊ทผ
int arr[100]; // ์ ์ธ๋ง ํ๋ฉด ๋จ
๋ฐ์ดํฐ๋ง ์ ์ฅ (ํฌ์ธํฐ ๋ถํ์)
int ๋ฐฐ์ด: 4๋ฐ์ดํธ ร N๊ฐ = 4N ๋ฐ์ดํธ
์ฐ์๋ ๋ฉ๋ชจ๋ฆฌ โ CPU ์บ์ ํจ์จ ๋์
โ ์ฑ๋ฅ ํฅ์
int arr[5]; // ํฌ๊ธฐ 5๋ก ๊ณ ์
// 6๊ฐ๋ฅผ ์ ์ฅํ๊ณ ์ถ์ผ๋ฉด? โ ์ ๋ฐฐ์ด ์์ฑ ํ์
// ์ค๊ฐ์ ์ฝ์
/์ญ์ ์ O(N)
// ๋ชจ๋ ์์๋ฅผ ์ด๋ํด์ผ ํจ
int arr[1000]; // 1000๊ฐ ์ ์ธ
// ์ค์ 10๊ฐ๋ง ์ฌ์ฉ โ 990๊ฐ ๋ญ๋น
int arr[5];
// ๋ฐํ์์ ํฌ๊ธฐ ๋ณ๊ฒฝ ๋ถ๊ฐ๋ฅ
// (๋์ ๋ฐฐ์ด ์ ์ธ)
int findMax(int arr[], int size) {
int max = arr[0];
for (int i = 1; i < size; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
int findMin(int arr[], int size) {
int min = arr[0];
for (int i = 1; i < size; i++) {
if (arr[i] < min) {
min = arr[i];
}
}
return min;
}
// ์๊ฐ๋ณต์ก๋: O(N)
void reverse(int arr[], int size) {
int temp;
for (int i = 0; i < size / 2; i++) {
// ์ ๋์ ๊ตํ
temp = arr[i];
arr[i] = arr[size - 1 - i];
arr[size - 1 - i] = temp;
}
}
// ์๊ฐ๋ณต์ก๋: O(N)
์์:
์ด๊ธฐ: {10, 20, 30, 40, 50}
0 1 2 3 4
๊ตํ 1: arr[0] โ arr[4]
{50, 20, 30, 40, 10}
๊ตํ 2: arr[1] โ arr[3]
{50, 40, 30, 20, 10}
์ค๊ฐ(arr[2])์ ๊ทธ๋๋ก
int removeDuplicates(int arr[], int size) {
if (size == 0) return 0;
int newSize = 1; // ์ฒซ ์์๋ ํญ์ ํฌํจ
for (int i = 1; i < size; i++) {
int isDuplicate = 0;
// ์ด์ ์์๋ค๊ณผ ๋น๊ต
for (int j = 0; j < newSize; j++) {
if (arr[i] == arr[j]) {
isDuplicate = 1;
break;
}
}
// ์ค๋ณต์ด ์๋๋ฉด ์ถ๊ฐ
if (!isDuplicate) {
arr[newSize] = arr[i];
newSize++;
}
}
return newSize;
}
// ์๊ฐ๋ณต์ก๋: O(Nยฒ)
์์:
์ด๊ธฐ: {10, 20, 10, 30, 20, 40}
์ฒ๋ฆฌ:
10 โ ์ถ๊ฐ (์ฒซ ์์)
20 โ ์ถ๊ฐ (์ค๋ณต ์๋)
10 โ ์ ์ธ (์ค๋ณต)
30 โ ์ถ๊ฐ (์ค๋ณต ์๋)
20 โ ์ ์ธ (์ค๋ณต)
40 โ ์ถ๊ฐ (์ค๋ณต ์๋)
๊ฒฐ๊ณผ: {10, 20, 30, 40}
// ์ ์ธ
int arr[3][4]; // 3ํ 4์ด
// ์ด๊ธฐํ
int arr[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
// ์ผ๊ด ์ด๊ธฐํ
int arr[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
arr[3][4]:
๋
ผ๋ฆฌ์ ๊ตฌ์กฐ:
col0 col1 col2 col3
row0 [1] [2] [3] [4]
row1 [5] [6] [7] [8]
row2 [9] [10] [11] [12]
์ค์ ๋ฉ๋ชจ๋ฆฌ (์ฐ์ ๋ฐฐ์น):
[1][2][3][4][5][6][7][8][9][10][11][12]
int arr[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
// ํ ์ฐ์ ์ํ
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
// ์ถ๋ ฅ:
// 1 2 3 4
// 5 6 7 8
// 9 10 11 12
arr[i][j]์ ์ฃผ์ = ์์์ฃผ์ + ((i ร ์ด๊ฐ์) + j) ร ๋ฐ์ดํฐํฌ๊ธฐ
์: arr[1][2]์ ์ฃผ์
= 1000 + ((1 ร 4) + 2) ร 4
= 1000 + 6 ร 4
= 1000 + 24
= 1024
๋ ธ๋๋ค์ด ํฌ์ธํฐ๋ก ์ฐ๊ฒฐ๋ ์๋ฃ๊ตฌ์กฐ
๋
ธ๋ ๊ตฌ์กฐ:
โโโโโโโโฌโโโโโโโ
โ data โ next โ โ next: ๋ค์ ๋
ธ๋์ ์ฃผ์
โโโโโโโโดโโโโโโโ
๋งํฌ๋ ๋ฆฌ์คํธ:
Head โ [10|โ] โ [20|โ] โ [30|โ] โ [40|NULL]
1000 2000 3000 4000
๋ฉ๋ชจ๋ฆฌ๋ ๋น์ฐ์์ ! โ
typedef struct Node {
int data; // ๋ฐ์ดํฐ
struct Node* next; // ๋ค์ ๋
ธ๋ ํฌ์ธํฐ
} Node;
Node* createNode(int data) {
Node* newNode = (Node*)malloc(sizeof(Node));
if (newNode == NULL) {
printf("Memory allocation failed\n");
return NULL;
}
newNode->data = data;
newNode->next = NULL;
return newNode;
}
void insertFront(Node** head, int data) {
Node* newNode = createNode(data);
newNode->next = *head; // ์ ๋
ธ๋๊ฐ ํ์ฌ head๋ฅผ ๊ฐ๋ฆฌํด
*head = newNode; // head๋ฅผ ์ ๋
ธ๋๋ก ๋ณ๊ฒฝ
}
// ์๊ฐ๋ณต์ก๋: O(1) โ
์์:
์ด๊ธฐ: Head โ [20|โ] โ [30|NULL]
10 ์ฝ์
:
1๋จ๊ณ: ์ ๋
ธ๋ ์์ฑ
[10|NULL]
2๋จ๊ณ: newNode->next = head
[10|โ] โ [20|โ] โ [30|NULL]
3๋จ๊ณ: head = newNode
Head โ [10|โ] โ [20|โ] โ [30|NULL]
void insertBack(Node** head, int data) {
Node* newNode = createNode(data);
// ๋ฆฌ์คํธ๊ฐ ๋น์ด์์ผ๋ฉด
if (*head == NULL) {
*head = newNode;
return;
}
// ๋ง์ง๋ง ๋
ธ๋ ์ฐพ๊ธฐ
Node* current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = newNode;
}
// ์๊ฐ๋ณต์ก๋: O(N) โ (๋ง์ง๋ง๊น์ง ์ํ)
์์:
์ด๊ธฐ: Head โ [10|โ] โ [20|NULL]
30 ์ฝ์
:
1๋จ๊ณ: ๋ง์ง๋ง ๋
ธ๋ ์ฐพ๊ธฐ
Head โ [10|โ] โ [20|NULL]
โ
current
2๋จ๊ณ: current->next = newNode
Head โ [10|โ] โ [20|โ] โ [30|NULL]
void insertAt(Node** head, int position, int data) {
Node* newNode = createNode(data);
// ๋งจ ์ ์ฝ์
if (position == 0) {
newNode->next = *head;
*head = newNode;
return;
}
// ์ด์ ๋
ธ๋ ์ฐพ๊ธฐ
Node* current = *head;
for (int i = 0; i < position - 1 && current != NULL; i++) {
current = current->next;
}
if (current == NULL) {
printf("Invalid position\n");
free(newNode);
return;
}
newNode->next = current->next;
current->next = newNode;
}
// ์๊ฐ๋ณต์ก๋: O(N)
์์: ์ธ๋ฑ์ค 2์ 25 ์ฝ์
์ด๊ธฐ: Head โ [10|โ] โ [20|โ] โ [30|NULL]
0 1 2
1๋จ๊ณ: position-1 (1๋ฒ) ๋
ธ๋ ์ฐพ๊ธฐ
Head โ [10|โ] โ [20|โ] โ [30|NULL]
โ
current
2๋จ๊ณ: newNode->next = current->next
current->next = newNode
๊ฒฐ๊ณผ: Head โ [10|โ] โ [20|โ] โ [25|โ] โ [30|NULL]
0 1 2 3
void deleteFront(Node** head) {
if (*head == NULL) {
printf("List is empty\n");
return;
}
Node* temp = *head;
*head = (*head)->next;
free(temp);
}
// ์๊ฐ๋ณต์ก๋: O(1) โ
์์:
์ด๊ธฐ: Head โ [10|โ] โ [20|โ] โ [30|NULL]
1๋จ๊ณ: temp = head
temp โ [10|โ] โ [20|โ] โ [30|NULL]
โ
Head
2๋จ๊ณ: head = head->next
Head โ [20|โ] โ [30|NULL]
temp โ [10|โ]
3๋จ๊ณ: free(temp)
Head โ [20|โ] โ [30|NULL]
void deleteBack(Node** head) {
if (*head == NULL) {
printf("List is empty\n");
return;
}
// ๋
ธ๋๊ฐ 1๊ฐ๋ง ์์ ๋
if ((*head)->next == NULL) {
free(*head);
*head = NULL;
return;
}
// ๋ง์ง๋ง ์ด์ ๋
ธ๋ ์ฐพ๊ธฐ
Node* current = *head;
while (current->next->next != NULL) {
current = current->next;
}
free(current->next);
current->next = NULL;
}
// ์๊ฐ๋ณต์ก๋: O(N) โ
void deleteValue(Node** head, int value) {
if (*head == NULL) {
return;
}
// ์ฒซ ๋
ธ๋๊ฐ ์ญ์ ๋์
if ((*head)->data == value) {
Node* temp = *head;
*head = (*head)->next;
free(temp);
return;
}
// ์ญ์ ํ ๋
ธ๋์ ์ด์ ๋
ธ๋ ์ฐพ๊ธฐ
Node* current = *head;
while (current->next != NULL && current->next->data != value) {
current = current->next;
}
// ๋ชป ์ฐพ์
if (current->next == NULL) {
printf("Value not found\n");
return;
}
// ์ญ์
Node* temp = current->next;
current->next = current->next->next;
free(temp);
}
์์: 20 ์ญ์
์ด๊ธฐ: Head โ [10|โ] โ [20|โ] โ [30|NULL]
1๋จ๊ณ: 20์ ์ด์ ๋
ธ๋(10) ์ฐพ๊ธฐ
Head โ [10|โ] โ [20|โ] โ [30|NULL]
โ โ
current temp
2๋จ๊ณ: current->next = temp->next
Head โ [10|โ] โโโโโโ
โ
[20|โ] [30|NULL]
temp
3๋จ๊ณ: free(temp)
Head โ [10|โ] โ [30|NULL]
Node* search(Node* head, int key) {
Node* current = head;
while (current != NULL) {
if (current->data == key) {
return current; // ์ฐพ์
}
current = current->next;
}
return NULL; // ๋ชป ์ฐพ์
}
// ์๊ฐ๋ณต์ก๋: O(N)
void display(Node* head) {
Node* current = head;
printf("List: ");
while (current != NULL) {
printf("%d โ ", current->data);
current = current->next;
}
printf("NULL\n");
}
void deleteAll(Node** head) {
Node* current = *head;
Node* next;
while (current != NULL) {
next = current->next;
free(current);
current = next;
}
*head = NULL;
}
์์์ ์ค๋ช ํ ๊ธฐ๋ณธ ํํ
Head โ [10|โ] โ [20|โ] โ [30|NULL]
ํน์ง:
- ํ ๋ฐฉํฅ์ผ๋ก๋ง ์ด๋ ๊ฐ๋ฅ
- ์ด์ ๋
ธ๋๋ก ๋์๊ฐ ์ ์์
์๋ฐฉํฅ ํฌ์ธํฐ
typedef struct DNode {
int data;
struct DNode* prev; // ์ด์ ๋
ธ๋
struct DNode* next; // ๋ค์ ๋
ธ๋
} DNode;
NULL โ [10|โ] โ [20|โ] โ [30|โ] โ NULL
prev next
์ฅ์ :
๋จ์ :
๋ง์ง๋ง ๋ ธ๋๊ฐ ์ฒซ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํด
โโโโโโโโโโโโโโโโโโโ
โ โ
Head โ [10|โ] โ [20|โ] โ [30|โ]
์ฅ์ :
ํ์ฉ:
| ๊ตฌ๋ถ | ๋ฐฐ์ด | ๋งํฌ๋ ๋ฆฌ์คํธ |
|---|---|---|
| ๋ฉ๋ชจ๋ฆฌ | ์ฐ์์ | ๋น์ฐ์์ |
| ํฌ๊ธฐ | ๊ณ ์ | ๋์ |
| ์ ๊ทผ | O(1) โ | O(N) โ |
| ํ์ | O(N) | O(N) |
| ๋งจ์ ์ฝ์ | O(N) โ | O(1) โ |
| ๋งจ๋ค ์ฝ์ | O(1) โ | O(N) โ |
| ์ค๊ฐ ์ฝ์ | O(N) | O(N) |
| ๋งจ์ ์ญ์ | O(N) โ | O(1) โ |
| ๋งจ๋ค ์ญ์ | O(1) โ | O(N) โ |
| ์ค๊ฐ ์ญ์ | O(N) | O(N) |
| ๋ฉ๋ชจ๋ฆฌ ํจ์จ | ๋์ โ | ๋ฎ์ (ํฌ์ธํฐ) โ |
| ์บ์ ํจ์จ | ๋์ โ | ๋ฎ์ โ |
// ๋ฐฐ์ด: O(1)
int value = arr[100]; // ๋ฐ๋ก ์ ๊ทผ
// ๋งํฌ๋ ๋ฆฌ์คํธ: O(N)
Node* current = head;
for (int i = 0; i < 100; i++) {
current = current->next; // 100๋ฒ ์ด๋
}
int value = current->data;
๋ฐฐ์ด (10๊ฐ int):
[10][20][30][40][50]...[100]
๋ฉ๋ชจ๋ฆฌ: 4๋ฐ์ดํธ ร 10 = 40๋ฐ์ดํธ
๋งํฌ๋ ๋ฆฌ์คํธ (10๊ฐ int):
[10|โ] โ [20|โ] โ ... โ [100|NULL]
๋ฉ๋ชจ๋ฆฌ: (4๋ฐ์ดํธ + 8๋ฐ์ดํธ) ร 10 = 120๋ฐ์ดํธ
(64๋นํธ ์์คํ
์์ ํฌ์ธํฐ 8๋ฐ์ดํธ)
๋ฐฐ์ด์ด 3๋ฐฐ ํจ์จ์ ! โ
๋ฐฐ์ด์ ์ค๊ฐ ์ฝ์ :
{10, 20, 30, 40, 50}์ 25 ์ฝ์
(์ธ๋ฑ์ค 2)
์ด๋ ํ์: 30, 40, 50 โ 3๊ฐ
์๊ฐ: O(N)
๋งํฌ๋ ๋ฆฌ์คํธ์ ์ค๊ฐ ์ฝ์ :
[10] โ [20] โ [30] โ [40] โ [50]์ 25 ์ฝ์
์ฐพ๊ธฐ: 20๊น์ง ์ด๋ โ O(N)
์ฝ์
: ํฌ์ธํฐ 2๊ฐ ๋ณ๊ฒฝ โ O(1)
์ ์ฒด: O(N)
๊ฒฐ๋ก : ์ฝ์ /์ญ์ ๋ ๋น์ทํ์ง๋ง, ๋งจ ์ ์์ ์ ๋งํฌ๋ ๋ฆฌ์คํธ๊ฐ ์ ๋ฆฌ
๋ฐฐ์ด:
[10][20][30][40][50] โ ์ฐ์ ๋ฉ๋ชจ๋ฆฌ
์บ์์ ํ ๋ฒ์ ๋ก๋ โ ๋น ๋ฆ โ
๋งํฌ๋ ๋ฆฌ์คํธ:
[10] โ [20] โ [30] โ [40] โ [50]
๊ฐ ๋
ธ๋๊ฐ ๋ค๋ฅธ ์์น โ ์บ์ ๋ฏธ์ค โ ๋๋ฆผ โ
1. ์ธ๋ฑ์ค ์ ๊ทผ์ด ๋น๋ฒํ ๋
์: arr[i], ๋๋ค ์ก์ธ์ค
2. ํฌ๊ธฐ๊ฐ ๊ณ ์ ๋์ด ์์ ๋
์: ํ์ 100๋ช
์ ์ฑ์
3. ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ ํ์ ์ผ ๋
์: ์๋ฒ ๋๋ ์์คํ
4. ์์ฐจ ์ ๊ทผ์ด ๋ง์ ๋
์: for๋ฌธ์ผ๋ก ์ ์ฒด ์ํ
1. ํฌ๊ธฐ๊ฐ ๋์ ์ผ๋ก ๋ณํ ๋
์: ์ฌ์ฉ์ ์
๋ ฅ์ ๋ฐ๋ผ ํฌ๊ธฐ ๋ณํ
2. ๋งจ ์ ์ฝ์
/์ญ์ ๊ฐ ๋น๋ฒํ ๋
์: ์คํ, ํ ๊ตฌํ
3. ์ค๊ฐ ์ฝ์
/์ญ์ ๊ฐ ๋น๋ฒํ๊ณ
ํด๋น ์์น๋ฅผ ์ด๋ฏธ ์๊ณ ์์ ๋
์: ํฌ์ธํฐ๋ก ์์น๋ฅผ ์ ์ฅํด๋ ๊ฒฝ์ฐ
4. ๋ฉ๋ชจ๋ฆฌ ๋จํธํ๋ฅผ ํผํ๊ณ ์ถ์ ๋
์: ํฐ ์ฐ์ ๋ฉ๋ชจ๋ฆฌ ํ๋ณด ์ด๋ ค์
int main() {
int arr[5] = {10, 20, 30, 40, 50};
int i;
for (i = 0; i < 5; i++) {
arr[i] = arr[i] + 5;
}
printf("%d %d", arr[2], arr[4]);
return 0;
}
ํ์ด:
์ด๊ธฐ: arr[] = {10, 20, 30, 40, 50}
๋ฐ๋ณต๋ฌธ ์คํ:
i=0: arr[0] = 10 + 5 = 15
i=1: arr[1] = 20 + 5 = 25
i=2: arr[2] = 30 + 5 = 35
i=3: arr[3] = 40 + 5 = 45
i=4: arr[4] = 50 + 5 = 55
์ต์ข
: arr[] = {15, 25, 35, 45, 55}
์ถ๋ ฅ: arr[2]=35, arr[4]=55
๋ต: 35 55
typedef struct Node {
int data;
struct Node* next;
} Node;
int main() {
Node* head = NULL;
// ๋
ธ๋ ์์ฑ ๋ฐ ์ฐ๊ฒฐ
Node* n1 = createNode(10);
Node* n2 = createNode(20);
Node* n3 = createNode(30);
head = n1;
n1->next = n2;
n2->next = n3;
n3->next = NULL;
// ๋งจ ์์ 5 ์ฝ์
Node* newNode = createNode(5);
newNode->next = head;
head = newNode;
// ์ถ๋ ฅ
printf("%d %d", head->data, head->next->next->data);
return 0;
}
ํ์ด:
1. ์ด๊ธฐ ๋ฆฌ์คํธ ์์ฑ:
Head โ [10] โ [20] โ [30] โ NULL
2. ๋งจ ์์ 5 ์ฝ์
:
newNode = [5]
newNode->next = head โ [5] โ [10] โ [20] โ [30] โ NULL
head = newNode
์ต์ข
: Head โ [5] โ [10] โ [20] โ [30] โ NULL
์ถ๋ ฅ:
head->data = 5
head->next = [10]
head->next->next = [20]
head->next->next->data = 20
๋ต: 5 20
// ๋ฐฐ์ด์์ ์ต๋๊ฐ ์ฐพ๊ธฐ
int findMax(int arr[], int size) {
int max = arr[0];
for (int i = 1; i < size; i++) {
if (arr[i] ______ max) { // ๋น์นธ 1
max = ______; // ๋น์นธ 2
}
}
return max;
}
์ ๋ต:
if (arr[i] > max) { // ๋น์นธ 1: >
max = arr[i]; // ๋น์นธ 2: arr[i]
}
// ๋งจ ๋ค์ ๋
ธ๋ ์ฝ์
void insertBack(Node** head, int data) {
Node* newNode = createNode(data);
if (*head == NULL) {
*head = newNode;
return;
}
Node* current = *head;
while (current->______ != NULL) { // ๋น์นธ 1
current = current->next;
}
current->next = ______; // ๋น์นธ 2
}
์ ๋ต:
while (current->next != NULL) { // ๋น์นธ 1: next
current = current->next;
}
current->next = newNode; // ๋น์นธ 2: newNode
// ๋ฐฐ์ด์ ์ผ์ชฝ์ผ๋ก 1์นธ ํ์
// {10, 20, 30, 40} โ {20, 30, 40, 10}
void rotateLeft(int arr[], int size) {
int temp = arr[0]; // ์ฒซ ์์ ์ ์ฅ
// ์ผ์ชฝ์ผ๋ก ์ด๋
for (int i = 0; i < size - 1; i++) {
arr[i] = arr[i + 1];
}
arr[size - 1] = temp; // ๋ง์ง๋ง์ ์ ์ฅ
}
// ์๊ฐ๋ณต์ก๋: O(N)
๋์ ๊ณผ์ :
์ด๊ธฐ: {10, 20, 30, 40}
temp = 10
์ด๋:
arr[0] = arr[1] โ {20, 20, 30, 40}
arr[1] = arr[2] โ {20, 30, 30, 40}
arr[2] = arr[3] โ {20, 30, 40, 40}
๋ง์ง๋ง์ temp ๋ฐฐ์น:
arr[3] = temp โ {20, 30, 40, 10}
// arr1๊ณผ arr2๋ฅผ result์ ํฉ์น๊ธฐ
void mergeArrays(int arr1[], int size1,
int arr2[], int size2,
int result[]) {
int i, j;
// arr1 ๋ณต์ฌ
for (i = 0; i < size1; i++) {
result[i] = arr1[i];
}
// arr2 ๋ณต์ฌ
for (j = 0; j < size2; j++) {
result[i + j] = arr2[j];
}
}
// ์๊ฐ๋ณต์ก๋: O(N + M)
์์:
arr1[] = {10, 20, 30} (size1 = 3)
arr2[] = {40, 50} (size2 = 2)
๊ฒฐ๊ณผ: result[] = {10, 20, 30, 40, 50}
// ๋งํฌ๋ ๋ฆฌ์คํธ๋ฅผ ์ญ์์ผ๋ก ๋ณ๊ฒฝ
Node* reverse(Node* head) {
Node* prev = NULL;
Node* current = head;
Node* next = NULL;
while (current != NULL) {
next = current->next; // ๋ค์ ๋
ธ๋ ์ ์ฅ
current->next = prev; // ๋ฐฉํฅ ์ ํ
prev = current; // prev ์ด๋
current = next; // current ์ด๋
}
return prev; // ์๋ก์ด head
}
// ์๊ฐ๋ณต์ก๋: O(N)
๋์ ๊ณผ์ :
์ด๊ธฐ: [10] โ [20] โ [30] โ NULL
1๋จ๊ณ: current = [10]
next = [20]
[10] โ NULL (๋ฐฉํฅ ์ ํ)
prev = [10], current = [20]
2๋จ๊ณ: current = [20]
next = [30]
[20] โ [10] โ NULL
prev = [20], current = [30]
3๋จ๊ณ: current = [30]
next = NULL
[30] โ [20] โ [10] โ NULL
prev = [30], current = NULL
์ต์ข
: [30] โ [20] โ [10] โ NULL
// ๋ฆฌ์คํธ์ ์ค๊ฐ ๋
ธ๋ ์ฐพ๊ธฐ (Fast & Slow Pointer)
Node* findMiddle(Node* head) {
if (head == NULL) return NULL;
Node* slow = head;
Node* fast = head;
// fast๋ 2์นธ, slow๋ 1์นธ์ฉ ์ด๋
while (fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;
}
return slow; // slow๊ฐ ์ค๊ฐ ์ง์
}
// ์๊ฐ๋ณต์ก๋: O(N)
๋์ ๊ณผ์ :
๋ฆฌ์คํธ: [10] โ [20] โ [30] โ [40] โ [50] โ NULL
์ด๊ธฐ:
slow = [10], fast = [10]
1๋จ๊ณ:
slow = [20], fast = [30]
2๋จ๊ณ:
slow = [30], fast = [50]
3๋จ๊ณ:
fast->next = NULL โ ์ข
๋ฃ
slow = [30] โ (์ค๊ฐ ๋
ธ๋)
// ๋ฆฌ์คํธ์ ์ํ(Cycle)์ด ์๋์ง ํ์ธ
bool hasCycle(Node* head) {
if (head == NULL) return false;
Node* slow = head;
Node* fast = head;
while (fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;
// ๋ง๋๋ฉด ์ํ ์์
if (slow == fast) {
return true;
}
}
return false; // ์ํ ์์
}
// ์๊ฐ๋ณต์ก๋: O(N)
๋์ ์๋ฆฌ:
์ํ์ด ์๋ ๊ฒฝ์ฐ:
[10] โ [20] โ [30] โ [40]
โ โ
โโโโโโโโโ
slow์ fast๊ฐ ์ธ์ ๊ฐ ๋ง๋จ โ
์ํ์ด ์๋ ๊ฒฝ์ฐ:
[10] โ [20] โ [30] โ [40] โ NULL
fast๊ฐ NULL์ ๋๋ฌ โ ์ํ ์์ โ
๋ต:
1. ๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ:
- ๋ฐฐ์ด: ์ฐ์๋ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ์ ์ฅ
- ๋งํฌ๋ ๋ฆฌ์คํธ: ๋น์ฐ์์ ๋ฉ๋ชจ๋ฆฌ, ํฌ์ธํฐ๋ก ์ฐ๊ฒฐ
2. ์ ๊ทผ ์๋:
- ๋ฐฐ์ด: ์ธ๋ฑ์ค๋ก ์ง์ ์ ๊ทผ O(1)
- ๋งํฌ๋ ๋ฆฌ์คํธ: ์์ฐจ ์ ๊ทผ O(N)
3. ํฌ๊ธฐ ๋ณ๊ฒฝ:
- ๋ฐฐ์ด: ๊ณ ์ ํฌ๊ธฐ, ๋ณ๊ฒฝ ๋ถ๊ฐ
- ๋งํฌ๋ ๋ฆฌ์คํธ: ๋์ ํฌ๊ธฐ, ์์ ๋กญ๊ฒ ๋ณ๊ฒฝ ๊ฐ๋ฅ
๋ต:
์ค๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์
ํ๋ ค๋ฉด ํด๋น ์์น ์ดํ์
๋ชจ๋ ์์๋ฅผ ํ ์นธ์ฉ ๋ค๋ก ์ด๋ํด์ผ ํฉ๋๋ค.
์: {10, 20, 30, 40, 50}์ ์ธ๋ฑ์ค 2์ 25 ์ฝ์
1. 50์ ์ธ๋ฑ์ค 5๋ก ์ด๋
2. 40์ ์ธ๋ฑ์ค 4๋ก ์ด๋
3. 30์ ์ธ๋ฑ์ค 3์ผ๋ก ์ด๋
4. ์ธ๋ฑ์ค 2์ 25 ์ฝ์
์ด๋ ํ์๋ (๋ฐฐ์ด ํฌ๊ธฐ - ์ฝ์
์์น)์ด๋ฏ๋ก
์ต์
์ ๊ฒฝ์ฐ(๋งจ ์ ์ฝ์
) N๋ฒ ์ด๋ โ O(N)
๋ต:
Tail ํฌ์ธํฐ๋ฅผ ์ถ๊ฐ๋ก ์ ์งํฉ๋๋ค.
๊ตฌ์กฐ:
typedef struct List {
Node* head;
Node* tail; // ๋ง์ง๋ง ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํด
} List;
์ฝ์
์:
1. newNode ์์ฑ
2. tail->next = newNode
3. tail = newNode
Tail ํฌ์ธํฐ๋ก ๋ง์ง๋ง ๋
ธ๋๋ฅผ ๋ฐ๋ก ์ ๊ทผํ๋ฏ๋ก
์ํ ์์ด O(1)์ ์ฝ์
๊ฐ๋ฅํฉ๋๋ค.
๋ต:
์ฅ์ :
1. ์๋ฐฉํฅ ํ์ ๊ฐ๋ฅ (prev ํฌ์ธํฐ)
2. ํน์ ๋
ธ๋ ์ญ์ ์ ์ด์ ๋
ธ๋ ์ฐพ๊ธฐ ์ฌ์
3. ์ญ์ ์ํ ๊ฐ๋ฅ
๋จ์ :
1. ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ์ฆ๊ฐ (ํฌ์ธํฐ 2๊ฐ)
2. ์ฝ์
/์ญ์ ์ ํฌ์ธํฐ ๊ด๋ฆฌ ๋ณต์ก (prev, next ๋ชจ๋ ์ฒ๋ฆฌ)
3. ๊ตฌํ ๋์ด๋ ์ฆ๊ฐ
ํ์ฉ:
- ๋ธ๋ผ์ฐ์ ์ ์/๋ค ์ด๋
- ํ
์คํธ ์๋ํฐ์ Undo/Redo
- LRU ์บ์ ๊ตฌํ
// ๋ฐฐ์ด์์ ํฉ์ด target์ธ ๋ ์์ ์ธ๋ฑ์ค ์ฐพ๊ธฐ
// arr[] = {2, 7, 11, 15}, target = 9
// ๋ต: [0, 1] (2 + 7 = 9)
void twoSum(int arr[], int size, int target) {
for (int i = 0; i < size - 1; i++) {
for (int j = i + 1; j < size; j++) {
if (arr[i] + arr[j] == target) {
printf("[%d, %d]\n", i, j);
return;
}
}
}
printf("Not found\n");
}
// ์๊ฐ๋ณต์ก๋: O(Nยฒ)
// ๋ฐฐ์ด์ ์ค๋ฅธ์ชฝ์ผ๋ก k์นธ ํ์
// arr[] = {1, 2, 3, 4, 5}, k = 2
// ๊ฒฐ๊ณผ: {4, 5, 1, 2, 3}
void reverse(int arr[], int start, int end) {
while (start < end) {
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
start++;
end--;
}
}
void rotateRight(int arr[], int size, int k) {
k = k % size; // k๊ฐ size๋ณด๋ค ํด ๊ฒฝ์ฐ ๋๋น
// 1. ์ ์ฒด ์ญ์
reverse(arr, 0, size - 1);
// 2. ์ k๊ฐ ์ญ์
reverse(arr, 0, k - 1);
// 3. ๋๋จธ์ง ์ญ์
reverse(arr, k, size - 1);
}
// ์๊ฐ๋ณต์ก๋: O(N)
๋์ ๊ณผ์ :
์ด๊ธฐ: {1, 2, 3, 4, 5}, k = 2
1. ์ ์ฒด ์ญ์:
{5, 4, 3, 2, 1}
2. ์ 2๊ฐ ์ญ์:
{4, 5, 3, 2, 1}
3. ๋๋จธ์ง ์ญ์:
{4, 5, 1, 2, 3} โ
// ์ ๋ ฌ๋ ๋ ๋ฆฌ์คํธ๋ฅผ ๋ณํฉํ์ฌ ์ ๋ ฌ๋ ํ๋์ ๋ฆฌ์คํธ๋ก
// list1: [1] โ [3] โ [5]
// list2: [2] โ [4] โ [6]
// ๊ฒฐ๊ณผ: [1] โ [2] โ [3] โ [4] โ [5] โ [6]
Node* mergeSortedLists(Node* l1, Node* l2) {
// ๋๋ฏธ ๋
ธ๋ ์์ฑ
Node dummy;
Node* tail = &dummy;
dummy.next = NULL;
while (l1 != NULL && l2 != NULL) {
if (l1->data <= l2->data) {
tail->next = l1;
l1 = l1->next;
} else {
tail->next = l2;
l2 = l2->next;
}
tail = tail->next;
}
// ๋จ์ ๋
ธ๋ ์ฐ๊ฒฐ
if (l1 != NULL) {
tail->next = l1;
} else {
tail->next = l2;
}
return dummy.next;
}
// ์๊ฐ๋ณต์ก๋: O(N + M)
// ๋ค์์ N๋ฒ์งธ ๋
ธ๋ ์ญ์
// ๋ฆฌ์คํธ: [1] โ [2] โ [3] โ [4] โ [5], N = 2
// ๊ฒฐ๊ณผ: [1] โ [2] โ [3] โ [5] (4 ์ญ์ )
Node* removeNthFromEnd(Node* head, int n) {
Node dummy;
dummy.next = head;
Node* first = &dummy;
Node* second = &dummy;
// first๋ฅผ n+1์นธ ์์๊ฒ ์ด๋
for (int i = 0; i <= n; i++) {
if (first == NULL) return head;
first = first->next;
}
// ๋ ๋ค ์ด๋ (๊ฐ๊ฒฉ ์ ์ง)
while (first != NULL) {
first = first->next;
second = second->next;
}
// ์ญ์
Node* temp = second->next;
second->next = second->next->next;
free(temp);
return dummy.next;
}
// ์๊ฐ๋ณต์ก๋: O(N)
๋์ ๊ณผ์ :
๋ฆฌ์คํธ: [1] โ [2] โ [3] โ [4] โ [5], N = 2
1. first๋ฅผ n+1=3์นธ ์ด๋:
first โ [4], second โ [dummy]
2. ๋ ๋ค ๋๊น์ง ์ด๋ (๊ฐ๊ฒฉ ์ ์ง):
first โ NULL, second โ [3]
3. second->next (4) ์ญ์ :
[1] โ [2] โ [3] โ [5]
โ ์ฐ์๋ ๋ฉ๋ชจ๋ฆฌ
โ ๊ณ ์ ํฌ๊ธฐ
โ ์ธ๋ฑ์ค ์ ๊ทผ: O(1)
โ ํ์: O(N)
โ ๋งจ๋ค ์ฝ์
/์ญ์ : O(1)
โ ์ค๊ฐ ์ฝ์
/์ญ์ : O(N)
โ ๋ฉ๋ชจ๋ฆฌ ํจ์จ์
โ ์บ์ ์นํ์
์ฃผ์ ๊ณ์ฐ: ์์์ฃผ์ + (์ธ๋ฑ์ค ร ๋ฐ์ดํฐํฌ๊ธฐ)
โ ๋น์ฐ์์ ๋ฉ๋ชจ๋ฆฌ
โ ๋์ ํฌ๊ธฐ
โ ์ธ๋ฑ์ค ์ ๊ทผ: O(N)
โ ํ์: O(N)
โ ๋งจ์ ์ฝ์
/์ญ์ : O(1)
โ ๋งจ๋ค ์ฝ์
/์ญ์ : O(N) (Tail ์์ ๋)
โ ์ค๊ฐ ์ฝ์
/์ญ์ : O(N)
โ ํฌ์ธํฐ ๋ฉ๋ชจ๋ฆฌ ์ค๋ฒํค๋
๋
ธ๋ ๊ตฌ์กฐ: data + next ํฌ์ธํฐ
| ์ฐ์ฐ | ๋ฐฐ์ด | ๋งํฌ๋ ๋ฆฌ์คํธ |
|---|---|---|
| ์ ๊ทผ | O(1) | O(N) |
| ํ์ | O(N) | O(N) |
| ๋งจ์ ์ฝ์ | O(N) | O(1) |
| ๋งจ๋ค ์ฝ์ | O(1) | O(N) |
| ์ค๊ฐ ์ฝ์ | O(N) | O(N) |
| ๋งจ์ ์ญ์ | O(N) | O(1) |
| ๋งจ๋ค ์ญ์ | O(1) | O(N) |
int arr[5]; // ์ธ๋ฑ์ค: 0, 1, 2, 3, 4
arr[5] = 10; // โ ๋ฒ์ ์ด๊ณผ (Undefined Behavior)
arr[4] = 10; // โ ์ฌ๋ฐ๋ฆ
Node* head = NULL; // โ ๋ฐ๋์ ์ด๊ธฐํ
if (head == NULL) { // NULL ์ฒดํฌ ์ต๊ดํ
// ์ฒ๋ฆฌ
}
Node* temp = head;
head = head->next;
free(temp); // โ ๋ฐ๋์ ํด์
void insertFront(Node** head, int data) {
// *head๋ฅผ ์์ ํ๋ ค๋ฉด **head ํ์
*head = newNode;
}
// ๋น ๋ฆฌ์คํธ
if (head == NULL) { ... }
// ๋
ธ๋ 1๊ฐ
if (head->next == NULL) { ... }
// ๋ฐฐ์ด ๋ฒ์
if (index < 0 || index >= size) { ... }
check list: