C로 배우는 쉬운 자료구조 개정 3판 Chapter 04 연습문제 (2024)

C로 배우는 쉬운 자료구조

C로 배우는 쉬운 자료구조 개정 3판 Chapter 04 연습문제

가속 2020. 6. 8. 19:32

URL 복사 이웃추가

본문 기타 기능

신고하기

01. 연결 리스트를 사용하기에 적합한 경우는?

① 자료를 정렬하는 경우

② 자료를 역순으로 처리하는 경우

③ 자료의 삽입과 삭제가 많은 경우

④ 자료를 탐색하는 경우

연결 리스트는 데이터 이외에 다른 노드를 가리키는 주솟값을 가지기 때문에 배열에 비해 삽입과 삭제가 간단하다

02. 성격이 다른 자료구조는?

① Stack

② Queue

③ Linked List

④ Circular Queue

4번 원형 큐는 배열을 이용한 순차 자료구조임

03. 연결 리스트에 대한 설명으로 거리가 먼 것은?

① 노드의 삽입과 삭제가 쉽다.

② 노드들이 포인터로 연결되어 있어 탐색이 빠르다.

③ 연결해 주는 포인터를 위한 추가 공간이 필요하다.

④ 연결 리스트 중에서 중간 노드 연결이 끊어지면 그 다음 노드를 찾기 어렵다.

연결 리스트는 배열에 비해 탐색 속도가 떨어진다.

연결 리스트의 장점은 삽입과 삭제가 용이한 것이다.

04. 다음과 같은 단순 연결 리스트에 대해, 아래와 같은 C언어로 작성된 프로그램을 수행한 후 포인터 tmp가 가리키는 노드는?

L P

↓ ↓

data link → . . . . . →data link → data link → data NULL

가 나 다 라

for (tmp = L; tmp->link != p; tmp = tmp -> link);

tmp -> link = p -> link;

① 가

② 나

③ 다

④ 라

초기식 tmp = L

조건식 tmp의 link(temp 의 다음 노드)가 P가 아닐때 까지 반복

변화식 tmp = temp -> link

반복문을 마치면 tmp는 P 노드의 이전 노드인 '나' 노드를 가리키게 된다.

이후 tmp -> link = p -> link

tmp 의 link가 p의 link(라) 를 가리키게 되어

연결 순서는

가 . . . . 나 라 가 된다.

이 코드는 '다' 노드를 삭제하기 위한 코드인 걸 알 수 있다.

05. n개의 데이터로 구성된 선형 리스트를 단순 연결 리스트로 표현하고자 한다. 다음 중 시간 복잡도가 가장 낮은 연산은?

① 포인터가 가리키는 노드의 다음 노드를 리스트에서 삭제

② 리스트 길이를 출력

③ 포인터 값이 주어진 임의의 노드 앞에 새로운 노드 추가

④ 마지막 노드의 데이터

① 삭제할 이전 노드의 주솟값이 주어졌기 때문에 바로 삭제 연산을 진행할 수 있다.

② ④ n번의 탐색이 필요하다.

③ 임의의 노드 앞의 노드를 찾기 위한 탐색 과정이 필요하다.

Index

Name

Pointer

1

KIM

6

2

PARK

1

3

CHOI

4

4

BAEK

2

5

LEE

7

6

MIN

5

7

ANN

8

8

JUNG

-

06. 다음 선형 연결 리스트리스트에서 LEE를 찾기 위한 비교 횟수는? (단, HEADER는 3이다.)

위 표 참고

① 4

② 5

③ 6

④ 7

3 → 4 → 2 → 1 → 6 → 5(LEE)

6회

07. C 언어를 사용해 연결 리스트를 구현할 때, 관련이 없는 것은?

① 비트 단위 논리곱

② 자기 참조 구조체

③ 동적 메모리 할당

④ 포인터

메모리 주소

data

link

2000

A

2020

2010

B

2030

2020

C

2010

2030

D

08. 자료들이 단순 연결 리스트에 다음과 같이 구성되어 있을 때, 자료 B를 삭제한 후 변경된 내용으로 옳은 것은?

위 표 참고

