- 배열(array) 리스트(list)의 차이점
- 배열은 인덱스를 가진 데이터의 집합이고, 리스트는 인덱스 없이 순차적으로 저장된 데이터의 집합이다.
- 배열은 메모리에 연속적으로 저장되고 리스트는 메모리에 분산 되어 저장된다.
6.1 배열(array)로 구현된 리스트
- 배열을 이용하여 리스트를 구현하면 순차적인 메모리 공간이 할당됨(리스트의 순차적 표현)
#include<stdio.h>
#include<stdlib.h>
#define MAX_LIST_SIZE 100
typedef int element;
typedef struct {
element array[MAX_LIST_SIZE]; // 배열의 정의
int size; // 현재 리스트에 저장된 항목들의 개수
} ArrayListType;
// 오류 처리 함수
void init(ArrayListType* L)
{
L->size = 0;
}
// 리스트가 비어 있으면 1을 반환
// 그렇지 않으면 0을 반환
int is_empty(ArrayListType* L)
{
return L->size == 0;
}
// 리스트가 가득 차 있으면 1을 반환
// 그렇지 않으면 1을 반환
int is_full(ArrayListType* L)
{
return L->size == MAX_LIST_SIZE;
}
element get_entry(ArrayListType* L, int pos)
{
if (pos < 0 || pos >= L->size)
printf("위치 오류");
return L->array[pos];
}
// 리스트 출력
void print_list(ArrayListType* L)
{
int i;
for (i = 0; i < L->size; i++)
printf("%d->", L->array[i]);
printf("\n");
}
void insert_last(ArrayListType* L, element item)
{
if (L->size >= MAX_LIST_SIZE)
{
printf("리스트 오버플로우");
}
L->array[L->size++] = item;
}
void insert(ArrayListType* L, int pos, element item)
{
if (!is_full(L) && (pos >= 0) && (pos <= L->size)) {
for (int i = (L->size - 1); i >= pos; i--)
L->array[i + 1] = L->array[i];
L->array[pos] = item;
L->size++;
}
}
element delect(ArrayListType* L, int pos)
{
element item;
if (pos < 0 || pos >= L->size)
printf("위치 오류");
item = L->array[pos];
for (int i = pos; i < (L->size - 1); i++)
L->array[i] = L->array[i + 1];
L->size--;
return item;
}
int main(void)
{
// ArrayListType를 정적으로 생성하고 ArrayListType를 가리키는 포인터를 함수의 매개변수로 전달
ArrayListType list;
init(&list);
insert(&list, 0, 10); print_list(&list); // 0번째 위치에 10 추가
insert(&list, 0, 20); print_list(&list); // 0번째 위치에 20 추가
insert(&list, 0, 30); print_list(&list); // 0번째 위치에 30 추가
insert_last(&list, 40); print_list(&list); // 맨끝에 40 추가
delect(&list, 0); print_list(&list); // 0번째 항목 삭제
return 0;
}
6.2 연결 리스트(Linked List)
- 동적으로 크기가 변할 수 있고 삭제나 삽입 시에 데이터를 이동할 필요가 없는 연결된 표현
- 이 연결된 표현은 포인터를 사용하여 데이터들을 연결함
- 연결 리스트의 구조
- 연결리스트는 노드(node)들의 집합, 다른 노드로 가기 위해서는 현재 노드가 가지고 있는 포인터를 이용
- 연결 리스트에서는 연결 리스트의 첫번째 노드를 알아야 만이 전체의 노드에 접근할수 있음
- 따라서 연결 리스트마다 첫번째 노드를 가리키고 있는 변수가 필요한데 이것을 헤드포인터(head pointer)라고 한다
6.3 단순 연결 리스트(Single Linked List)
- 노드 들이 하나의 링크 필드를 가지며 이 링크 필드를 이용하여 모든 노드들이 연결. 마지막 노드의 링크 필드값 NULL
- 노드의 정의
- 노드는 자기 참조 구조체(자기 자신을 참조하는 포인터를 포함하는 구조체)를 이용하여 정의됨
#include<stdio.h>
#include<stdlib.h>
typedef int element;
typedef struct ListNode { // 노드 타입을 구조체로 정의
element data;
struct ListNode* link;
} ListNode;
// 공백 리스트 생성
// 구조체 변수 선언
ListNode* head = NULL;
- 노드의 생성
노드의 크기만큼 동적메모리를 할당 받음, 이 동적 메모리가 하나의 노드가됨. 동적메모리의 주소를 헤드 포인터인 head에 저장
head = (ListNode*)malloc(sizeof(ListNode));
- 노드의 연결
// 두번째 노드 생성
ListNode* p;
p = (ListNode*)malloc(sizeof(ListNode));
p->data = 20;
p->link = NULL;
// 첫번째 노드의 링크가 두번째 노드를 가리킴
head->link = p;
#include<stdio.h>
#include<stdlib.h>
typedef int element;
typedef struct ListNode { // 노드 타입을 구조체로 정의
element data;
struct ListNode* link;
} ListNode;
// 오류 처리 함수
void error(char* message)
{
fprintf(stderr, "%s\n", message);
exit(1);
}
ListNode* insert_first(ListNode* head, int value)
{
ListNode* p = (ListNode*)malloc(sizeof(ListNode));
p->data = value;
p->link = head; // 헤드 포인터의 값을 복사
head = p; // 헤드 포인터 변경
return head;
}
// 노드 pre 뒤에 새로운 노드 삽입
ListNode* insert(ListNode* head, ListNode* pre, element value)
{
ListNode* p = (ListNode*)malloc(sizeof(ListNode));
p->data = value;
p->link = pre->link;
pre->link = p;
return head;
}
ListNode* delete_first(ListNode* head)
{
ListNode* removed;
if (head == NULL) return NULL;
removed = head;
head = removed->link;
free(removed);
return head;
}
// pre가 가리키는 노드의 다음 노드를 삭제
ListNode* delete(ListNode* head, ListNode* pre)
{
ListNode* removed;
removed = pre->link;
pre->link = removed->link;
free(removed);
return head;
}
void print_list(ListNode* head)
{
for (ListNode* p = head; p != NULL; p = p->link)
printf("%d->", p->data);
printf("NULL \n");
}
int main(void)
{
ListNode* head = NULL;
for (int i = 0; i < 5; i++)
{
head = insert_first(head, i); // insert_first()가 반환된 헤드 포인터를 head에 대입
print_list(head);
}
for (int i = 0; i < 5; i++)
{
head = delete_first(head);
print_list(head);
}
return 0;
}
'CS Study > DataStructure' 카테고리의 다른 글
05 큐 (0) | 2022.01.20 |
---|---|
04 스택 (0) | 2022.01.20 |
03 배열, 구조체, 포인터 (0) | 2022.01.18 |
02 순환 (0) | 2022.01.18 |
01 자료구조와 알고리즘 (0) | 2022.01.18 |