chapter 10. 구조체와 리스트 처리 10.1 자기참조 구조체
DESCRIPTION
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. - PowerPoint PPT PresentationTRANSCRIPT
1
Chapter 10. 구조체와 리스트 처리
10.1 자기참조 구조체
- 자기 자신과 같은 형의 구조체를 포인트하는 포인터 멤버 필드를 갖는 구조체 - 동적 자료구조 (dynamic data strutures)
( 예 )struct list { int data; struct list *next;} a;
next : NULL 또는 다음 list 원소의 메모리 주소를 가짐 .NULL 은 list 의 끝 .
a
↑datanext → link( 연결 )
2
- node 의 작성
struct list a, b, c;
a.data = 1;
b.data = 2;
c.data = 3;
a.next = b.next = c.next = NULL;
↑ NULL
1a
↑ NULL
2b
↑ NULL
3c
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)
↑
1a
↑
2b
↑
3c
═
4
10.2 선형 연결 리스트 (Linear linked-lists)
- 구조체 자료들이 순차적으로 연결됨 .
↑
1
↑
2
↑
3
═
↑head
5
( 예 ) "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) 은 기억장소를 할당받지 않음 .
변수가 선언될 경우에만 기억장소를 할당함 .
6
- 기억장소의 동적할당
( 예 )
LINK head;
head = malloc(sizeof(ELEMENT));
• ELEMENT type 의 기억장소가 동적으로 할당된 후 그 주소가 head 에 저장됨 .
- linear linked - list 의 작성 예
• 'n', 'e', 'w' 를 저장하는 linear linked-list
head = malloc(sizeof(ELEMENT));
head
↑ ↑
7
head -> d = 'n';
head -> next = NULL;
head -> next = malloc(sizeof(ELEMENT));
head -> next -> d = 'e';
head -> next -> next = NULL;
head
↑ n ↑
head
↑ n ↑═
head
↑ n ↑ e ↑═
8
head -> next -> next = malloc(sizeof(ELEMENT));
head -> next -> next -> d = 'w';
head -> next -> next -> next = NULL;
head
↑ n ↑ e ↑ w ↑═
9
10.3 리스트 연산
- 기본연산• 리스트 생성• 원소 개수 세기• 원소 탐색• 두 리스트의 결합• 원소 삽입• 원소 삭제
10
( 예 ) 문자열의 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; }}
11
문자열 : s
A : call w/ s
B : call w/ s+1
C : call w/ s+2
a b c \0
a b c \0
head
↑ a ↑ ?
head
↑ b ↑ ?
head
↑ c ↑ ?
b c \0
c \0
12
D : call w/ s+3
return NULL;
C' :
B' :
A' :
head
↑ c ↑
\0
═head
↑ b ↑ c ↑ ═
head
↑ a ↑ b ↑ c ↑ ═
13
- ( 예 ) 문자열의 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; }
14
• list w/ one element
• 두번째 element 첨부
• tail 의 갱신
head
tail
↑
↑
a ↑ ?
head
tail
↑
↑
a ↑ ? ↑ ?
head
tail
↑
↑
a ↑ b ↑ ?
15
• 세번째 element 첨부
• tail 의 갱신
• '\0' 를 발견
head
tail
↑
↑
a ↑ b ↑ ? ↑ ?
head
tail
↑
↑
a ↑ b ↑ c ↑ ?
head
tail
↑
↑
a ↑ b ↑ c ↑
〓
16
10.4 리스트 처리 함수
- 리스트의 원소의 수를 세는 함수
• 재귀 version
int count(LINK head)
{
if (head == NULL)
return 0; else
return (1 + count(head -> next));
}
17
• for loop 사용
int count(LINK head)
{
int cnt = 0;
for ( ; head != NULL; head = head -> next)
++ cnt;
return cnt;
}
18
- 리스트의 원소를 출력
• 재귀 version
void print_list(LINK head)
{
if (head == NULL)
printf("\nNULL");
else {
printf("\n%c --> ", head -> d);
print_list(head -> next);
}
}
19
- 문자열 "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));}
( 실행결과 )The resulting list isa --> b --> c --> NULLNumber of elements : 3
20
- 두 list 의 결합
void concatenate(LINK a, LINK b)
{
assert(a != NULL);
if (a -> next == NULL)
a -> next = b;
else
concatenate(a -> next, b);
}
21
- 새로운 원소의 삽입 : 고정된 시간 안에 삽입가능 .
(c.f. array : 배열의 길이에 비례 )
• 삽입전
void insert(LINK p1, LINK p2, LINK q){ assert(p1 -> next == p2);
p1 -> next = q;
q -> next = p2;}
P1P2
...q
A ↑ C ↑
B ↑
...
〓
22
• 삽입 후P1
P2
...q
A ↑ C ↑
B ↑
...
23
- 원소의 삭제• 삭제 전
/* temp = p -> next; */
p -> next = p -> next -> next;
/* free(temp); */
• 삭제 후
P
...A ↑ C ↑B ↑ ...
P
...A ↑ C ↑B ↑ ...
temp
24
- 리스트의 삭제 : 재귀호출
void delete_list(LINK head){
if (head != NULL) {
delete_list(head -> next); free(head);
}}
25
10.5 stacks
- 구현
cnt↑ top
stack
data
↑
elem
data
↑
data
↑NULL
• •
•
〓
26
- "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;
27
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);
28
- 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++;}
29
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;
}
30
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));}
31
( 예 ) 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
32
< 비교 > 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
33
10.6 Polish Notation
10.7 Queue
- 선형 연결 리스트를 이용
- FIFO(First-In-First-Out)
- 구현
count
front
rear
queue
data
↑ data
↑ data
↑
elem
삽입 : list 의 rear 에 삽입됨 .삭제 : list 의 front 에서 삭제됨 .
34
- "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;
};
35
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);
36
- "queue.c"
#include "queue.h"
void initialize(queue *q){
q -> cnt = 0; q -> front = NULL; q -> rear = NULL;
}
0
NULL
NULL
queue
37
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);}
38
n
front
rear
queue
54 ↑
(n - 1)
13
d p
13 ↑ 7 ↑•••
39
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 ++;}
40
n
front
rear
queue
250 ↑
(n + 1)
p d
5 ↑ 13 ↑
d NULL
•••
41
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));}
42
숙제 .
1. 문자열을 입력하여 각 문자를 element 의 data 로 하는 linked-list 를 작성한 후 linked-list 의 모든 문자를 출력하는 program 을 작성하라 .
2. 위의 data 를 이용하여 문자열의 길이를 출력하는 program 을 작성하라 .
3. 한 문자를 입력 받아 그 문자가 위의 linked-list 에 있으면 그 element 를 list 에서 제외한 후 남은 문자열을 출력하고 ,
그 문자가 없으면 message 와 함께 문자열을 출력하는 program 을 작성하라 .
43
숙제 .
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 를 사용할 것 )