380 likes | 629 Views
제 4 장 리스트. 리스트의 개요 배열 구조 : 삽입 / 삭제가 비효율적 리스트 구조 : 포인터 개념을 이용하여 삽입 / 삭제 연산을 효율적으로 수행 리스트의 구성 : data field & link data field : 실제 자료가 저장 link field : 다음 노드에 대한 포인터가 저장. data. data. data. data. link. link. link. link. 배열 Int a[7]. 3,4 삽입. a[0]. a[0]. a[0]. 1. 1. 1.
E N D
리스트의 개요 • 배열 구조 : 삽입/삭제가 비효율적 • 리스트 구조 : 포인터 개념을 이용하여 삽입/삭제연산을 효율적으로 수행 • 리스트의 구성 : data field & link • data field : 실제 자료가 저장 • link field : 다음 노드에 대한 포인터가 저장 data data data data link link link link
배열 Int a[7] 3,4 삽입 a[0] a[0] a[0] 1 1 1 a[1] 2 a[1] 2 a[1] 2 a[2] 5 a[2] a[2] 3 a[3] 6 a[3] a[3] 4 5 5 a[4] a[4] a[4] 6 6 a[5] a[5] a[5] a[6] a[6] a[6]
리스트 • 3추가 1 1 1 4 4 4 2 2 2 3 3
4.1 포인터 • 주소를 저장하기위한 공간 • 선언: 객체형 * 변수명; • 예제 : int * ptr; int a; • 선언시 “*변수명” 의 의미 => 주소저장공간 • 객체사용 • & : 주소연산자 • *: 역참조(간접지시) 연산자 • 예제 • ptr = &a; • ptr = a; • *ptr = a;
4.1 포인터 int *a1; int a2 = 10; a1 = &a2 *a1 = a2; printf(“%d %d %d %d”, a2, &a2, a1, *a1); 1000 a1 1002 a2
4.1 포인터 int *a1; int a2 = 10; a1 = &a2 *a1 = a2; printf(“%d %d %d %d”, a2, &a2, a1, *a1); 1002 1000 a1 10 1002 a2
4.1 포인터 • 포인터 사용시 주의할점 • 포인터는 항상 어떤 대상을 가리키고 있어야 함 • 어떤 대상도 가리키고 있지 않는 포인터는 항상 NULL로 초기화 • ‘\n;
4.1 포인터 • 동적기억장소 할당 => malloc int i, *pi; float f, *pf; pi = (int *) malloc(sizeof(int)); pf = (float *) malloc(sizeof(float)); *pi = 1024; *pf = 3.14; • 할당된 메모리 해제 => free free(pi); free(pf);
4.2 단순연결리스트 • 연결리스트 : 화살표로 표시된 링크를 가진 노드들의 순열 bat cat sat vat \n ptr
bat 4.2 단순연결리스트 vat • 연결리스트의 특징 • 노드들은 순차적 위치에 존재하지 않는다 • 노드들의 위치는 실행시마다 바뀔수 있다 cat sat bat cat sat vat \n ptr
4.2 단순연결리스트 • linked list의 활용 • 스택 / 큐 : 배열구조에 비해서 동적인 상황을 구성 • 다항식 문제의 해결 • 트리 및 그래프 구조의 표현 • 동적인 해싱 구조의 생성 • 메모리 세그멘테이션의 관리
4.2 단순연결리스트 • 연결 리스트 구성을 위한 기능 • 노드의 구조 정의: struct • 노드 생성 방법 : malloc • 노드 삭제 방법 : free
4.2 단순연결리스트 • 예제 [at로 끝나는 단어 리스트] typedef struct list_node *list_pointer; typedef struct list_node { char data[4]; list_pointer link; }; list_pointer ptr = NULL;
4.2 단순연결리스트 ptr \n • 공백 리스트 생성 • list_pointer ptr = NULL; • 공백 리스트 검사 • #define IS_EMPTY(ptr) (!(ptr))
ptr bat \n • 새 노드 생성 • ptr = (list_pointer) malloc(sizeof(list_node)); • 노드 필드에 값 지정 • 구조 멤버(structure member) 연산자 : ‘->’ e->name ≡ (*e).name strcpy(ptr->data,"bat"); ptr->link = NULL;
4.2 단순연결리스트 • 예제 : 2-노드 연결 리스트 10 20 \n ptr
10 20 \n ptr typedef struct list_node *list_pointer; typedef struct list_node { int data; list_pointer link; }; list_pointer ptr = NULL;
10 20 \n ptr list_pointer create2() { /* 두개의 노드를 가진 연결 리스트의 생성 */ list_pointer first, second; first = (list_pointer) malloc (sizeof(list_node)); second = (list_pointer) malloc (sizeof(list_node)); second->link = NULL; second->data = 20; first->data = 10; first->link = second; return first; }
4.2 단순연결리스트 • 예제 [리스트 삽입] • 함수 호출 : insert(&ptr, node); • #define IS_FULL(ptr) (!(ptr)) 10 20 \n ptr 15
node void insert(list_pointer *ptr, list_pointer node) { list_pointer temp; temp = (list_pointer) malloc (sizeof(list_node)); if (IS_FULL(temp)){ fprintf(stderr, “The memory is full\n”); exit(1); } temp->data = 15; if (*ptr) { temp->link = node->link; node->link = temp; } else { temp->link = NULL; *ptr = temp; } } 10 20 \n ptr 15 temp 20 \n ptr
10 15 20 \n ptr trail node • 예제 : 리스트의 삭제 void deleteq(list_pointer *ptr, list_pointer trail, list_pointer node) { /노드삭제, trail은 삭제될 node의 선행노드이며 ptr은 리스트의 시작 */ if (trail) tail->link = node->link; else *ptr=(*ptr)->link; free(node); }
10 15 20 \n ptr • 예제 : 리스트의 출력 void print_list(list_pointer ptr) { printf(“The list contains : “); for ( ; ptr; ptr=ptr->link) printf(“%4d”, ptr->data); printf(“\n”); }
4.2 단순연결리스트 • 연습문제 : 리스트에 포함된 노드의 수 int list_length(list_pointer ptr) { int len =0; while (ptr) { len++; ptr = ptr ->link; } return len; } 10 15 20 \n ptr
10 15 20 \n ptr • 연습문제 : 자료의 탐색 list-pointer list_search(list_pointer ptr, char *data) { while(ptr) { if (!strcmp(ptr->data, data)) return ptr else ptr = ptr->link; } return NULL; }
4.3 동적연결 스택과 큐 \n front rear 10 10 15 20 \n top
4.3 동적연결 스택과 큐 • 스택과 큐에 대한 함수 작성 • isFull • isEmpty • Add • Delete
4.3 동적연결 스택과 큐 • 스택 #define MAX_STACKS 10 /*스택의 최대 원소수 */ typedef struct { int key; /*기타필드*/ }element; typedef struct stack *stack_pointer; typedef struct stack { element item; stack_pointer link; }; Stack_pointer top; Stack_pointer mtop[MAX_STACKS]; top mtop[0] mtop[1] mtop[2] mtop[3] mtop[4]
4.3 동적연결 스택과 큐 • 스택의 초기 조건 top[i]=NULL, 0≤i<MAX_STACKS • 경계 조건 i번째 스택이 공백이면, top[i]=NULL 메모리가 가득차면, IS_FULL(temp)
4.3 동적연결 스택과 큐 • add(&top[stack_no],item); • item=delete(&top[stack_no]);
4.3 동적연결 스택과 큐 void add(stack_pointer *top, element item) { /*스택의 톱에 원소를 삽입*/ stack_pointer temp=(stack_pointer) malloc(sizeof(stack)); if (IS_FULL(temp)){ fprintf(stderr,”The memory is full\n”); exit(1); } temp->item = item; temp->link = *top; *top = temp; } \n top
4.3 동적연결 스택과 큐 Element delete(stack_pointer *top) { /*스택으로부터 원소를 삭제*/ stack_pointer temp = *top; element item; if (IS_EMPTY(temp)){ fprintf(stderr,”The stack is empty\n”); exit(1); } item = temp->item; *top = temp->link; free(temp); return item; } \n top
4.3 동적연결 스택과 큐 • 큐 #define MAX_QUEUE 10 /*큐의 최대원소수*/ typedef struct queue *queue_pointer; typedef struct queue{ element item; queue_pointer link; } queue_pointer front,rear; queue_pointer m_front[MAX_QUEUES],m_rear[MAX_QUEUES];
4.3 동적연결 스택과 큐 • 초기조건 front[i]=NULL, 0<=i<MAX_QUEUES • 경계조건 i번째 큐가 공백이면, front[i]=NULL 메모리가 가득차기만하면, IS_FULL(temp);
4.3 동적연결 스택과 큐 • addq(&front,&rear,item); • item=deleteq(&front);
front rear 10 10 15 20 \n void addq(queue_pointer *front, queue_pointer *rear, element item) { /*큐의 rear에 원소를 삽입*/ queue_pointer temp = (queue_pointer) malloc(sizeof (queue)); if(IS_FULL(temp)){ fprintf(stderr,”The memory is full\n”); exit(1); } temp->item = item; temp->link = NULL; if (*front) *rear->link = temp; else *front = temp; *rear = temp; }
front rear 10 10 15 20 \n element deleteq(queue_pointer *front) { /*큐에서 원소를 삭제*/ queue_pointer temp = *front; element item; if (IS_EMPTY(*front)){ fprintf(stderr,”The queue is empty\n”); exit(1); } item = temp->item; *front = temp->link; free(temp); return item; }
과제물 • 리스트를 이용한 동적 스택구현 • 리스트를 이용한 동적 큐 구현