이진 탐색 트리를 연결 자료구조를 사용하여 표현하고 이진 탐색 트리에 대한 연산을 수행하는 프로그램


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#include<stdio.h>
#include<stdlib.h>
 
typedef struct treeNode {
    char key;        //데이터 필드
    struct treeNode* left;    //왼쪽 서브 트리 링크 필드
    struct treeNode* right;    //왼쪽 서브 트리 링크 필드
} treeNode;
 
typedef char element; //char을 이진 탐색 트리 element의 자료형으로 정의
 
treeNode* insertNode(treeNode *p, char x)
{    //포인터 p가 가리키는 노드와 비교하여 노드 x를 삽입하는 연산
    treeNode *newNode;
    if (p == NULL){
        newNode = (treeNode*)malloc(sizeof(treeNode));
        newNode->key = x;
        newNode->left = NULL;
        newNode->right = NULL;
        return newNode;
    }
    else if (x < p->key) p->left = insertNode(p->left, x);
    else if (x > p->key) p->right = insertNode(p->right, x);
    else printf("\n 이미 같은키가 있습니다! \n");
 
    return p;
}
 
void deleteNode(treeNode *root, element key)
{    //root 노드부터 탐색하여 key 값과 같은 노드를 찾아 삭제하는 연산
    treeNode *parent, *p, *succ, *succ_parent;
    treeNode *child;
 
    parent = NULL;
    p = root;
    while ((p != NULL) && (p->key != key)){
        parent = p;
        if (key < p->key) p = p->left;
        else p = p->right;
    }
    if (p == NULL){
        printf("\n 찾는 키가 이진 트리에 없습니다!!");
        return;
    }
 
    //삭제할 노드가 단말 노드인 경우
    if ((p->left == NULL) && (p->right == NULL)){
        if (parent != NULL){
            if (parent->left == p) parent->left = NULL;
            else parent->right = NULL;
        }
        else root = NULL;
    }
 
    //삭제할 노드가 한 개의 자식 노드를 가진 경우
    else if ((p->left == NULL|| (p->right == NULL)){
        if (p->left != NULL) child = p->left;
        else child = p->right;
 
        if (parent != NULL){
            if (parent->left == p) parent->left = child;
            else parent->right = child;
        }
        else root = child;
    }
 
    //삭제할 노드가 두 개의 자식 노드를 가진 경우
    else{
        succ_parent = p;
        succ = p->left;
        while (succ->right != NULL){
            succ_parent = succ;
            succ = succ->right;
        }
        if (succ_parent->left == succ) succ_parent->left = succ->left;
        else succ_parent->right = succ->left;
        p->key = succ->key;
        p = succ;
    }
    free(p);
}
 
treeNode* searchBST(treeNode* root, char x)
{        //이진 탐색 트리에서 키값이 x인 노드의 위치를 탐색하는 연산
    treeNode* p;
    p = root;
    while(p != NULL){
        if (x < p->key)p = p->left;
        else if (x == p->key) return p;
        else p = p->right;
    }
    printf("\n 찾는 키가 없습니다!");
    return p;
}
 
void displayInorder(treeNode* root)
{    //이진 탐색 트리를 중위 순회하면서 출력하는 연산
    if (root){
        displayInorder(root->left);
        printf("%c_", root->key);
        displayInorder(root->right);
    }
}
 
void menu()
{
    printf("\n*---------------------------*");
    printf("\n\t1 : 트리 출력");
    printf("\n\t2 : 문자 삽입");
    printf("\n\t3 : 문자 삭제");
    printf("\n\t4 : 문자 검색");
    printf("\n\t5 : 종료");
    printf("\n*---------------------------*");
    printf("\napsbdlqfur >> ");
}
 
int main()
{
    treeNode* root = NULL;
    treeNode* foundedNode = NULL;
    char choice, key;
 
    root = insertNode(root, 'G'); //트리 만들기
    insertNode(root, 'I');
    insertNode(root, 'H');
    insertNode(root, 'D');
    insertNode(root, 'B');
    insertNode(root, 'M');
    insertNode(root, 'N');
    insertNode(root, 'A');
    insertNode(root, 'J');
    insertNode(root, 'E');
    insertNode(root, 'Q');
 
    while (1){
        menu();
        choice = getchar(); getchar();
 
        switch (choice){
        case '1'printf("\t[이진트리 출력] ");
            displayInorder(root); printf("\n");
            break;
 
        case '2'printf("삽입할 문자를 입력하세요 : ");
            key = getchar(); getchar();
            insertNode(root, key);
            break;
 
        case '3'printf("삭제할 문자를 입력하세요 : ");
            key = getchar(); getchar();
            deleteNode(root, key);
            break;
 
        case '4'printf("찾을 문자를 입력하세요 : ");
            key = getchar(); getchar();
            foundedNode = searchBST(root, key);
            if (foundedNode != NULL)
                printf("\n %c 를 찾았습니다! \n", foundedNode->key);
            else printf("\n 문자를 찾지 못했습니다. \n");
            break;
 
        case '5'return 0;
 
        defaultprintf("없는 메뉴입니다. 메뉴를 다시 선택하세요! \n");
            break;
        }
    }
}
cs

 


출력 결과

 


작성조건

1. 프로그램 메뉴 : 서비스 요청 등록(큐 삽입) / 대기번호 출력 / 서비스 처리(큐 삭제)

2. 서비스 요청 등록의 고객 입력 사항 : 이름, 전화번호, 서비스 요청 품목(냉장고, TV, 핸드폰)


소스코드

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include <stdio.h>
#include<stdlib.h>
#include <malloc.h>
#include<string.h>
#include <stdbool.h>
typedef char element;
typedef struct QNode {
    element name[10];
    element phonenumber[20];
    int service;
    struct QNode *rink;
} QNode;
 
typedef struct {
    QNode *front*rear;
} LQueueType;
 
LQueueType * createLinkedQueue()
{
    LQueueType *LQ;
    LQ = (LQueueType *)malloc(sizeof(LQueueType));
    LQ->front = NULL;
    LQ->rear = NULL;
    return LQ;
}
 
int isEmpty(LQueueType *LQ)
{
    if (LQ->front == NULL) {
        printf("\n Linked Queue is empty!\n");
        return 1;
    }
    else return 0;
}
 
void enQueue(LQueueType *LQ, QNode *item)
{
    if (LQ->front == NULL) {
        LQ->front = item;
        LQ->rear = item;
    }
    else {
        LQ->rear->rink = item;
        LQ->rear = item;
    }
}
 
void deQueue(LQueueType *LQ , QNode *obj)
{
    QNode *old = LQ->front;
 
    if (!isEmpty(LQ))
    {
        *obj = *old;
        LQ->front = LQ->front->rink;
        if (LQ->front == NULL)
            LQ->rear = NULL;
        free(old);
    }
}
 
void main(void)
{
    LQueueType *LQ1 = createLinkedQueue();
    QNode *newNode;
    int iCount = 0;
    int select = 0;
    bool flag = true;
    while (flag) {
        printf("항목을 선택해주세요. 1.서비스 요청 등록   2. 대기번호 출력   3. 서비스 처리   4. 종료\n");
        scanf("%d", &select);
        QNode old;
        switch (select)
        {
        case 1:
            newNode = (QNode *)malloc(sizeof(QNode));
            printf("이름 입력 : "); 
            char name[10];
            scanf("%s", name);
            strcpy(newNode->name, name);
            printf("전화번호 입력 : ");
            char num[20];
            scanf("%s", num);
            strcpy(newNode->phonenumber, num);
            printf("서비스 요청 품목(냉장고 : 1, TV : 2, 핸드폰 : 3 중 하나 입력) : ");
            scanf("%d", &newNode->service);
            enQueue(LQ1, newNode);
            printf("\n\n");
            iCount++;
            break;
        case 2:
            printf("대기번호 : %d\n", iCount);
            break;
        case 3:
            deQueue(LQ1, &old);
            switch (old.service)
            {
            case 1:
                printf("이름 : %s 전화번호 : %s 서비스 요청 품목 : 냉장고\n", old.name, old.phonenumber);
                break;
            case 2:
                printf("이름 : %s 전화번호 : %s 서비스 요청 품목 : TV\n", old.name, old.phonenumber);
                break;
            case 3:
                printf("이름 : %s 전화번호 : %s 서비스 요청 품목 : 핸드폰\n", old.name, old.phonenumber);
                break;
            }
            iCount--;
            break;
        default:
            flag = false;
            break;
        }
    }
}
cs

 


출력결과

 


(C언어) 후위표기 수식의 연산 프로그램


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
typedef int element;    //int를 element로 변환
 
//원소를 저장할 스택노드 구조체 구현
typedef struct stackNode {
    element data;
    struct stackNode *link;
}stackNode;
 
//스택 최상단 변수 선언
stackNode* top;
 
 
void push(element item)        //연결 리스트 스택의 삽입 연산
{
    stackNode* temp = (stackNode *)malloc(sizeof(stackNode));
    temp->data = item;
    temp->link = top;
    top = temp;
}
 
element pop()        //연결 리스트 스택의 삭제 후 반환 연산
{
    element item;
    stackNode* temp = top;
 
    if (top == NULL) {
        printf("\n\n Stack empty!\n");
        return 0;
    }
    else {
        item = temp->data;
        top = temp->link;
        free(temp);
        return item;
    }
}
 
element peek()        //연결 리스트 스택의 top 원소 검색 연산
{
    element item;
    if (top == NULL) {
        printf("\n\n Stack is empty!\n");
        return 0;
    }
    else {
        item = top->data;
        return item;
    }
}
 
void del()        //연결 리스트 스택의 삭제 연산
{
    stackNode* temp;
    if (top == NULL) {
        printf("\n\n Stack is empty! \n");
    }
    else {
        temp = top;
        top = top->link;
        free(temp);
    }
}
 
void printStack()        //연결리스트 스택의 출력 연산
{
    stackNode* p = top;
    printf("\n STACK [ ");
    while (p) {
        printf("%d", p->data);
        p = p->link;
    }
    printf("] ");
}
 
element evalPostfix(char *exp)    //후위 표기법을 계산하는 연산
{
    int opr1, opr2, value, i = 0;
    int length = strlen(exp);
    char symbol;
    top = NULL;
 
    for (i = 0; i < length; i++) {
        symbol = exp[i];
        if (symbol != '+' && symbol != '-' && symbol != '*' && symbol != '/') {
            value = symbol - '0';
            push(value);
        }
        else {
            opr2 = pop();
            opr1 = pop();
            switch (symbol) {
            case '+': push(opr1 + opr2); break;
            case '-': push(opr1 - opr2); break;
            case '*': push(opr1 * opr2); break;
            case '/': push(opr1 / opr2); break;
            }
        }
    }
    return pop();
}
 
void main(void)
{
    int result;
    char* express = "35*62/-";
    printf("후위표기식 =>%s",express);
 
    result = evalPostfix(express);
    printf("\n\n연산결과 => %d", result);
 
    getchar();
}
cs

 


출력결과

 


(c언어) 이중 연결 리스트의 원소 삭제 알고리즘


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
 
//리스트 구조체 선언
struct Dnode {
    struct Dnode *llink;
    char data[5];
    struct Dnode *rlink;
};
struct DoubleList {
    struct Dnode *dNode;
};
 
struct DoubleList DL = { NULL };
 
void deleteNode(DoubleList DL, Dnode *old) 
{
    old->llink->rlink = old->rlink;
    old->rlink->llink = old->llink;
    free(old);
}
 
 
 
void main() {
    struct Dnode *dn, *dn1, *dn2;
    dn = (Dnode*)malloc(sizeof(Dnode));
    dn1 = (Dnode*)malloc(sizeof(Dnode));
    dn2 = (Dnode*)malloc(sizeof(Dnode));
    strcpy(dn->data, "apple");
    strcpy(dn1->data, "banana");
    strcpy(dn2->data, "orange");
 
    dn->llink = NULL;
    dn->rlink = dn1;
 
    dn1->llink = dn;
    dn1->rlink = dn2;
 
    dn2->llink = dn1;
    dn2->rlink = NULL;
    DL.dNode = dn;
 
    printf("------Before------\n");
    struct Dnode *Temp = DL.dNode;
    int cnt = 0;
    while (Temp != NULL)
    {
        printf("%d : %s\n", cnt++, Temp->data);
        Temp = Temp->rlink;
    }
 
 
    deleteNode(DL, dn1);
 
 
    printf("------after------\n");
    Temp = DL.dNode;
    cnt = 0;
    while (Temp != NULL)
    {
        printf("%d : %s\n", cnt++, Temp->data);
        Temp = Temp->rlink;
    }
 
    return;
}
 
 
cs

 


출력결과

 


(C언어) 원형 연결 리스트의 첫 번째 노드 삽입 알고리즘


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
 
struct List {
    char strData[11];
    struct List *nextList;
};
struct CircleList {
    struct List *List;
};
 
void insertFirstNode(struct CircleList *list, char *x);
 
void main() {
 
    struct CircleList CL = { NULL };
    
    insertFirstNode(&CL, "apple");
    insertFirstNode(&CL, "Banana");
    insertFirstNode(&CL, "Orange");
    struct List* temp = CL.List;
    do
    {
        printf("%s\t", temp->strData);
        temp = temp->nextList;
    } while (temp != CL.List);
    return;
}
 
void insertFirstNode(struct CircleList *list, char *x){
    struct List* newNode;
    newNode = (List*)malloc(sizeof(List));
    newNode->nextList = NULL;
    strcpy(newNode->strData, x);
 
    strcpy(newNode->strData, x);
    if (list->List == NULL) {
        list->List = newNode;
        newNode->nextList = newNode;
    }
    else {
        List *temp = list->List;
        while (temp->nextList != list->List)
        {
            temp = temp->nextList;
        }
        newNode->nextList = temp->nextList;
        temp->nextList = newNode;
        list->List = newNode;
    }
}
 
cs

출력화면


메인 문에서 연결형 리스트를 미리 생성해 놓고 검색하고자 하는 문자열을 입력받아 탐색알고리즘을 통해 탐색   결과를 출력 하는 프로그램




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include<stdio.h>
#include<string.h>
 
//리스트 구조체 선언
struct List {
    char strData[11];
    struct List *nextList;
};
 
//탐색 알고리즘 함수 선언
struct List* searchNode(struct List *list, char *x);
 
void main() {
    //연결형 리스트 생성
    struct List appleList = { "apple",NULL };
    struct List BananaList = { "Banana", &appleList };
    struct List melonList = { "Melon", &BananaList };
    struct List piList = { "Rassbary", &melonList };
    struct List nameList = { "신홍기", &piList };
    struct List *search;
 
    //검색할 이름을 저장할 변수 선언과 값 받기
    char strTemp[11];
    
    printf_s("검색할 것을 입력하세요 : ");
    scanf("%s", strTemp);
    //search에 searchNode함수를 실행한 결과를 저장
    search = searchNode(&nameList, strTemp);
 
    //탐색알고리즘을 통해 찾은경우와 못찾은 경우를 출력
    if (search != NULL)
    {
        printf_s("%s를 리스트에서 찾았습니다.\n", strTemp);
    }
    else {
        printf_s("%s를 리스트에서 찾지 못했습니다.\n", strTemp);
    }
    return;
}
 
//리스트 L에서 x 노드 탐색 알고리즘
struct List* searchNode(struct List *list, char *x) {
    //시작주소를 temp에 저장;
    struct List *temp = list;
    //마지막 노드일 때 까지 반복문 돌리는 것
    while (temp != NULL)
    {
        //temp의 현재 노드에 저장된 strData와 검색하려는 x노드가 같은지 비교
        if (!strcmp(temp->strData, x)) {
            //맞을경우 temp반환
            return temp;
        }
        //다음 노드로 이동
        temp = temp -> nextList;
    }
    //찾지 못하여 NULL값 반환
    return temp;
}
 
cs


C언어 정리

함수 특정한 작업을 수행하는 독립적인 부분

 

  • 함수 사용시 코드 중복을 막을 수 있다.
  • 재사용성이 있다.
  • 모듈로 나누어 개발 과정이 쉬워진다.

 

함수의 종류

 

  • 사용자 정의 함수
  • 라이브러리 함수 컴파일러 제공 라이브러리

 

함수 구현

반환형 함수이름(매개변수 1, ... , 매개변수 n) <- 함수 헤더

함수시작{

함수 몸체

함수 종료}

함수 호출 함수를 호출하여 사용하는 것


함수 원형 컴파일러에게 함수에 대하여 미리 알리는 것(함수 호출 부분 위에 있으면 안써도 되지만 그런 경우가 적음)

가변 매개 변수 매개 변수의 개수가 가변적으로 변할 수 있는 기능

ex) int sum(int sum, ...)