① A의 link → 2030

B의 link → 2010

③ B의 link → 2020

④ C의 link → 2030

자료의 연결 순서는

A (2000) → C (2020) → B (2010) → D(2030) 이다.

B를 삭제할 경우

A (2000) → C (2020) → D(2030)가 되는데

C의 link가 D로 바뀌었다.

09. 다음 포인터 연산의 의미를 설명하시오.

(가) p = p.link;

(나) p = q;

(다) p.link = q;

(라) p.link = q.link

(가) p를 p의 다음 노드로 설정한다.

(나) p가 가리키는 값은 q가 된다.

(다) p의 다음 노드는 q 노드이다.

(라) p의 다음 노드는 q의 다음 노드이다.

10. 단순 연결 리스트 L에서 특정 노드 p 바로 뒤에 새로운 노드 new를 삽입하기 위한 연산 insertAfter의 가상코드가 다음과 같다. ㉠에 들어갈 내용으로 옳은 것은?

Algorithm insertAfter(L, p, new)

if L = NULL

then L ← new;

else

end if

return

① p.next ← new; new. next ← p.next;

② new.next ← p.next; p.next ← new;

③ new.next ← p; p.next ← new;

④ p.next ← new; new.next ← p;

L이 NULL이 아닐 때 new 노드를 삽입하는 연산이 필요하다.

new의 다음 노드를 p의 다음 노드로 설정하고

p의 다음 노드를 new노드로 설정한다.

순서가 바뀌면 원래 p의 다음 노드값을 찾을 수 없게 된다.

11. 다음 C코드에서 foobar 함수가 하는 일을 바르게 설명한 것은?

struct list_t{

int data;

struct list_t *link;

};

typedef struct list_t *list_p;

void foobar(list_p *ptr, struct list_t *node){

if (*ptr == NULL){

*ptr = node;

node -> link = node;

}

else{

node -> link = (*ptr) -> link;

(*ptr) -> link = node;

}

}

① 한 줄로 연결된 단순 연결 리스트에서 *ptr이 가리키는 노드의 뒤에 node를 삽입, 리스트가 비어 있으면 node로 새로 리스트를 만든다.

② 한 줄로 연결된 이중 연결 리스트에서 *ptr이 가리키는 노드의 뒤에 node를 삽입, 리스트가 비어 있으면 node로 새로 리스트를 만든다.

③ 원형으로 연결된 단순 연결 리스트에서 *ptr이 가리키는 노드의 뒤에 node를 삽입, 리스트가 비어 있으면 node로 새로 리스트를 만든다.

④ 원형으로 연결된 이중 연결 리스트에서 *ptr이 가리키는 노드의 뒤에 node를 삽입, 리스트가 비어 있으면 node로 새로 리스트를 만든다.

foobar 함수는 *ptr이 NULL일 경우에는 node로 원형 리스트를 만든다.

NULL아닐 경우에는 *ptr의 뒤에 node를 삽입한다.

12. 다음 알고리즘은 주어진 단순 연결 리스트를 역순으로 변환하는 알고리즘이다. 알고리즘의 ㉠에 들어갈 내용으로 옳은 것은? (단, 리스트의 시작 주소를 나타내는 포인터는 start이며 노드의 연결 포인터 필드는 link이다.)

p = start;

q = NULL;

while (p != NULL){

p = p -> link;

q -> link = r;

}

start = q;

① q = q -> link; r = q;

② r = q; q = p;

③ r = q; p -> link;

④ q = q -> link;

역순으로 변환하려면 연결 리스트가 3개 필요하다.

13. 구조체 list를 이용한 단순 연결 리스트 x, y의 후위 노드(색칠된 부분)들을 서로 스왑(Swap)하기 위한 코드는? (단, 후위 노드들의 next는 NULL이 아니다.)

x → data next → (색칠된 부분) → data next → . . .

y → data next → (색칠된 부분) → data next → . . .

struct list{

int data;

struct list *next;

}*x, *y, *tmp

보기 생략

임의로 각 노드의 데이터를 x1, x2, x3 , y1, y2, y3라고 한다.

tmp = x -> next -> next;

