일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- AWS
- OpenCV
- 스프링
- spring boot
- 코테
- python
- thymeleaf
- 시스템호출
- 가상면접사례로배우는대규모시스템설계기초
- 카카오 알고리즘
- @Autowired
- @Component
- 카카오
- Spring
- C언어
- Nodejs
- 파이썬
- C++
- 구조체배열
- nestJS
- 카카오 코테
- 코딩테스트
- 프로그래머스
- 해시
- git
- 컴포넌트스캔
- TypeORM
- nestjs typeorm
- nestjs auth
- 알고리즘
- Today
- Total
공부 기록장 💻
[자료구조] 단순 연결 리스트(Linked List) ADT + 예제들 본문
(C언어로 쉽게 풀어쓴 자료구조 연결리스트 Lab + 추가 변형)
1. 과일의 이름을 저장하는 단순 연결 리스트 (p.200)
+ 사용자로부터 직접 문자열 입력 받기
+ 맨 앞의 노드에 해당하는 메모리를 반환하는 함수 delete_first 구현
* 주의할점
main 함수에서 저장된 각 동적 메모리를 반환하기 위해서
반복문을 이용하여 delete_first 함수를 호출할 때,
delete_first 함수 내에서 이미 메모리를 반환하고 head의 값이 변경되고 있다는 점을 유의하여 작성해야 함.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct { char name[100]; }element;
typedef struct {
element data;
struct ListNode* link;
}ListNode;
ListNode* insert_first(ListNode* head, element value) {
ListNode* new_node = (ListNode*)malloc(sizeof(ListNode));
new_node->data = value;
new_node->link = head;
head = new_node;
return head;
}
void print_list(ListNode* head) {
for (ListNode* p = head;p != NULL;p = p->link) {
printf("%s -> ", p->data.name);
printf("NULL \n");
}
}
ListNode* delete_first(ListNode* head) {
if (head == NULL) {
printf("마지막 노드\n");
return NULL;
}
ListNode* p = head; // 첫번째 노드에 p 대입
head = p->link;
printf("\nfree(%s) \n", p->data.name);
free(p);
return head;
}
int main(void) {
ListNode* head = NULL;
element data;
int i = 0l;
while (1) {
printf("과일 이름 입력(종료는 end) : ");
gets(data.name);
if (strcmp(data.name, "end") == 0) break;
head = insert_first(head, data);
print_list(head);
printf("\n");
}
while(head!=NULL){
head = delete_first(head);
print_list(head);
}
return 0;
}
결과:
2. 특정한 값을 탐색하는 함수 추가 구현(p.202)
+ 사용자로부터 문자열 입력받아 연결 리스트에서 해당 값 탐색하기
search_list() 함수는 다음과 같다.
int search_list(ListNode* head, element target) {
for (ListNode* p = head;p != NULL;p = p->link) {
if (strcmp(p->data.name, target.name)==0)
return p;
}
return NULL;
}
전체 코드 :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct { char name[100]; }element;
typedef struct {
element data;
struct ListNode* link;
}ListNode;
ListNode* insert_first(ListNode* head, element value) {
ListNode* new_node = (ListNode*)malloc(sizeof(ListNode));
new_node->data = value;
new_node->link = head;
head = new_node;
return head;
}
void print_list(ListNode* head) {
for (ListNode* p = head;p != NULL;p = p->link) {
printf("%s -> ", p->data.name);
printf("NULL \n");
}
}
ListNode* delete_first(ListNode* head) {
if (head == NULL) {
printf("마지막 노드\n");
return NULL;
}
ListNode* p = head; // 첫번째 노드에 p 대입
head = p->link;
printf("\nfree(%s) \n", p->data.name);
free(p);
return head;
}
int search_list(ListNode* head, element target) {
for (ListNode* p = head;p != NULL;p = p->link) {
if (strcmp(p->data.name, target.name)==0)
return p;
}
return NULL;
}
int main(void) {
ListNode* head = NULL;
element data;
while (1) {
printf("과일 이름 입력(종료는 end) : ");
gets(data.name);
if (strcmp(data.name, "end") == 0) break;
head = insert_first(head, data);
print_list(head);
printf("\n");
}
printf("\n찾고자 하는 과일 이름 : ");
gets(data.name);
if (search_list(head, data))
printf("\n리스트에서 %s 탐색 성공\n\n", data.name);
else
printf("\n리스트이서 %s 탐색 실패\n\n", data.name);
while (head != NULL) {
head = delete_first(head);
print_list(head);
}
return 0;
}
결과:
3. 두 개의 리스트를 하나로 합치는 함수 구현(p.204)
4. 리스트를 역순으로 만드는 연산(p.206)
5. 사용자가 입력하는 값을 연결 리스트에 저장하고 데이터의 값들의 합 구하기, 탐색한 값 삭제하기(p.217 #9, 10, 11, 12, 13)
#include <stdio.h>
#include <stdlib.h>
typedef int element;
typedef struct ListType {
int size;
struct ListNode* head;
struct ListNode* tail;
}ListType;
typedef struct ListNode {
element data;
struct ListNode* link;
}ListNode;
// create
ListType* create() {
ListType* list = (ListType*)malloc(sizeof(ListType));
list->size = 0;
list->head = list->tail = NULL;
return list;
}
// error
void error(char* message) {
fprintf(stderr, "%s\n", message);
exit(1);
}
// insert_last
void insert_last(ListType* list, element item) {
ListNode* new = malloc(sizeof(ListNode));
if (new == NULL) error("메모리 동적 할당 실패 \n");
new->data = item;
new->link = NULL;
if (list->tail == NULL) {
list->head = list->tail = new;
}
else {
list->tail->link = new;
list->tail = new;
}
list->size++;
}
// print_list
void print_list(ListType* list) {
ListNode* p = list->head;
for (int i = 0;i < list->size - 1;i++) {
printf("%d->", p->data);
p = p->link;
}
printf("%d\n", p->data);
}
// get_length
int get_length(ListType* list) { return list->size; }
// add
element add(ListType* list) {
ListNode* p = list->head;
element sum = 0;
for (;p;p = p->link)
sum += p->data;
return sum;
}
int search(ListType* list, element key) {
ListNode* p = list->head;
int cnt = 0;
for (;p;p = p->link)
if (p->data == key) cnt++;
return cnt;
}
void delete(ListType* list, element key) {
ListNode* p, * next;
p = list->head;
while (p != NULL) {
next = p->link;
if(p->data==key) free(p);
p = next;
}
printf("연결 리스트에서 %d를 성공적으로 삭제했습니다.\n\n", key);
}
int main() {
ListType* list;
int n, data, key;
list=create();
printf("노드의 개수 : ");
scanf("%d", &n);
for (int i = 0;i < n;i++) {
printf("노드 #%d 데이터 : ", i + 1);
scanf("%d", &data);
element item = data;
insert_last(list, item);
}
print_list(list);
printf("\n연결 리스트 노드의 개수 = %d\n\n", get_length(list));
printf("연결 리스트의 데이터 합 : %d\n\n", add(list));
printf("탐색할 값을 입력하시오: ");
scanf("%d", &key);
printf("%d는 연결 리스트에서 %d번 나타납니다.\n\n", key, search(list, key));
delete(list, key);
free(list);
}
6. 랜덤으로 생성한 정수 10개를 연결 리스트에 저장하고, 최솟값과 최댓값을 찾고, 오름차순으로 정렬하였다가 홀수번째 노드들을 삭제하고, 다시 내림차순으로 정렬(역순)하여 출력하기
(p.218-219 #15-16, #19)
// 랜덤으로 정수 생성하여 리스트에 저장 후, 최댓값과 최솟값 찾기
// 정렬하기
// 홀수번째 노드들이 전부 삭제되기
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef int element;
typedef struct ListType {
struct ListNode* head, * tail;
int size;
}ListType;
typedef struct ListNode {
element data;
struct ListNode* link;
}ListNode;
void error(char* message) {
fprintf(stderr, "%s\n", message);
exit(1);
}
// ListType 생성, 초기화
ListType* create() {
ListType* new = (ListType*)malloc(sizeof(ListType));
new->head = new->tail = NULL;
new->size = 0;
return new;
}
// add(insert_last)
void add(ListType* list, element item) {
ListNode* new = (ListNode*)malloc(sizeof(ListNode));
if (new == NULL) error("동적 메모리 할당 실패 \n");
new->link = NULL;
new->data = item;
if (list->tail == NULL)
list->head = list->tail = new;
else {
list->tail->link = new;
list->tail = new;
}
list->size++;
}
void bubble_sort(ListType* list) {
ListNode* p, * q;
element tmp;
for (p = list->head;p != NULL;p = p->link) {
for (q = p;q != NULL;q = q->link) {
if (p->data > q->data) {
tmp = p->data;
p->data = q->data;
q->data = tmp;
}
}
}
}
ListNode* reverse(ListType* list) {
ListNode* p = list->head, * q = NULL, * r = q;
while (p != NULL) {
r = q;
q = p;
p = p->link;
q->link = r;
}
list = q;
}
void delete(ListType* list, ListNode* prev) {
ListNode* p = prev->link;
prev->link = p->link;
free(p);
}
ListType* delete_odd(ListType* list) {
ListType* new = create();
ListNode* p = list->head;
// 짝수번째것만 저장하도록 함
while(p!=NULL) {
// 0, 2, 4, 6, 8 (홀수번째는 제외)
p = p->link;
add(new, p->data);
p = p->link;
}
free(list);
return new;
}
int get_length(ListType* list) { return list->size; }
void get_max_min(ListType* list) {
ListNode* p = list->head;
element max = p->data, min = p->data;
for (p->link;p;p = p->link) {
if (p->data > max) max = p->data;
if (p->data < min)min = p->data;
}
printf("\n최댓값은 %d, 최솟값은 %d\n\n", max, min);
}
void print_list(ListType* list) {
ListNode* p = list->head;
for (int i = 0;i < list->size - 1;i++) {
printf("%d -> ", p->data);
p = p->link;
}
printf("%d\n", p->data);
}
int main() {
// 랜덤으로 정수 생성하여 리스트에 저장 후, 최댓값과 최솟값 위치 찾기
// 오름차순으로 정렬하고 출력하기
// 홀수번째 노드들 전부 삭제하기 (새로운 노드 생성하도록 함)
// 내림차순으로 변경 후 출력
ListType* list;
int randNum;
list = create();
srand(time(NULL));
for (int i = 0;i < 10;i++) {
randNum = rand() % 100;
add(list, randNum);
}
printf("-------출력 -------\n");
printf("리스트 요소 개수 : %d\n", get_length(list));
print_list(list);
get_max_min(list);
bubble_sort(list);
printf("\n------ 오름차순 정렬 -------\n");
printf("리스트 요소 개수 : %d\n", get_length(list));
print_list(list);
list=delete_odd(list);
printf("\n------ 홀수번째 노드 메모리 해제-------\n");
printf("리스트 요소 개수 : %d\n", get_length(list));
print_list(list);
list->head = reverse(list);
printf("\n------ 역순 -------\n");
printf("리스트 요소 개수 : %d\n", get_length(list));
print_list(list);
}
7. 두 개의 연결리스트에 랜덤으로 숫자 5개씩 저장하고, 오름차순으로 정렬한뒤, 두 연결리스트를 하나로 병합한 새로운 오름차순 정렬된 연결리스트 생성하기 (p.218 #17-18)
// 랜덤 생성한 번호들 5개씩 연결리스트에 생성
// 오름차순으로 두 연결리스트 각각 정렬
// 두개의 단순 연결 리스트 a,b(오름차순으로 정렬) 를 다시 새로운 오름차순 c 연결리스트 생성
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef int element;
typedef struct ListType {
struct ListNode* head, * tail;
int size;
}ListType;
typedef struct ListNode {
element data;
struct ListNode* link;
}ListNode;
void error(char* message) {
fprintf(stderr, "%s\n", message);
exit(1);
}
// ListType 생성, 초기화
ListType* create() {
ListType* new = (ListType*)malloc(sizeof(ListType));
new->head = new->tail = NULL;
new->size = 0;
return new;
}
// add(insert_last)
void add(ListType* list, element item) {
ListNode* new = (ListNode*)malloc(sizeof(ListNode));
if (new == NULL) error("동적 메모리 할당 실패 \n");
new->link = NULL;
new->data = item;
if (list->tail == NULL)
list->head = list->tail = new;
else {
list->tail->link = new;
list->tail = new;
}
list->size++;
}
void bubble_sort(ListType* list) {
ListNode* p, * q;
element tmp;
for (p = list->head;p != NULL;p = p->link) {
for (q = p;q != NULL;q = q->link) {
if (p->data > q->data) {
tmp = p->data;
p->data = q->data;
q->data = tmp;
}
}
}
}
int get_length(ListType* list) { return list->size; }
void merge(ListType* list1, ListType* list2, ListType* list3) {
ListNode* head1 = list1->head;
ListNode* head2 = list2->head;
while (head1 && head2) {
if (head1->data == head2->data) {
add(list3, head1->data);
head1 = head1->link;
head2 = head2->link;
}
else if (head1->data < head2->data) {
add(list3, head1->data);
head1 = head1->link;
}
else {
add(list3, head2->data);
head2 = head2->link;
}
}
for (;head1;head1 = head1->link)
add(list3, head1->data);
for (;head2;head2=head2->link)
add(list3, head2->data);
}
void print_list(ListType* list) {
ListNode* p = list->head;
for (int i = 0;i < list->size - 1;i++) {
printf("%d -> ", p->data);
p = p->link;
}
printf("%d\n", p->data);
}
int main() {
ListType* list1, *list2, *list3;
int randNum;
list1 = create();
list2 = create();
list3 = create();
srand(time(NULL));
for (int i = 0;i < 5;i++) {
randNum = rand() % 100;
add(list1, randNum);
}
for (int i = 0;i < 5;i++) {
randNum = rand() % 100;
add(list2, randNum);
}
bubble_sort(list1); bubble_sort(list2);
printf("\n------ 오름차순 정렬후 출력 -------\n");
printf("리스트 요소 개수 : %d\n", get_length(list1));
print_list(list1);
printf("\n------ 오름차순 정렬후 출력 -------\n");
printf("리스트 요소 개수 : %d\n", get_length(list2));
print_list(list2);
merge(list1, list2, list3);
printf("\n------ 오름차순 정렬후 출력 -------\n");
printf("리스트 요소 개수 : %d\n", get_length(list3));
print_list(list3);
free(list1);free(list2);free(list3);
}
'# CS Study > DS Algorithm' 카테고리의 다른 글
[자료구조] 배열 Array List (0) | 2021.04.14 |
---|---|
[자료구조] 이중 연결 리스트(Doubly Linked List)를 이용한 학생 성적 관리 프로그램 - 이중 연결리스트 초기화, 출력, 검색, 정렬, 메모리 해제 (2) | 2021.04.14 |
[자료구조] 단순 연결 리스트 Singly Linked List 실습 문제 - 동적 메모리 할당, 노드 생성(create), 삽입(insert), 역순 연산(reverse), 버블 정렬(bubble sort), 출력, 메모리 해제 (0) | 2021.04.13 |
[자료구조] 배열 실습 문제들 (0) | 2021.04.04 |
[자료구조] 다항식 배열의 연산 (구조체 배열, 포인터, 다항식의 표현) (0) | 2021.04.04 |