순환 (재귀 호출) : 알고리즘이나 함수가 수행 도중에 자기 자신을 다시 호출하여 문제를 해결하는 기법자기자신을 재호출하는 것으로 순환을 멈추는 부분이 있어야 함

 

함수와 변수

변수의 속성 이름,타입,크기,+범위,생존시간,연결

범위 변수가 사용 가능한 범위가시성

생존 시간:메모리에 존재하는 시간

연결 다른 영역에 있는 변수와의 연결 상태


변수의 범위

전역 변수 함수의 외부에서 정의프로그램이 끝나면 소멸초기화 안해도 0. 모든 함수에서 사용하는 공통적인 데이터를 전역변수로 선언우선순위 지역변수 전역변수

지역 변수 함수의 내부블록 안에서 정의선언된 블록이 끝나면 소멸

 

생존 기간

자동 할당 블록에 들어갈 때 생성블록에서 나올 소멸

정적 할당 프로그램 실행 시간 동안 계속 유지변수가 선언된 위치저장 유형 지정자로 생존기간 결정

auto : 자동할당과 동일

static : 정적변수로 블록이 끝나도 유지됨

register : CPU안의 레지스터에 변수가 저장됨

extern : 외부 연결시 사용

연결 다른 범위에 속하는 변수들을 서로 연결하는 것