x -> next -> next = y -> next -> next;

y -> next -> next = tmp;

tmp = x -> next;

x -> next = y -> next;

y -> next = tmp;

임의로 각 노드의 데이터를 x1, x2, x3 , y1, y2, y3라고 한다.

① tmp는 x3 노드를 가리킨다

② x2의 다음 노드를 y3 노드로 설정

③ y2의 다음 노드를 tmp노드로 설정(현재 tmp 노드는 x3을 가리킴)

④ tmp는 x2 노드를 가리킨다

⑤ x1의 다음 노드를 y2 노드로 설정

⑥ y1의 다음 노드를 tmp노드로 설정(현재 tmp노드는 x2를 가리킴)

아래 그림 처럼 연결하고 데이터를 순서대로 읽으면

x1 → y2 → x3 → . . . . .

y1 → x2 → y3 → . . . . .이 된다.

문제 13의 답

14. 희소행렬은 연결 리스트로 표현할 때 가장 큰 장점은?

① 기억 장소가 절약된다.

② 임의의 위치로 액세스가 가능하다.

③ 이진 탐색이 가능하다.

④ 행렬 사이의 연산 시간을 줄일 수 있다.

희소행렬을 이차원 배열로 표현할 경우 배열에 행 번호, 열 번호, 값인 3가지 데이터가 필요하다.

연결 리스트를 이용할 경우 값, 다음 노드의 주소 2가지 데이터만 있으면 된다.

15. 다음은 원형 연결 리스트의 길이를 구하는 함수이다. 원형 연결 리스트의 마지막 노드를 last가 가리키고 있을 때, ㉠에 들어갈 문장으로 옳은 것은?

int length(listPointer last){

listPointer temp = last;

int count = 0;

if (last){

for (count = 1; ㉠; count++)

temp = temp -> link;

}

return count;

}

① temp -> link != last

② temp == last -> link

③ temp != last -> link

④ temp -> link == NULL

last는 원형 연결 리스트의 마지막 노드를 가리킨다.

temp의 다음 노드가 last를 가리킨다면 한 바퀴를 탐색한 것이다.

16. 원형 연결 리스트 맨 앞에 새로운 노드를 삽입할 때, ㉠, ㉡에 대한 시간 복잡도는?

㉠ 포인터 ptr이 원형 연결 리스트의 맨 앞 노드를 가리키는 경우

㉡ 포인터 ptr이 원형 연결 리스트의 맨 뒤 노드를 가리키는 경우

㉠ ㉡

① O(1) O(1)

② O(1) O(n)

③ O(n) O(1)

④ O(n) O(n)

연결 리스트에 새로운 노드를 삽입하려면 삽입하고자 하는 위치 이전의 노드의 주소를 알아야한다.

㉠ 포인터 ptr이 맨 앞 노드를 가리킬 경우 그 앞 노드(마지막 노드)를 탐색하기 위한 연산이 추가로 필요하다.

㉡ 포인터 ptr이 마지막 노드를 가리킨다면 삽입하고자 하는 위치의 이전 노드의 주소를 알고 있는 것이니 바로 새로운 노드를 삽입할 수 있다.

17. 원형 연결 리스트 길이를 계산하기 위한 C 함수를 작성하고자 한다. ㉠과 ㉡에 들어갈 알맞은 명령은? (단, 원형 연결 리스트의 길이는 노드 개수로 정의하고, 원형 연결 리스트의 시작 포인터는 ptr이라고 가정한다.)

struct list_node{

char data;

struct list_node* link;

}

typedef struct list_node* list_pointer;

int CListLength(list_pointer ptr){

list_pointer temp;

int count = 0;

if ( ㉠ ){

temp = ptr;

do{

count++;

}while ( ㉡ );

}

return count;

}

㉠ ㉡

① !ptr temp -> link != ptr

② ptr temp = temp -> link, temp != ptr

③ !ptr temp = temp -> link, temp == ptr

④ ptr temp -> link == ptr

15번과 비슷한 문제지만 이 문제는 count가 0부터 시작한다.

temp와 ptr이 같아질 때까지 link를 타고 이동한다. 처음에 temp 를 ptr로 초기화 하기 때문에 do while문을 사용.

