List
리스트
- 배열을 이용하여 리스트를 구현하면 순차적인 메모리 공간이 할당되므로, 이것을 리스트의 순차적 표현이라 함
- 일상생활에서의 리스트
- 버킷 리스트
- 해야 할 일 목록 등등…
리스트 구현
-
init() : 리스트의 사이즈를 0으로 초기화
- isEmpty() : 리스트의 사이즈가 0이면 비어있음 1 리턴
- isFull() : 리스트의 사이즈가 리스트의 크기와 같으면 꽉 참 1리턴
- insertLast() : 리스트가 꽉 차있는지 확인 이후 리스트에 원소 삽입
- insert() : 리스트가 꽉 차있는지 확인 이후 원하는 Index에 원소 값 삽입 -> 원하는 Index의 값을 넣기 위해 값을 하나씩 미뤄넣고 넣어야 함
- deleteLast() : 리스트가 비어있는지 확인 후 리스트의 값을 삭제
- delete() : 리스트가 비어있는지 확인 후 원하는 Index에 원소값을 삭제 -> 원하는 Index의 값을 삭제 하기 위해 값을 삭제 후 Index를 하나씩 당겨야 함
- print() : 리스트의 값을 하나씩 출력
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 100
typedef struct{
int data[N];
int size ;
}ListType;
void init(ListType *L){
L->size = 0;
}
int isEmpty(ListType *L)
{
return L->size == 0;
}
int isFull(ListType *L)
{
return L->size == N;
}
void insertLast(ListType *L, int elem){
if(isFull(L)){
printf("List is Full!!!\n");
return ;
}
else{
L->data[L->size] = elem;
L->size ++ ;
}
}
void insert(ListType *L, int pos, int elem)
{
if(isFull(L)){
printf("FULL\n");
return;
}
for(int i=L->size-1; i>=pos; i-- ){
L->data[i+1] = L->data[i];
}
L->data[pos] = elem;
L->size++;
}
int deleteLast(ListType *L){
if(isEmpty(L)){
printf("isEmpty\n");
return -1;
}
int elem = L->data[L->size -1];
L->size -- ;
return elem;
}
int delete(ListType *L, int pos){
if(isEmpty(L)){
printf("isEmpty\n");
return -1;
}
int elem = L->data[pos];
for(int i=pos; i < L->size-1; i++)
L->data[i] = L->data[i+1];
L->size -- ;
return elem;
}
void print(ListType *L){
for(int i=0; i<L->size; i++){
printf("%d -> ", L->data[i]);
}
printf("\b\b\b \n");
}
int main(){
ListType L;
init(&L);
insertLast(&L, 10); print(&L);
insertLast(&L, 20); print(&L);
insertLast(&L, 30); print(&L);
getchar();
insert(&L, 1, 40); print(&L);
insert(&L, 0, 50); print(&L);
insert(&L, 3, 60); print(&L);
getchar();
printf("[%d] is deleted.\n", deleteLast(&L)); print(&L);
printf("[%d] is deleted.\n", delete(&L, 2)); print(&L);
getchar();
return 0;
}
연결된 표현(연결된 리스트)
- 리스트의 항목들을 노드(node)라고 하는 곳에 분산하여 저장
- 노드(node)는 데이타 필드와 링크 필드로 구성
- 데이타 필드 - 리스트의 원소 , 즉 데이타 값을 저장한는 곳
- 링크 필드 - 다른 노드의 주소값을 저장하는 장소(포인터)
노드(node) = 데이타 필드 + 링크필드
# 포인터만 잘 설정해주면 삽입삭제가 기존 리스트보다 쉬움
- 장점 : 삽입, 삭제가 용이 , 연속된 메모리 공간이 필요없으며 크기 제한이 없다.
- 단점 : 구현이 어려우며, 오류가 발생하기 쉽다.
-
단순 연결리스트(한방향) : 하나의 링크필드만 가지고 있고 마지막 링크필드의 값은 무조건 NULL 포인터가 멈추는 지점이 필요
- 원형 연결리스트(끝에서 다시 처음으로) :
- 이중 연결리스트(양방향) :
단순 연결리스트(한방향) 구현
#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode{
char data;
struct ListNode* next ;
}ListNode; // Node의 구성요소 링크필드 + 데이타 필드
typedef struct{
ListNode * Head;
}ListType; // 리스트 타입 리스트를 사용 시 이 타입을 선언
void init(ListType *L){
L->Head = NULL;
}
void insertFirst(ListType *L, char elem){
ListNode* node =(ListNode*) malloc(sizeof(ListNode)); // 동적으로 메모리 할당
//Node 초기화
node->data = elem;
//데이터 초기화
node->next = L->Head;
// 널값 가져오기
L->Head = node;
// 이전 노드가 현재 노드를 가르키는 포인터
}
void insertLast(ListType *L, char elem){
ListNode* node =(ListNode*) malloc(sizeof(ListNode)); // 동적으로 메모리 할당
node->data = elem;
node->next = NULL;
ListNode* p = L->Head;
if(p==NULL){
L->Head = node;
}
else
{
while(p->next != NULL)
p = p->next;
p->next = node;
}
}
void print(ListType * L){
ListNode* p; //리스트 노드를 가르키는 빨간 화살표
for(p = L->Head; p != NULL; p = p->next){
printf("%c->", p->data);
}
printf("\n");
}
int main(void){
ListType L;
init(&L);
insertLast(&L, 'E'); print(&L);
insertFirst(&L, 'A'); print(&L);
insertFirst(&L, 'B'); print(&L);
insertFirst(&L, 'C'); print(&L);
getchar();
insertLast(&L, 'D'); print(&L);
return 0;
}