외부 연결 전역변수에 extern을 붙여 다른 파일에서도 접근 가능하게 함

내부 연결 함수앞에 static 붙여 외부에서 접근 못하게 함

무연결

 

배열

배열 동일한 타입의 데이터가 여러 개 저장되어 있는 데이터 저장 장소

배열은 변수에 인덱스를 통해 접근함반복문과 활용하면 간편하게 처리됨원소 일일이 복사,비교 해야됨

ex)int grade[10]; -> 정수형 원소 10개를 저장하는 grade 배열 생성(인덱스는 0부터)

초기화 : int grade[5]={10,20,30}; -> [0]:10 [1]:20 [2]:30 [3],[4]:0 저장됨배열크기 지정안하면 초기화된 개수만큼만 배열 생성

배열 원소 개수 구하기 : sizeof(배열이름) / sizeof(배열이름[0])

 

포인터

포인터 

 

  • 변수의 주소를 가지고 있는 변수
  • 변수의 크기에 따라서 차지하는 메모리 공간이 달라진다
  • 명시적으로 포인터의 타입을 변경할 수 있음

 

포인터 변수 선언 : *변수 ex) int *p;

변수의 주소를 계산하는 연산자 : & ex) 변수 i의 주소 : &i

포인터와 변수의 연결 : p = &i;

