2019년 4월 13일 토요일

# JPEG, PNG, WEBP 이미지 압축 포멧관련 테스트.

흔히 들어본 이미지 압축 포멧은 다음과 같다.

JPEG
Joint Photograph Experts Group의 약자로, 그림 파일 형식의 하나.

정지 화상을 위해서 만들어진 손실 압축, 무손실 압축(JPEG 9.1부터) 방법 표준이다. 이 표준은 ISO와 ITU-T에서 제정하였다.(ISO 10918-1, 한국어 설명)

JPEG를 사용하는 파일 형식들도 보통 JPEG 이미지라 불리며, .jpg, .jpeg, .jpe 등의 확장자를 사용한다.

JPEG 표준은 이미지가 어떻게 연속된 바이트로 바뀌는 지만을 규정한다. 독립 JPEG 그룹(Independent JPEG Group; IJG)에서 만든 JPEG의 확장인 JFIF(JPEG File Interchange Format)는 JPEG 스트림을 저장과 전송에 적합한 형태로 담는 이미지 파일 형식이다. 디지털 카메라의 사진 저장 방식으로는 다른 확장인 EXIF JPEG 형식이 더 자주 사용된다. 일반적으로 JPEG 파일이라고 할 때는 JFIF 형식이거나 EXIF JPEG 형식을 가리키지만, JNG와 같은 JPEG 기반의 다른 파일 형식도 있다.