18. 이중 연결 리스트에서 노드 p 다음(next) 노드가 q이고 이전(prev) 노드가 p인 경우, 인접한 p, q 노드의 위치를 서로 바꾸는 연산 순서로 옳은 것은? (단, p, q 노드는 모두 연결 리스트의 처음 노드나 마지막 노드가 아니라고 가정한다.)

ㄱ. p -> preve -> next = q;

ㄴ. q -> next -> prev = p;

ㄷ. p -> prev = q;

ㄹ. q -> next = p;

ㅁ. q -> prev = p -> prev;

ㅂ. p -> next = q -> next;

① ㄱ → ㄴ → ㄷ → ㄹ → ㅁ → ㅂ

② ㄱ → ㄴ → ㅁ → ㅂ → ㄷ → ㄹ

③ ㄱ → ㄴ → ㅂ → ㄹ → ㄷ → ㅁ

④ ㄷ → ㄹ → ㅁ → ㅂ → ㄱ → ㄴ

19. 다음은 원형 연결 리스트의 맨 앞에 새로운 노드를 추가하는 알고리즘의 가상코드이다. ㉠, ㉡에 들어갈 문장으로 옳은 것은? (단, 원형 연결 리스트에서 last는 리스트의 맨 마지막 노드를 가리키는 포인터이고 초기치는 NULL 가상코드이며, 변수 p는 새로 삽입되는 노드를 나타낸다. 또한 리스트에 노드를 세 개 이상 추가할 수 있어야 한다.)

struct node{

int key;

struct node *next;

}*last = NULL; // 마지막 노드를 가리키는 포인터

Function insertFront(struct node *p)

if (last == NULL) then // 리스트가 빈 경우

last = p;

p -> next = p;

else // 리스트에 하나 이상의 노드가 있는 경우

end if

return;

end

㉠ ㉡

① p -> next = last -> next last -> next = p;

② last -> next = p; p -> next = last -> next;

③ p -> next = last; last -> next = p;

④ last -> next = p; p -> next = last;

원형 연결 리스트인 것에 주의

20. 이중 연결 리스트에서 포인터 p가 가리키는 노드의 오른쪽에 포인터 newNode가 가리키는 노드를 삽입할 때, 연산 순서가 바르게 나열된 것은? (단, llink는 왼쪽 노드를 가리키는 포인터이고 rlink는 오른쪽 노드를 가리키는 포인터이다.)

ㄱ. p -> rlink = newNode;

ㄴ. newNode -> llink = p;

ㄷ. newNode -> rlink = p -> rlink;

ㄹ. p -> rlink -> llink = newNode;

① ㄱ - ㄴ - ㄷ- ㄹ

② ㄴ - ㄱ - ㄹ- ㄷ

③ ㄴ - ㄷ- ㄱ - ㄹ

④ ㄴ - ㄷ - ㄹ - ㄱ

ㄴ - ㄷ - ㄱ - ㄹ의 순으로 하면

ㄹ이 p -> rlink -> rlink -> llink가 되어야함.

21. 다음 코드는 가용 공간 리스트로부터 노드를 할당받아 이중 연결 리스트에 새로운 값 x를 삽입하기 위한 함수의 일부이다. 할당받은 노드에 대한 포인터는 new이고, 이중 연결 리스트에서 삽입 위치는 pre가 가리키는 노드 뒤라고 하자. ㉠, ㉡에 알맞은 문장은?

new ← getNode();

new.data ← x;

pre.rlink ← new;

new.llink ← pre;

㉠ ㉡

① new.rlink ← pre.rlink; new.rlink.llink ← new.llink;

new.llink ← pre.rlink; new.rlink.rlink ← new;

③ new.llink ← pre.rlink; new.rlink.rlink ← new.llink;

④ new.rlink ← pre.rlink; new.rlink.llink ← new;

㉠ ㉡ 뒤에서 pre의 오른쪽 link와 new의 왼쪽 link를 서로 연결하고 있다.

㉠과 ㉡에서는 new의 오른쪽 link를 연결하는 과정이 필요하다.