간접 참조 연산자 *: 포인터가 가리키는 값을 가져오는 연산자 ex) *p -> p가 가리키는 변수의 값 반환


포인터 연산

증가 연산 포인터변수에 +1을 할 경우 타입에 따라 주소 늘어나는 양이 다름

ex) char 타입 +1-> 1byte 증가, int타입 +1 -> 4byte증가

*p++ : p가 가리키는 위치에서 값을 가져온 후에 p를 증가

(*p)++ : p가 가리키는 위치의 값을 가져온 후 처리가 끝나면 값을 증가

*++p : p를 증가시킨 후에 p가 가리키는 값을 가져옴

++*p : p가 가리키는 위치에서 값을 가져온 후 처리 전에 그 값을 증가


포인터와 배열

포인터는 배열처럼 사용이 가능(인덱스 표기법을 포인터로도 가능)

ex) int a[] = {10,20,30,40,50}; *a->10 *(a+1) -> 20 a->a[0]의 주소 (a+1)->a[1]의 주소

int *p=a; p[0]=10;

 

함수 호출시 인수 전달 방법

값에 의한 호출(call by value) : 변수를 매개변수로 사용할 때 값을 복사해서 넘겨줌

참조에 의한 호출(call by reference) : 해당 변수의 주소값을 넘겨줌(scanf도 주소값을 넘김). 배열 매개 변수는 인덱스 없이 적으면 됨


