일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 시스템호출
- 구조체배열
- Spring
- spring boot
- git
- C++
- 코테
- AWS
- 스프링
- TypeORM
- python
- 프로그래머스
- OpenCV
- C언어
- 알고리즘
- 카카오
- 가상면접사례로배우는대규모시스템설계기초
- @Autowired
- 카카오 코테
- 코딩테스트
- @Component
- 해시
- Nodejs
- thymeleaf
- nestjs typeorm
- nestJS
- nestjs auth
- 파이썬
- 컴포넌트스캔
- 카카오 알고리즘
Archives
- Today
- Total
공부 기록장 💻
[자료구조] 연결 리스트 (Linked List) 응용 - 특정 위치에 데이터 삽입과 삭제, 선행 노드의 포인터 이용 본문
# CS Study/DS Algorithm
[자료구조] 연결 리스트 (Linked List) 응용 - 특정 위치에 데이터 삽입과 삭제, 선행 노드의 포인터 이용
dream_for 2021. 6. 7. 14:45
특정 위치에 새로운 데이터(노드)를 삽입하고, 삭제할 수 있는 연결 리스트 프로그램이다.
data.txt
20074241 마바사 50 90 95
20074242 가나다 80 95 85
20074243 라마바 70 60 95
20074244 사아자 50 30 65
add_last() 함수를 이용
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRUE 1
#define FALSE 0
typedef struct element {
int nId;
char* name;
int nKor, nEng, nMath, nSum;
double dAvg;
}element;
typedef struct ListNode{
element data;
struct ListNode* link;
}ListNode;
typedef struct ListType{
ListNode* head; // 리스트의 헤드포인터
int length; // 노드의 개수
}ListType;
// 초기화(ListType의 head와 length를 초기화)
void init(ListType* list) {
if (list == NULL) return;
list->length = 0;
list->head = NULL;
}
int is_empty(ListType* list) {
if (list->head == NULL) return TRUE;
else return FALSE;
}
int get_length(ListType* list) { return list->length; }
// insert_node : 실제로 새로운 노드를 삽입하는 함수 (선행 노드 p가 가리키는 링크에 new_node 의 링크를 연결)
void insert_node(ListNode** phead, ListNode* p, ListNode* new_node) {
// phead: 헤드 포인터
// p : 선행 노드
// new_node : 신규 노드
if (*phead == NULL) { // empty list
new_node->link = NULL;
*phead = new_node;
}
else if (p == NULL) { // 선행 노드가 없는 경우(첫번째에 삽입하게 되는 경우)
new_node->link = *phead;
*phead = new_node;
}
else { // p 노드 다음에 삽입
new_node->link = p->link;
p->link = new_node;
}
}
// 리스트를 삽입할 위치의 노드의 주소를 얻는 함수
ListNode* get_node_at(ListType* list, int pos) {
int i;
ListNode* tmp_node = list->head;
if (pos < 0) return NULL; // 첫번째 위치에 삽입하도록 pos값이 0 미만이 전달된경우
for (i = 0;i < pos;i++)
tmp_node = tmp_node->link;
return tmp_node; // pos 위치의 노드 주소값 반환
}
// pos 위치에 data를 추가
void add(ListType *list, int position, element data) {
ListNode* p;
// pos의 숫자가 new_node 를 삽입하기 위한 유효한 위치인지 먼저 검사해보기
if (position >= 0 && position <= list->length) {
ListNode* node = (ListNode*)malloc(sizeof(ListNode));
if (node == NULL) {
printf("memory allocation failure\n");
return;
}
node->data = data;
p = get_node_at(list, position - 1); // 선행 노드의 주소를 주소를
insert_node(&(list->head), p, node); // 해당 포인터 p 위치에 new node를 삽입
list->length++;
}
}
// add_first : 리스트의 첫번째 노드 삽입
void add_first(ListType* list, element data) {
// 새로 추가하는 노드가 기존의 첫번째 노드를 가리키도록
add(list, 0, data); // list->head 다음에 추가
}
// add_last: 리스트의 끝에 순서대로 삽입하는 함수
void add_last(ListType* list, element data) {
add(list, get_length(list), data); // 리스트의 맨 뒤(get_length())에 추가하도록 함수 호출
}
// 연결리스트 출력
void display(ListType* list) {
int i;
ListNode* node = list->head;
printf("|========|======|====|====|====|====|======|\n");
printf("| 학번 | 이름 |국어|영어|수학|총점| 평균 |\n");
printf("|========|======|====|====|====|====|======|\n");
// ListType 구조체의 head 포인터가 가리키는 ListNode 구조체의 data의 멤버 변수들 출력
// 노드의 개수만큼 반복하기
for (i = 0;i < list->length;i++) {
printf("|%d|%s|%4d|%4d|%4d|%4d|%6.2lf|\n",
node->data.nId, node->data.name, node->data.nKor, node->data.nEng,
node->data.nMath, node->data.nSum, node->data.dAvg);
node = node->link; // 다음 노드로 이동
}
printf("|========|======|====|====|====|====|======|\n\n");
}
// 최고 점수를 갖고 있는 노드 출력
void list_max(ListType* list) {
int i;
ListNode* node = list->head;
ListNode* max_node=list->head; // 최고 점수를 갖고 있는 노드를 저장할 임시 포인터에 첫번째 노드 주소를 담아둔다.
node = node->link; // 다음 노드와 비교하기 위해 2번째 노드를 다시 대입
// (노드의 개수-1)만큼 차례대로 반복하며, dAvg 평균을 비교하여 더 높은 노드를 max_node에 대입. 반복하여 갱신한다
for (i = 0;i < list->length-1;i++) {
if (node->data.dAvg > max_node->data.dAvg)
max_node = node;
node = node->link; // 다음 노드로 이동
}
// 최고 점수를 갖고 있는 max_node 의 데이터들을 출력
printf("|========|======|====|====|====|====|======|\n");
printf("| 학번 | 이름 |국어|영어|수학|총점| 평균 |\n");
printf("|========|======|====|====|====|====|======|\n");
printf("|%d|%s|%4d|%4d|%4d|%4d|%6.2lf|\n",
max_node->data.nId, max_node->data.name, max_node->data.nKor, max_node->data.nEng,
max_node->data.nMath, max_node->data.nSum, max_node->data.dAvg);
printf("|========|======|====|====|====|====|======|\n\n");
}
// 삭제할 노드의 메모리 공간 해제
void remove_node(ListNode** phead, ListNode* p, ListNode* removed) {
// phead: 헤드 포인터
// p : 삭제할 노드의 선행 노드
// removed : 삭제할 노드
if (p == NULL) {
ListNode* pf;
pf = *phead;
*phead = (*phead)->link;
free(pf->data.name); // 동적으로 할당받은 name에 대한 메모리 해제
free(pf); // 전체 pf 노드에 대한 메모리 해제
}
else
p->link = removed->link;
// printf("%d 학번의 데이터 삭제\n", removed->data.nId);
free(removed);
}
// 특정 위치의 노드 삭제
void delete_node(ListType* list, int pos) {
if (!is_empty(list) && pos >= 0 && pos < list->length) {
ListNode* p = get_node_at(list, pos - 1); // 실제 삭제하고자 하는 이전 노드의 포인터
remove_node(&(list->head), p, (p != NULL) ? p->link : NULL);
list->length--;
}
}
// 삭제
void clear(ListType* list) {
int i, cnt = list->length;
for (i = 0;i < cnt;i++)
delete_node(list, 0); // 위치를 지정해 준 노드의 메모리를 해제(첫번째 인덱스의 노드 삭제)
// 뒤에서부터 삭제할 수 있는 함수도 구현하기
}
int main() {
FILE* fp;
element input;
ListType list;
char buf[100];
fp = fopen("data.txt", "rt");
if (fp == NULL) {
printf("file not found \n");
return 0;
}
init(&list);
// 파일 읽어서 연결리스트에 저장
while (!feof(fp)) {
// element tmp 구조체의 변수들에 임시로 읽어 저장
fscanf(fp, "%d%s%d%d%d", &input.nId, buf, &input.nKor, &input.nEng, &input.nMath);
input.nSum = input.nKor + input.nEng + input.nMath;
input.dAvg = input.nSum / 3.0;
input.name = (char*)malloc(strlen(buf) * sizeof(char) + 1); // char형 포인터에 실제 메모리를 할당해줌
strcpy(input.name, buf);
add_last(&list, input);
}
//printf("리스트 추가 후 출력 \n");
display(&list); // 연결 리스트 출력
// 최고 점수 검색
// 값이 가장 큰 노드를 찾아 출력하는 list_max()
printf("최고 점수는 ? \n");
list_max(&list);
printf("\n리스트 삭제\n\n");
clear(&list);
printf("삭제된 후 리스트 출력 \n");
display(&list);
}
add_first() 함수를 이용
while (!feof(fp)) { // element tmp 구조체의 변수들에 임시로 읽어 저장
fscanf(fp, "%d%s%d%d%d", &input.nId, buf, &input.nKor, &input.nEng, &input.nMath);
...
add_first(&list, input);
}
728x90
반응형
'# CS Study > DS Algorithm' 카테고리의 다른 글
[자료구조] 스택 / 큐 / 연결리스트 정리 (0) | 2021.06.07 |
---|---|
[자료구조] 이중 연결 리스트 (Doubly Linked List) 를 이용한 mp3 음악 재생 프로그램 - 양방향 순회(검색, 추가, 삭제, (0) | 2021.06.07 |
[자료구조] 원형 큐 (Circular Queue) 응용 - 오름차순으로 큐에 데이터 삽입하기 (0) | 2021.06.07 |
[자료구조] 덱 (Deque : Double-Ended-Queue) 의 구조와 구현 - 덱의 전단(front)와 후단(rear)의 입출력 (0) | 2021.06.02 |
[자료구조] 원형 연결 리스트 (Circular Linked List) 의 구조와 구현 (3) | 2021.06.02 |
Comments