-- 나무위키 中 ( link : https://namu.wiki/w/JPEG )

PNG
Portable Network Graphics의 약자로 그림 파일형식 중 하나이다.

PNG는 무손실 압축 포맷을 채택하였으며, 256색에 한정되던 GIF의 한계를 극복하여 32비트 트루컬러(알파채널, RGB에 각 8비트 지원)를 표현할 수 있게 되었다. 다만 네이티브 PNG는 GIF에서 제공하던 애니메이션 기능은 제공하지 못한다.

-- 나무위키 中 ( link : https://namu.wiki/w/PNG )

...

구글에서 개발한 이미지 포멧인 WEBP의 경우 아래와 같다.

WebP is a modern image format that provides superior lossless andlossy compression for images on the web. Using WebP, webmasters and webdevelopers can create smaller, richer images that make the web faster.
WebP lossless images are 26% smaller in size compared to PNGs. WebPlossy images are 25-34% smaller than comparable JPEG images at equivalentSSIM quality index.
Lossless WebP supports transparency (also known as alpha channel) at acost of just 22% additional bytes. For cases when lossy RGB compressionis acceptable, lossy WebP also supports transparency, typically providing3× smaller file sizes compared to PNG.

(link : https://developers.google.com/speed/webp/ )

무손실 PNG에 비해 26% 크기가 작으며, 손실 JPEG에 비해 25~34%가 작다!! 라는게 핵심이다.
웹상에서는 수많은 이미지가 있고 이는 결국 네트워크 트래픽으로 이어진다. 결국 비용이 많이 발생한다. 따라서 WEBP 포멧을
사용하면 이런저런 비용을 줄일 수 있고, 사용자 측면에서도 웹 페이지가 빠르게 보여지니 좋은거다.. 라는 거겠지.

일단 간단하게 테스트를 해보았다.
평소에 루리웹 월페이퍼 게시판에서 이미지를 다운하는데 이를 이용했다.
( ※ JPEG 손실, PNG 무손실, WEBP는 손실 )


다운받은 해당 게시글에 포함된 이미지는 82개이고 각기 다른 포멧으로 다운받아 압축했다.

JPEG는 약100mb / PNG는 180mb / WEBP는 52mb 정도가 나왔다.

이번에는 이미지 파일 1개로만 비교해보면 위 그림과 같다.

확실히 WEBP의 파일사이즈가 작다.

# 안드로이드(Android OS) 내장메모리(internal memory) 복구 가이드라인 ( windows 기준 )

테스트 환경 : Windows 10 ( 64bit )

전체적인 가이드는 다음과 같다.

1. 복구하고자 하는 스마트폰은 반드시 루팅한다. ( Super su )

2. ADB를 이용, 안드로이드에 마운트된 user data 또는 내장메모리 그 자체를 이미지로 만들어서 로컬 컴퓨터에 저장.
  (ADB 설치방법은 구글링으로 검색하자.)

3. 2번에서 만들어진 이미지를 이용해 vhd 파일로 바꾼다.

4. vhd파일을 가상디스크로 읽어들여 해당 디스크에 대해 복구프로그램을 돌려준다.



루팅의 경우에는 스마트폰마다 방법이 다르므로 구글링을 통해 찾는게 수월하다. 그러면, 2번~4번까지의 방법을 알아보자.

2번의 경우
 (0) adb 및 netcat 이용시에는 cmd 프로그램을 활용한다. cygwin에서 제공하는 기본 terminal을 이용하지 않는 이유는
     netcat을 통해 파일 전송시에 그 속도가 현저하게 뒤떨어진다.
 (1) 스마트폰 연결 후, cmd창을 open
 (2) adb start-server
 (3) adb forward tcp:9999 tcp:9999 ( port번호는 원하는걸로 )
 (4) adb su -c /system/xbin/busybox nc -l -p 9999 -e /system/xbin/busybox dd if=/dev/block/mmcblk0
     - 내가 쓰는 스마트폰 기준으로 내장메모리는 mmcblk0 이란 이름으로 mount되어 있다.
 (5) 스마트폰내에 내장메모리를 로컬 컴퓨터로 전송하는 방법은 netcat, cygwin을 이용한다.
     cygwin을 설치 후( 설치 시 dependency 목록중에 progress var(=pv) util, debug를 추가)
     bin 폴더에 netcat 파일을 넣어준다. 그 다음, 데이터 전송 유틸러리인 netcat를 이용해 로컬 컴퓨터로
     전송한다.
     ex) nc 127.0.0.1 9999 | pv -i 0.5 > testDumpfile.raw
     p.s. netcat 명령어는 구글링으로 검색해서 알아보자!!



  ( 위 그림과 같이 파일이 전송되어 진다. )

2번 순서가 끝나면, 바로 VHD tool을 이용해 raw 파일을 가상화 디스크 파일로 변경해야 한다.
( 변경 후, 확장자명을 .vhd로 변경해주자. )
vhdtool 에 대한 이용법은 구글링을 통해 찾기 쉽다.
VhdTool.exe /create <FileName> <Size> [/quiet]VhdTool.exe /convert <FileName> [/quiet]VhdTool.exe /extend <FileName> <NewSize> [/quiet]VhdTool.exe /repair <BaseVhdFileName> <FirstSnapshotAVhdFileName> [/quiet]

위와 같이 간단한 명령어 체계를 가지고 있다.

vhd 파일로 변경이 끝나면, 이제 widnwos 컴퓨터 관리 앱을 통해 해당 vhd파일을 등록시켜준다. 이 또한 간단하게 검색을..

여기까지 완료되었다면, 복구 프로그램을 구해서 해당 디스크를 복구시켜보자. -끝-

# 3n+1 문제 ( Longest Collatz sequence )

#include <iostream>
#include <unordered_map>
#include <time.h>
using namespace std;

#define ARR_SIZE 1000000
#define MAX_NUMBER 1000000

unsigned int CalcChains(unsigned int _num, unsigned int* _chains);
void main() {

 clock_t startTime = 0;
 clock_t endTime = 0;

 unsigned int* chains = new unsigned int[ARR_SIZE];
 for (int i = 0; i < ARR_SIZE; i++) chains[i] = 0;

 unsigned maxChain = 0;
 unsigned maxNumber = 0;
 startTime = clock();
 for (unsigned int num = 1; num <= MAX_NUMBER; ++num) {
  unsigned int chain = CalcChains(num, chains);
  chains[num] = chain;
  if (chain > maxChain) {
   maxChain = chain;
   maxNumber = num;
  }
 }
 endTime = clock();
 cout << "max Chain is : " << maxChain << " and number is : " << maxNumber << endl;
 cout << "execution sec is : " << (double)(endTime - startTime) / CLK_TCK << endl;
 system("pause");
}

unsigned int CalcChains(unsigned int _num, unsigned int* _chainOfNumber) {
 unsigned int chains = 0;
 while (_num >= 1) {
  if (_num == 1) return ++chains;
  if ((_num < ARR_SIZE) && (_chainOfNumber[_num] > 0)) {
   chains += _chainOfNumber[_num];
   break;
  }
  if (_num % 2 == 0) { _num >>= 1; }
  else { _num = (_num * 3) + 1; }
  chains++;
 }
 return chains;
}

# 조합( nCk :: n개중 k개를 이용한 ) 구하기

 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
#include <iostream>
#include <vector>

using namespace std;

vector<int> numbers;
vector<int> combination;
int N, K; // 총 N 개중 K를 골라 조합을 만든다.

void input()
{
    cin >> N >> K;
    numbers.resize(N);
    for (int i = 0; i < N; ++i)
        cin >> numbers[i];
}

void PrintCombi(const vector<int>& v) {
    
    for (int i = 0; i < v.size(); ++i)
    {
        cout << v[i] << " ";
    }
    cout <<endl;
}

void Combi(int offset, int k) {
    if (k == 0) {
        PrintCombi(combination);
        return;
    }
    for (int i = offset; i <= numbers.size() - k; ++i) {
        combination.push_back(numbers[i]);
        Combi(i + 1, k - 1);
        combination.pop_back();
    }
}

int main() {
   
    input();
    Combi(0, K);

    return 0;
} 

# 간단한 사칙연산 계산기 ( 학부생 시절 흑역사의 흔적..)

  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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
#include <iostream>
#include <string>
#include <stack>
using namespace std;


// 연산자 우선순위
// 1. )
// 2. */
// 3. +-
// 4. ( 시작괄호의 경우, 가장낮은 우선순위지만 대소상관없이 무조건 스택에 삽입. (예외적)
enum OPERAND { PLUS=1, MINUS=1, PRODUCT=2, DIVIDE=2, LEFT_BRAKET=0, RIGHT_BRAKET=3};

/*-----메인 함수들-----*/
void NumFormulaChange(string& s);
void ChangePostFix(string& inputStr, string& outputStr, stack<string>& opStack);
int Calculator(string& outputStr, stack<int> calcStack);
/*-----부가적인 함수들-----*/
string CharToString(char c);
int GetOperand(char s);
int GetOperand(string s);
int Calc(string& inputStr, string& outputStr, stack<string> opStack, stack<int> calcStack);

void main()
{
    
    string inputStr;
    string outputStr;
    stack<string> opStack;
    stack<int> calcStack;
    int answer = 0;

    cout << "수식을 입력해주세요." << endl;
    cin >> inputStr;

    answer = Calc(inputStr, outputStr, opStack, calcStack);
    
    cout<< answer <<endl;
    
    
}
// 입력받은 수식으로 계산을 시작합니다.
int Calc(string& inputStr, string& outputStr, stack<string> opStack, stack<int> calcStack)
{
    NumFormulaChange(inputStr);
    ChangePostFix(inputStr, outputStr, opStack);

    return Calculator(outputStr, calcStack);
}

// 단일문자형을 스트링으로 변환.
string CharToString(char c)
{
    string str(1, c);
    return str;
}
// char to Operand
int GetOperand(char s)
{
    int op = s;
    switch (op)
    {
    case 40:
        op = LEFT_BRAKET;
        break;
    case 41:
        op = RIGHT_BRAKET;
        break;
    case 42:
        op = PRODUCT;
        break;
    case 43:
        op = PLUS;
        break;
    case 45:
        op = MINUS;
        break;
    case 47:
        op = DIVIDE;
        break;
    }
    return op;
}
//string to Operand
int GetOperand(string s)
{
    int op = s[0];
    switch (op)
    {
    case 40:
        op = LEFT_BRAKET;
        break;
    case 41:
        op = RIGHT_BRAKET;
        break;
    case 42:
        op = PRODUCT;
        break;
    case 43:
        op = PLUS;
        break;
    case 45:
        op = MINUS;
        break;
    case 47:
        op = DIVIDE;
        break;
    }
    return op;
}
// 입력받은 수식을 계산하여 int형 값으로 돌려줍니다.
int Calculator(string& outputStr, stack<int> calcStack)
{
    int tot = 0;
    int idx = 0;
    while (outputStr[idx] != '\0')
    {
        if ((outputStr[idx] == '+') ||
            (outputStr[idx] == '-') ||
            (outputStr[idx] == '*') ||
            (outputStr[idx] == '/')
            )
        {
            switch (outputStr[idx])
            {
            case 42: // * 곱하기.
                if (calcStack.size() >= 2)
                {
                    int num2 = calcStack.top();
                    calcStack.pop();
                    int num1 = calcStack.top();
                    calcStack.pop();

                    calcStack.push(num1 * num2);
                }
                break;
            case 43: // + 더하기.
                if (calcStack.size() >= 2)
                {
                    int num2 = calcStack.top();
                    calcStack.pop();
                    int num1 = calcStack.top();
                    calcStack.pop();

                    calcStack.push(num1 + num2);
                }
                break;
            case 45: // - 빼기.
                if (calcStack.size() >= 2)
                {
                    int num2 = calcStack.top();
                    calcStack.pop();
                    int num1 = calcStack.top();
                    calcStack.pop();

                    calcStack.push(num1 - num2);
                }
                break;
            case 47: // / 나누기.
                if (calcStack.size() >= 2)
                {
                    int num2 = calcStack.top();
                    calcStack.pop();
                    int num1 = calcStack.top();
                    calcStack.pop();

                    calcStack.push(num1 / num2);
                }
                break;
            }
            idx++;
        }
        else
        {
            int cnt = idx;
            while (outputStr[cnt] != '.')
            {
                cnt++;
            }
            string tmp = outputStr.substr(idx, cnt - idx);
            calcStack.push(stoi(tmp));
            idx += cnt - idx + 1;
        }
    }

    // 수식 계산이 완료 되었다.
    tot = calcStack.top();
    calcStack.pop();

    return tot;
}

//입력받은 수식을 후위표현식으로 바꾼다.
void ChangePostFix(string& inputStr, string& outputStr, stack<string>& opStack)
{
    int idx = 0;
    while (inputStr[idx] != '\0')
    {   
        //현재 inputStr 에서 읽어들인 연산자 (※ 연산자 비교시에만 쓰입니다. )
        int curOperand = 0;
        
        // 연산자 또는 괄호인 경우. (※ string 에서 첨자로 데이터접근시, char type으로 된다.)
        if ((inputStr[idx] == '+') ||
            (inputStr[idx] == '-') ||
            (inputStr[idx] == '*') ||
            (inputStr[idx] == '/') ||
            (inputStr[idx] == '(') ||
            (inputStr[idx] == ')'))
        {
            curOperand = GetOperand(inputStr[idx]);
                
            if (curOperand == LEFT_BRAKET) 
            {
                //예외적으로 '(' 연산자는, 스택에 바로 push() 한다.
                opStack.push(CharToString(inputStr[idx]));
            }
            else if (curOperand == RIGHT_BRAKET)
            {
                // 닫는 중괄호')'를 발견하면, 
                // 현재 스택에서 시작 괄호'('를 만날때까지 pop() 한다.
                // 시작, 닫는 괄호는 전부 버리고, 다른 연산자의 경우 outputStr에 저장.
                while ((opStack.size() > 0) && (opStack.top() != CharToString('(')))
                {
                    // +, -, *, / 연산자의 경우 outputStr에 저장.
                    outputStr += opStack.top();
                    opStack.pop();
                }
                // while 종료후, 닫는괄호')' 도 버린다.
                if (opStack.size() > 0)
                    opStack.pop();
            }
            else if (opStack.empty())
            {
                opStack.push(CharToString(inputStr[idx]));
            }
            else if (curOperand > GetOperand(opStack.top()))
            {
                opStack.push(CharToString(inputStr[idx]));
            }
            else if (curOperand <= GetOperand(opStack.top()))
            {
                do
                {
                    outputStr += opStack.top();
                    opStack.pop();
                    if (opStack.empty())
                        break;
                } while ((curOperand <= GetOperand(opStack.top())) != true);
                
                opStack.push(CharToString(inputStr[idx]));
            }
            idx++;    
        }
        else // 숫자인 경우, outputStr에 저장.
        {
            /*
             숫자의 경우, 자릿수별로 토큰을 나누어야한다.
             현재 첨자에서 숫자가 발견됬으니, 연산자를 만나기전까지 계속 읽어들여
             증가한 cnt 값을 idx 에서 빼주면, 숫자의 자릿수 크기를 구할 수 있다.
             이 값으로 subString 하여 outputStr에 저장한다. 그리고 숫자별 구분점 '.' 을
             추가해준다.
            */
            int cnt = idx;
            while ((inputStr[cnt] != '+') &&
                (inputStr[cnt] != '-') &&
                (inputStr[cnt] != '*') &&
                (inputStr[cnt] != '/') &&
                (inputStr[cnt] != '(') &&
                (inputStr[cnt] != ')') &&
                inputStr[cnt] != '\0')
            {
                cnt++;
            }
            outputStr += inputStr.substr(idx, cnt - idx);
            outputStr += CharToString('.');
            idx += cnt - idx;
        }
        
    }

    //모든 토큰화가 끝나고나서 스택에 남아있는 연산자를 전부 넣는다.
    while (opStack.size() > 0)
    {
        outputStr += opStack.top();
        opStack.pop();
    }
}

//입력받은 수식에서 음수 -N 꼴을 (0-N) 꼴로 바꾼다.
void NumFormulaChange(string& s)
{
    int idx = 0;
    while (s[idx] != '\0')
    {
        // 입력받은 string의 첫 원소가 '-' 인가?
        if (s[0] == '-')
        {
            s.insert(0, "(0");
            // 삽입 후, 내부 idx 에 밀려난 만큼 더해준다.
            int j = 0 + 4;
            while ((s[j] != '\0') &&
                (s[j] != '*') &&
                (s[j] != '/') &&
                (s[j] != '+') &&
                (s[j] != '-') &&
                (s[j] != '(') &&
                (s[j] != ')'))
            { 
                j++;
            }
            s.insert(j, ")"); // 종료괄호를 삽입.
        }
        else if ((s[idx] == '*') ||
            (s[idx] == '/') ||
            (s[idx] == '+') ||
            (s[idx] == '('))
        {
            // 연산자 발견후, 다음 위치에 '-'가 발견되면 -N 의 음수를 (0-N) 형태로 바꾸어준다.
            if (s[idx + 1] == '-')
            {   // minus 가 발견된 지점에 "(0" 삽입.
                s.insert(idx + 1, "(0");
                // 삽입 후, 내부 idx 에 밀려난 만큼 더해준다.
                int j = idx + 4;
                while ((s[j] != '\0') &&
                    (s[j] != '*') &&
                    (s[j] != '/') &&
                    (s[j] != '+') &&
                    (s[j] != '-') &&
                    (s[j] != '(') &&
                    (s[j] != ')'))
                { // 위에 언급된 연산자중에 하나라도 일치하는게 있다면 break;
                    j++;
                }
                s.insert(j, ")"); // 종료괄호를 삽입.
            }
        }
        idx++;
    }
}

# 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
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
#pragma once

//================================
// 완전 이진 트리 
//
// 배열을 이용한 구현
//================================

/*NULL 의 경우 0으로 정의 되있는경우가 있으므로, 다른이름으로 정의해준다.. (중복되면 안되므로)*/
#define MAXNODE 100
#define nodeNULL -1 //빈노드를 의미
#include <iostream>



template<typename T>
class cBinaryTreeByArray
{

public:

 cBinaryTreeByArray();
 void insert(T num);
 void Traverse(int type);  // type -> 순회방법 
 typedef struct completeBinaryTreeByArray
 {
  T Item;
  int leftChild; // memorize index num
  int rightChild;// memorize index num

 }completeBinaryTreeByArray;

private:
 /*Insert*/
 void insertIn(T num, int subRoot);
 /* Traverse */ // 출력을 목적으로 작성된 순회메소드.
 void preOrder(int subRoot);
 void inOrder(int subRoot);
 void postOrder(int subRoot);
 completeBinaryTreeByArray completeTree[MAXNODE];
 int curNodeNum; //현재 노드 갯수
 int root; // 최상위 루트

};

template<typename T>
cBinaryTreeByArray<T>::cBinaryTreeByArray()
{
 // 최상위 루트
 root = 0;
 // 현재 노드 갯수 초기화. 현재 노드 갯수는 배열 인덱스 범위와 1의 차이
 curNodeNum = 0;

 // 구조체 배열 초기화.
 for (int i = 0; i < MAXNODE; i++)
 {
  completeTree[i].Item = 0;
  completeTree[i].leftChild = nodeNULL;
  completeTree[i].rightChild = nodeNULL;

 }
}
template<typename T>
void cBinaryTreeByArray<T>::insert(T num)
{
 insertIn(num, root);
}
template<typename T>
void cBinaryTreeByArray<T>::insertIn(T num, int subRoot)
{
 if (curNodeNum == 0) // 최상위 루트가 존재하지 않는다면.
 {
  completeTree[curNodeNum].Item = num;
  completeTree[2 * curNodeNum + 1].leftChild = nodeNULL; // 2k+2
  completeTree[2 * curNodeNum + 2].rightChild = nodeNULL; // 2k+2
  curNodeNum++;

 }
 else if (completeTree[subRoot].leftChild == nodeNULL) // 왼쪽이 비었다.
 {
  completeTree[curNodeNum].Item = num;
  completeTree[2 * curNodeNum + 1].leftChild = nodeNULL;
  completeTree[2 * curNodeNum + 2].rightChild = nodeNULL;
  // 새 노드생성후 부모 노드의 왼쪽에 붙여준다.
  completeTree[subRoot].leftChild = curNodeNum;
  curNodeNum++;

 }
 else if (completeTree[subRoot].rightChild == nodeNULL) // 오른쪽이 비었다.
 {
  completeTree[curNodeNum].Item = num;
  completeTree[2 * curNodeNum + 1].leftChild = nodeNULL;
  completeTree[2 * curNodeNum + 2].rightChild = nodeNULL;
  // 새 노드생성후 부모 노드의 왼쪽에 붙여준다.
  completeTree[subRoot].rightChild = curNodeNum;
  curNodeNum++;
 }
 else
  insertIn(num, ++subRoot); // root 넘버는 1씩 증가하므로
}
template<typename T>
void cBinaryTreeByArray<T>::Traverse(int type)
{
 switch (type)
 {
 case 0:
  preOrder(root);
  break;
 case 1:
  inOrder(root);
  break;
 case 2:
  postOrder(root);
  break;
 default:
  break;
 }
}
template<typename T>
void cBinaryTreeByArray<T>::preOrder(int subRoot)
{

 if (subRoot != nodeNULL) // baseCase
 {
  std::cout << completeTree[subRoot].Item << std::endl;
  preOrder(completeTree[subRoot].leftChild);
  preOrder(completeTree[subRoot].rightChild);
 }
}
template<typename T>
void cBinaryTreeByArray<T>::inOrder(int subRoot)
{

 if (subRoot != nodeNULL)
 {
  inOrder(completeTree[subRoot].leftChild);
  std::cout << completeTree[subRoot].Item << std::endl;
  inOrder(completeTree[subRoot].rightChild);
 }
}
template<typename T>
void cBinaryTreeByArray<T>::postOrder(int subRoot)
{

 if (subRoot != nodeNULL)
 {
  postOrder(completeTree[subRoot].leftChild);
  postOrder(completeTree[subRoot].rightChild);
  std::cout << completeTree[subRoot].Item << std::endl;
 }
}

# 퀵소트 및 선택정렬 소스코드

아래는 위키백과 에서 소스 긁어왔고, 다시한번 보면서 되새겨보자. http://ko.wikipedia.org/wiki/%ED%80%B5_%EC%A0%95%EB%A0%AC http://ko.wikipedia.org/wiki/%EC%84%A0%ED%83%9D_%EC%A0%95%EB%A0%AC
 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
void quickSort(int numbers[], int array_size)
 {
   q_sort(numbers, 0, array_size - 1);
 }
 
 void q_sort(int numbers[], int left, int right)
 {
   if(left == right) return;
   int pivot, l_hold, r_hold;
   l_hold = left;
   r_hold = right;
   pivot = numbers[left];
 
   while (left < right)
   {
     while ((numbers[right] >= pivot) && (left < right))
       right--;
 
     if (left != right)
     {
       numbers[left] = numbers[right];
       left++;
     }
 
     while ((numbers[left] <= pivot) && (left < right))
       left++;
 
     if (left != right)
     {
       numbers[right] = numbers[left];
       right--;
     }
   }
 
   numbers[left] = pivot;
   pivot = left;
   left = l_hold;
   right = r_hold;
 
   if (left < pivot)
     q_sort(numbers, left, pivot-1);
   if (right > pivot)
     q_sort(numbers, pivot+1, right);
 }
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
void selectionSort(int *list, const int n)
{
    int i, j, indexMin, temp;
 
    for (i = 0; i < n - 1; i++)
    {
        indexMin = i;
        for (j = i + 1; j < n; j++)
        {
            if (list[j] < list[indexMin])
            {
                indexMin = j;
            }
        }
        temp = list[indexMin];
        list[indexMin] = list[i];
        list[i] = temp;
    }
}
그리고 이거는 직접 만들어본 quickSort
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
void QuickSort(int arr[], int up, int down) {
 int pivot = arr[(up + down) / 2];
 int upPtr = up;
 int downPtr = down;

 while (upPtr <= downPtr) {
  while (arr[upPtr] < pivot) upPtr++;
  while (arr[downPtr] > pivot) downPtr--;
  if (upPtr <= downPtr) {
   int tmp = arr[upPtr];
   arr[upPtr] = arr[downPtr];
   arr[downPtr] = tmp;
   upPtr++;
   downPtr--;
  }
 }
 if (up < downPtr) QuickSort(arr, up, downPtr);
 if (upPtr < down) QuickSort(arr, upPtr, down);
}