포인터 사용 주의점

 

  • 초기화가 안된 포인터를 사용하면 안됨 ex) int *p; *p=100;
  • 포인터가 아무것도 가리키고 있지 않는 경우에는 NULL로 초기화
  • NULL 포인터를 가지고 간접 참조할 경우 하드웨어로 감지 가능
  • 포인터의 유효성 여부 판단이 쉬움
  • 포인터의 타입과 변수의 타입 일치해야함
  • 함수가 종료되더라도 남아있는 변수의 주소를 반환해야함 (함수 내에 있는 지역 변수의 주소를 반환하면 함수종료시 사라져서 오류가 뜸)

 

포인터 사용의 장점

 

  • 연결 리스트나 이진 트리 등의 향상된 자료 구조를 만들 수 있음
  • 참조에 의한 호출이 가능함
  • 동적 메모리 할당

 

 

이중 포인터

이중 포인터 포인터를 가리키는 포인터

**p -> *p : p가 가리키는 위치의 내용 **p : *p가 가리키는 위치의 내용

포인터 배열 포인터를 모아서 배열로 만든 것

int *ap[10]; -> [] 연산자가 *연산자보다 우선 순위가 높아 ap는 배열이 됨 -> int *(포인터)들의 배열로 선언

ex) int *ap[10]={&a,&b,&c,&d,&e};

 2차원 배열로 문자열 저장

 문자형 포인터 배열

 char fruits[4][10]={“apple”,“blueberry”};

