430 likes | 647 Views
a. data next → link( 연결 ). ↑. Chapter 10. 구조체와 리스트 처리 10.1 자기참조 구조체 - 자기 자신과 같은 형의 구조체를 포인트하는 포인터 멤버 필드를 갖는 구조체 - 동적 자료구조 (dynamic data strutures) ( 예 ) struct list { int data; struct list *next; } a; next : NULL 또는 다음 list 원소의 메모리 주소를 가짐 . NULL 은 list 의 끝. a. b.
E N D
a data next → link(연결) ↑ Chapter 10. 구조체와 리스트 처리 10.1 자기참조 구조체 - 자기 자신과 같은 형의 구조체를 포인트하는 포인터 멤버 필드를 갖는 구조체- 동적 자료구조(dynamic data strutures) (예) struct list { int data; struct list *next; } a; next : NULL 또는 다음 list 원소의 메모리 주소를 가짐. NULL 은 list 의 끝.
a b c 1 2 3 ↑ NULL ↑ NULL ↑ NULL - node의 작성 struct list a, b, c; a.data = 1; b.data = 2; c.data = 3; a.next = b.next = c.next = NULL;
a b c 1 2 3 ↑ ↑ ↑ - node의 연결 a.next = &b; b.next = &c; - 연결된 원소의 자료 검색 a.next -> data : 2 (b.data) b.next -> data : 3 (c.data) a.next -> next -> data : 3 (c.data) ═
10.2 선형 연결 리스트(Linear linked-lists) - 구조체 자료들이 순차적으로 연결됨. head ↑ 1 2 3 ↑ ↑ ↑ ═
(예) "list.h" #include <stdio.h>#include <stdlib.h> typedef char DATA; struct linked_list { DATA d; struct linked_list *next; } ; typedef struct linked_list ELEMENT; typedef ELEMENT *LINK; - 위의 명세들(typedef)은 기억장소를 할당받지 않음. 변수가 선언될 경우에만 기억장소를 할당함.
↑ • - 기억장소의 동적할당 • (예) • LINK head; • head = malloc(sizeof(ELEMENT)); • ELEMENT type의 기억장소가 동적으로 할당된 후 그 주소가 head에 저장됨. • - linear linked - list의 작성 예 • 'n', 'e', 'w'를 저장하는 linear linked-list • head = malloc(sizeof(ELEMENT)); head ↑
n ↑ n ↑ n ↑ e ↑ • head -> d = 'n'; • head -> next = NULL; • head -> next = malloc(sizeof(ELEMENT)); • head -> next -> d = 'e'; • head -> next -> next = NULL; head ↑ head ↑ ═ head ↑ ═
n ↑ e ↑ w ↑ • head -> next -> next = malloc(sizeof(ELEMENT)); • head -> next -> next -> d = 'w'; • head -> next -> next -> next = NULL; head ↑ ═
10.3 리스트 연산 • - 기본연산 • 리스트 생성 • 원소 개수 세기 • 원소 탐색 • 두 리스트의 결합 • 원소 삽입 • 원소 삭제
(예) 문자열의 list 변환 - recursion(list는 재귀적으로 정의됨.) #include "list.h" LINK string_to_list(char s[]){ LINK head; if (s[0] == '\0') return NULL; else { head = malloc(sizeof(ELEMENT)); head -> d = s[0]; head -> next = string_to_list(s + 1); return head; }}
a ↑ ? b ↑ ? c ↑ ? 문자열 : s A : call w/ s B : call w/ s+1 C : call w/ s+2 head ↑ head ↑ head ↑
c ↑ b ↑ c ↑ a ↑ b ↑ c ↑ D : call w/ s+3 return NULL; C' : B' : A' : head ↑ ═ head ↑ ═ head ↑ ═
- (예) 문자열의 list 변환 : repetition(반복) #include "list.h" LINK s_to_l(char s[]){ LINK head = NULL, tail; int i; if (s[0] != '\0') { head = malloc(sizeof(ELEMENT)); /* 1st element */ head -> d = s[0]; tail = head; for (i = 1; s[i] != '\0'; ++i) { tail -> next = malloc(sizeof(ELEMENT)); tail = tail -> next; tail -> d = s[i]; } tail -> next = NULL; } return head; }
b ↑ ? ? ↑ ? a ↑ a ↑ • list w/ one element • 두번째 element 첨부 • tail의 갱신 head ↑ a ↑ ? tail ↑ head ↑ tail ↑ head ↑ tail ↑
a ↑ c ↑ ? b ↑ a ↑ c ↑ a ↑ b ↑ ? ↑ ? b ↑ • 세번째 element 첨부 • tail의 갱신 • '\0'를 발견 head ↑ tail ↑ head ↑ tail ↑ head ↑ tail 〓 ↑
10.4 리스트 처리 함수 • - 리스트의 원소의 수를 세는 함수 • 재귀 version • int count(LINK head) • { • if (head == NULL) • return 0; else • return (1 + count(head -> next)); • }
for loop 사용 • int count(LINK head) • { • int cnt = 0; • for ( ; head != NULL; head = head -> next) • ++ cnt; • return cnt; • }
- 리스트의 원소를 출력 • 재귀 version • void print_list(LINK head) • { • if (head == NULL) • printf("\nNULL"); • else { • printf("\n%c --> ", head -> d); • print_list(head -> next); • } • }
- 문자열 "abc"를 list로 바꾸고 그 list를 출력 #include "list.h" LINK string_to_list(char []);void print_list(LINK);void count(LINK); void main(){ LINK h; h = string_to_list("abc"); printf("The resulting list is \n"); print_list(h); printf("\nNumber of elements : %d", count(h));}
- 두 list의 결합 void concatenate(LINK a, LINK b) { assert(a != NULL); if (a -> next == NULL) a -> next = b; else concatenate(a -> next, b); }
A ↑ C ↑ B ↑ • - 새로운 원소의 삽입 : 고정된 시간 안에 삽입가능. • (c.f. array : 배열의 길이에 비례) • 삽입전 • void insert(LINK p1, LINK p2, LINK q){ assert(p1 -> next == p2); • p1 -> next = q; • q -> next = p2;} P2 P1 ... ... q 〓
A ↑ C ↑ B ↑ • 삽입 후 P2 P1 ... ... q
A ↑ C ↑ B ↑ A ↑ C ↑ B ↑ • - 원소의 삭제 • 삭제 전 • /* temp = p -> next; */ • p -> next = p -> next -> next; • /* free(temp); */ • 삭제 후 P ... ... P ... ... temp
- 리스트의 삭제 : 재귀호출 void delete_list(LINK head) { if (head != NULL) { delete_list(head -> next); free(head); } }
10.5 stacks - 구현 stack elem ••• 〓
- "stack.h" #include <stdio.h> #include <stdlib.h> #define EMPTY 0#define FULL 10000 typedef char data;typedef enum {false, true} boolean; struct elem { data d; struct elem *next; }; typedef struct elem elem;
struct stack { int cnt; elem *top; }; typedef struct stack stack; void initialize(stack *stk);void push(data d, stack *stk);data pop(stack *stk);data top(stack *stk);boolean empty(const stack &stk);boolean full(const stack &stk);
- ADT stack(linked - list version) #include "stack.h" void initialize(stack *stk){ stk -> cnt = 0; stk -> top = NULL;} void push(data d, stack *stk){ elem *p; p = malloc(sizeof(elem)); p -> d = d; p -> next = stk -> top; stk -> top = p; stk -> cnt++;}
data pop(stack *stk){ data d; elem *p; d = stk -> top -> d; p = stk -> top; stk -> top = stk -> top -> next; stk -> cnt--; free(p); return d; }
data top(stack *stk){ return (stk -> top -> d);} boolean empty(const stack *stk){ return ( (boolean)(stk -> cnt == EMPTY));} boolean full(const stack stk){ return ( (boolean)(stk -> cnt == FULL));}
(예) reverse stringint main(){ chat str[] = "Mary had a little lamb"; int i; stack s; initialize(&s); printf("In the string : %s\n", str); for (i = 0; str[i] != '\0'; ++i) if (!full(&s))push(str[i], &s); printf("From the stack : "); while(!empty(&s)) putchar(pop(&s)); putchar('\n'); return 0;} (실행결과)In the string : Mary had a little lamb.From the stack : .bmal ettil a dah yraM
<비교> ADT stack(array의 사용 예)#include <stdio.h>void main(){ char str[] = "Mary had a little lamb."; int i; stack s;reset(&s); /* stack의 초기화 */ printf("In the string : %s\n", str); for (i = 0; str[i] != '\0'; ++i) if (!full(&s))push(str[i], &s); printf("From the stack"); while(!empty(&s)) putchar(pop(&s)); putchar('\n');} (실행결과)In the string : Mary had a little lamb.From the stack : .bmal ettil a dah yraM
10.6 Polish Notation 10.7 Queue - 선형 연결 리스트를 이용 - FIFO(First-In-First-Out) - 구현 queue 삽입 : list의 rear에 삽입됨. 삭제 : list의 front에서 삭제됨. elem
- "queue.h" #include <assert.h> #include <stdio.h> #include <stdlib.h> #define EMPTY 0 #define FULL 10000 typedef unsigned int data; typedef enum {false, true} boolean; struct elem { data d; struct elem *next; };
typedef struct elem elem; struct queue { int cnt; elem *front; elem *rear; }; typedef struct queue queue; void initialize(queue *q);void enqueue(data d, queue *q);data dequeue(queue *q);data front(const queue *q);boolean empty(const queue *q);boolean full(const queue *q);
- "queue.c" #include "queue.h" void initialize(queue *q){ q -> cnt = 0; q -> front = NULL; q -> rear = NULL; } queue
data dequeue(queue *q){ data d; elem *p; d = q -> front -> d; p = q -> front; q -> front = q -> front -> next; q -> cnt--; free(p); return (d);}
queue (n - 1) ••• p d
void enqueue(data d, queue *q){ elem *p; p = malloc(sizeof(elem)); p -> d = d; p -> next = NULL; if(!empty(q)) { q -> rear -> next = p; q -> rear = p; } else q -> front = q -> rear = p; q -> cnt ++;}
queue (n + 1) ••• d p
data front(const queue *q){ return (q -> front -> d);} boolean empty(const queue *q){ return ( (boolean)(q -> cnt == EMPTY));} boolean full(const queue *q){ return ( (boolean)(q -> cnt == FULL));}
숙제. 1. 문자열을 입력하여 각 문자를 element의 data로 하는linked-list를 작성한 후 linked-list의 모든 문자를 출력하는 program을 작성하라. 2. 위의 data를 이용하여 문자열의 길이를 출력하는 program을 작성하라. 3. 한 문자를 입력 받아 그 문자가 위의 linked-list에 있으면 그 element를 list에서 제외한 후 남은 문자열을 출력하고,그 문자가 없으면 message와 함께 문자열을 출력하는program을 작성하라.
숙제. 4. 10, 20, 30, 40, 50으로 linked-list를 만들고0~60 사이의 정수를 입력하여list에 ascending order를 지켜 추가한 후list의 모든 수를 출력하는 program을 작성하라.단, 입력은 여러번 주어진다. (약 10회 정도) 5. 문자열을 입력하여 각 문자를 element로 하는stack과 queue를 작성한 후's'를 입력하면 순서대로 (queue를 이용), 'r'을 입력하면 역순으로(stack을 이용) 출력하는 program을 작성하라.(ADT를 사용할 것)