22. 이중 연결 리스트가 적당한 자료구조는?

① 스택

② 큐

③ 원형 큐

④ 데크

데크는 이중 연결 리스트를 사용해 큐의 양쪽 끝에서 데이터를 삽입하고 삭제할 수 있도록 확장된 큐 자료구조이다.

23. 다음 구조체를 갖는 이중 연결 리스트에서 A, B, C는 각각 노드를 가리키는 포인터 변수이다. 노드 B를 삭제하기 위한 명령으로 옳지 않은 것은?

struct Dlist{

int data;

struct Dlist *left;

struct Dlist *right;

};

그림 생략

① B -> right -> left = B -> left; B -> left -> right = B -> right;

② A -> right = C; C -> left = A;

③ A -> right = A -> right -> right; B -> right -> left = B -> left;

④ C -> left -> right = B -> right; C -> left = B -> left;

C -> left -> right == B -> right 이므로 의미 없는 문장이다.

24. 다음은 이중 연결 리스트의 맨 앞에 새로운 키값을 갖는 노드를 삽입하는 알고리즘이다. ㉠ ~ ㉢에 들어갈 문장으로 바르게 짝지어진 것은? (단, head는 이중 연결 리스트의 맨 앞 노드를 가리키는 포인터이며, 리스트는 초기에 비어 있다고 가정한다.

코드 생략

㉠ ㉡ ㉢

① temp -> prev = NULL temp -> prev = head temp -> prev = head

② temp -> prev = NULL temp -> next = NULL temp -> next = head

③ temp -> next = temp temp -> next = NULL temp -> prev = head

④ temp -> next = temp temp -> prev = head temp -> next = head

㉠ 우선 temp 의 이전 노드를 NULL로 설정한다. (맨 앞에 삽입할 거니까)

㉡ 리스트에 NULL이면 연결할 노드가 없으므로 temp의 다음 노드도 NULL로 설정한다.

㉢ temp는 맨 앞에 삽입할 노드이므로 next를 head와 연결해준다.

25. 순차 자료구조와 연결 자료구조를 비교하여 설명하시오.

순차 자료구조는 빈자리 없이 값을 저장하기 때문에 메모리를 적게 잡아먹는데

연결 자료구조는 값 이외에 다음 자료의 주소를 저장하여야 하기 때문에 순차 자료구조에 비해 메모리를 많이 잡아먹는다.

순차 자료구조는 데이터를 삽입하거나 삭제할 때 모든 원소를 이동시켜야 하는 반면

연결 자료구조는 다음 자료의 주소값만 바꾸어 주면 되기 때문에 삽입과 삭제가 쉽다.

순차 자료구조는 연결 자료구조에 비해 탐색이 빠르다.

26. 단순 연결 리스트, 원형 연결 리스트, 이중 연결 리스트의 특징을 비교하여 설명하시오.

단순 연결 리스트는 각 노드가 다음 노드를 가리키는 주솟값을 갖기 때문에 배열과 비교해 값의 삽입과 삭제가 쉽다.

원형 연결 리스트는 단순 연결 리스트의 마지막 노드가 첫 번째 노드를 가리키는 것으로 한 노드에서 모든 노드로 접근할 수 있다.

이중 연결 리스트는 이전 노드를 가리키는 주솟값과 다음 노드를 가리키는 주솟값을 둘다 저장한다. 그래서 값을 삽입하거나 삭제할 때 이전 노드의 주솟값을 따로 구하는 연산을 하지 않아도 된다.

27. 이중 연결 리스트가 필요한 경우를 예를 들어 설명하시오.

이중 연결 리스트는 이전 노드와 이후 노드의 주솟값을 둘 다 가지고 있다.

이는 인터넷 브라우저에서 이전 방문 / 이후 방문 기능에 사용된다.

인터넷을 사용하다가 이전에 방문했던 페이지를 방문할 때 이전 버튼을 누르면 방금 전의 페이지가 나오고

그 상태에서 또 이전 버튼이나 이후 버튼을 이용해 페이지를 방문할 수 있다.

한글이나 엑셀, 포토샵 등 편집 프로그램에도 사용된다.

해당 프로그램들에는 되돌리기(Ctrl+Z)와 다시 실행(Ctrl+Shift+Z or Ctrl + Y) 기능이 있다.

되돌리기 버튼을 누르면 방금 전에 수행한 동작을 원래대로 되돌린다.

그 상태에서 다시 실행을 누르면 되돌리기를 실행하여 취소했던 명령이나 동작을 다시 실행한다.

저장된 메모리가 허용하는 한 되돌리기 버튼을 계속 누를 수도 있다.

28. 다음과 같이 구조체 자료형인 _node를 선언하고 이를 이용해 연결 리스트를 만들었다. 다음 코드를 보고 물음에 답하시오. (단 시작 함수는 _tmain()이다.)

코드 생략

(가) 숫자 10, 5, 8, 3, 1, 7을 삽입하되 작은 수부터 연결 리스트가 유지되도록 함수 ordered_insert(int k)를 작성하시오. (단 k는 삽입하려는 정수이다.)

(나) 연결 리스트를 구성하는 각 node의 변수 data를 모두 출력하는 함수 print_list(node* t)를 작성하시오. (단, t는 node에 대한 시작 포인터이고, 화면에 출력할 함수는 printf()를 사용한다.

(다) 삭제하려는 숫자를 인수로 받아 그 노드를 삭제하는 함수 delete_node(int k)를 작성하시오. (단, k는 삭제하려는 정수이다.)

tail이 무슨 용도인지는 모르겠는데 쓰레기값이 저장되어서 값이 100,000 이상일 때 쓰레기값으로 판단 후 NULL처리

이후는 교재에 나오는 연결 리스트와 비슷함

#include <stdio.h>#include <stdlib.h>typedef struct _node{ int data; struct _node *next;}node;node *head, *tail;void init_list(){ head = (node*)malloc(sizeof(node)); tail = (node*)malloc(sizeof(node)); head -> next = tail; tail -> next = tail;}node *ordered_insert(int k){ node* newNode = (node*)malloc(sizeof(node)); newNode -> data = k; if (head -> next -> data >= 100000){ newNode -> next = NULL; head -> next = newNode; tail -> next = newNode; } else{ node* temp = head -> next; node* pre = NULL; while(k > temp -> data){ pre = temp; temp = temp -> next; } if (pre == NULL){ newNode -> next = temp; head -> next = newNode; } else{ newNode -> next = temp; pre -> next = newNode; } }}node* print_list(node* t){ int count = 0; printf("{"); while (t != NULL){ printf("%d", t -> data); t = t -> next; count++; if (count >= 10) break; if (t != NULL) printf(", "); } printf("} \n");}int delete_node(int k){ node* pre = head -> next; node* old; while (pre -> next -> data != k) pre = pre -> next; old = pre -> next; pre -> next = pre -> next -> next;}int main(){ node* t; init_list(); ordered_insert(10); ordered_insert(5); ordered_insert(8); ordered_insert(3); ordered_insert(1); ordered_insert(7); printf("\nInitial Linked list is "); print_list(head -> next); delete_node(8); print_list(head -> next); return 0;}

직접 푼 거라 틀린 문제가 있을 수 있습니다.

공감이 글에 공감한 블로거 열고 닫기

댓글23 이 글에 댓글 단 블로거 열고 닫기

인쇄

C로 배우는 쉬운 자료구조 개정 3판 Chapter 04 연습문제 (2024)

References

Top Articles
Latest Posts
Article information

Author: Golda Nolan II

Last Updated:

Views: 6432

Rating: 4.8 / 5 (58 voted)

Reviews: 81% of readers found this page helpful

Author information

Name: Golda Nolan II

Birthday: 1998-05-14

Address: Suite 369 9754 Roberts Pines, West Benitaburgh, NM 69180-7958

Phone: +522993866487

Job: Sales Executive

Hobby: Worldbuilding, Shopping, Quilting, Cooking, Homebrewing, Leather crafting, Pet

Introduction: My name is Golda Nolan II, I am a thoughtful, clever, cute, jolly, brave, powerful, splendid person who loves writing and wants to share my knowledge and understanding with you.