char *fruits[]={“apple”,“blueberry”}; 

2차원 배열 사용시 낭비되는 공간 발생 

그런거 없다 

 

배열 포인터 배열을 가리키는 포인터

int (*pa)[10]; -> 먼저 포인터가 됨 -> int [10]을 가리키는 포인터가 됨

ex) int a[5]={1,2,3,4,5}; int (*pa)[5]; pa=a; (*pa)[0] (*pa)[1] (*pa)[2] 로 사용

2차원 배열과 포인터 연산

2차원 배열로 생성해도 1->2->3행 순으로 메모리에 저장 포인터를 이용하여 2차원 배열을 탐색 가능


함수 포인터

함수 포인터 함수를 가리키는 포인터함수도 메모리에 존재하기 때문에 함수 주소를 가져올 수 있다.

int (*pf)(int,int); -> pf가 먼저 포인터가됨 -> int 함수(int,int) 함수를 가리키는 포인터가 됨

함수 포인터 배열 같은 반환타입매개변수를 사용하는 함수를 여러개 저장하는 배열

int (*pf[5])(int,int);

const 포인터

const를 붙이는 위치에 따라서 의미가 달라짐

const char *p : p가 가리키는 내용이 변경되지 않음을 나타냄

char *const p : 포인터 p가 변경되지 않음을 나타냄

 

구조체

구조체 다른 타입의 집합

구조체 선언 형식

struct 구조체이름{

자료형 멤버1;

자료형 멤버2;

...

};

구조체를 선언할 때 구조체포인터를 멤버로 가질 수 있다.


구조체 변수 선언

변수 : struct 구조체이름 변수명;

배열 : struct 구조체이름 변수[크기];

선언과 동시에 초기화 가능

struct student s1 = {24, “Kim”, 4.3};

struct student s2[3]={{1,“Park”,172.8},{2,“Kim”,179.2},{3,“Lee”,180.3}};

구조체 멤버를 참조하려면 .연산자를 사용함

ex) s1.number = 26; s1.grade=4.3;

같은 구조체 변수끼리 대입은 가능하나 비교가 불가능


구조체와 포인터

struct 구조체이름 *p; p=&s1;

포인터를 사용시 ‘.’연산자, ‘->’연산자 사용 가능

ex)동일한 기능 (*p).number (*p).name, p->number p->name

 

구조체와 함수

구조체를 함수의 인수로 전달할 경우 구조체의 복사본이 함수로 전달되어 메모리 소비가 커짐

구조체의 포인터를 함수의 인수로 전달할 경우 원본이 훼손될 수있으나 시공간 절약가능

int equal(struct 구조체이름 const *p1) : const를 추가함으로써 포인터를 통한 구조체의 변경을 막는 것

함수에서 구조체 반환시 구조체의 복사본을 반환

공용체 같은 메모리 영역을 여러 개의 변수가 공유공용체를 선언하고 사용하는 방법은 구조체와 비슷

공용체 선언 형식

union 공용체 명{

char c;

int i; //i와 c는 같은 공간을 활용

};




출력에 평균값들 잘못되어 있음.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include<stdio.h>
 
main(){
 int a[5][3= { { 301011 }, { 409032 }, { 706556 }, { 704332 }, { 801089 } };
 int sum[5= { 0, };
 int ssum[3= { 0, };
 int i, j,n=5,m=3;
 
 
 printf("# 각 시험의 최대, 최저, 평균 점수\n");
 for (i = 0; i < m; i++){
  int smax = a[0][i], smin = a[0][i];
  printf("시험 %d ",i+1);
  for (j = 0; j < n; j++){
   if (a[j][i]>smax)smax = a[j][i];
   if (a[j][i]<smin)smin = a[j][i];
   ssum[i] += a[j][i];
  }
  printf("최대점수=%d\n", smax);
  printf("       최저점수=%d\n", smin);
  printf("       평균점수=%.2lf\n", (double)ssum[i] / n);
 }
 
 
 printf("\n# 각 학생의 최고, 최하, 평균점수\n");
 for (i = 0; i <n ; i++){
  int smax = a[i][0], smin = a[i][0];
  printf("학생 %d ", i + 1);
  for (j = 0; j < m; j++){
   if (a[i][j]>smax)smax = a[i][j];
   if (a[i][j]<smin)smin = a[i][j];
   sum[i] += a[i][j];
  }
  printf("최대점수=%d\n", smax);
  printf("       최저점수=%d\n", smin);
  printf("       평균점수=%.2lf\n", sum[i] / 5.0);
 }
 
 
 //정렬
 int t,k;
 for (i = 0; i < n-1; i++){
  for (j = i+1; j < n; j++){
   if (sum[i] > sum[j]){ t = sum[i]; sum[i] = sum[j]; sum[j] = t; }
  }
 }
 for (k = 0; k < m; k++){
  for (i = 0; i < n-1; i++){
   for (j = i + 1; j < n; j++){
    if (a[i][k]>a[j][k]){ t = a[i][k]; a[i][k] = a[j][k]; a[j][k] = t; }
   }
  }
 }
 
 
 printf("\n# 각 시험마다 산술 평균값, 중간값, 모드값(최빈값)\n");
 //최빈값 찾기
 for (k = 0; k < m; k++){
  printf("시험 %d ", k + 1);
  int cnt = 1, q = a[0][k], max = 1, ss = a[0][k];
  for (i = 1; i < n; i++){
   if (a[i][k] != q){
    if (max < cnt){ max = cnt; ss = q; }
    cnt = 1;
    q = a[i][k];
   }
   else{ cnt++; }
  }
  printf("산술평균=%.2lf\n", (double)ssum[k] / n);
  printf("       중앙값=%d\n", a[n/2][k]);
  printf("       최빈값=%d\n", ss);
 }
 
 printf("\n# 각 학생별로 총점을 구하고 이 총점을 기준으로 정렬\n");
 for (i = 0; i < 5; i++)
  printf("%d\n", sum[i]);
 
cs


+ Recent posts