728x90

삽입정렬(Insert Sort)


힙정렬(Heap Sort)
초보 프로그래머의 실력을 보고자 할 때 우선순위 큐를 물어보는 경우가 많다. 실제 기술 면접 때도 우선순위 큐를 다루는 문제가 자주 나오니 확실하게 기억해두자.
우선순위 큐는 힙(Heap)을 사용해야 한다. 물론 삽입정렬과 큐를 사용해도 무관하지만 그것은 O(N^2)알고리즘이다. 이에 반해 Heap은 O(N log N)이다. 엄청난 차이를 보이는 알고리즘.. 그러한 차이를 알고있느냐가 관건인 것이다. 돌아만 가는 코드를 내놓은 프로그래머는 실무에선 그다지 필요하지 않다.


쉘 정렬(Shell Sort)

출처 : http://www.tipssoft.com
퍼갈때 출처를 달아달라는 말이 있었다..ㅎ
728x90
728x90

선택정렬(Selection Sort)


버블정렬(bubble sort)


퀵정렬(Quick Sort)

자료출처 : http://www.tipssoft.com
728x90
728x90
완전제곱이란?


인터넷 카페를 돌다가 누군가 완전제곱 판별 소스를 올려놓은 것을 봤다. 소스를 보면서 문제를 풀 때 바로 컴퓨터 앞에서 작성을 시작하는 것이 얼마나 위험한 일인지 다시 생각하게 되었다.
아래는 까페 관리자가 올린 소스다. 프로그래밍에 꽤 신경을 많이 쓰는 것이 보이는 사람인데 문제를 풀 때는 가끔 실수를 하기도 하니까.. 만약 이 글을 본다면 기분나쁘게 생각하지 말았으면 좋겠다.

좀 더 많은 수를 입력받을 수있게 하기 위해 unsigned long을 사용하고 있는 것을 알 수 있다.(int는 컴파일러에 따라 다른 결과를 가져올 수도 있다.)
무리하게 if문 내에 핵심내용을 기술하는 것 외에도 치명적인 실수가 있다. 프로그램이 실행되는 동안 불필요한 작업을 반복해서 하고 있는 부분이 있다. 도대체 어디가? 아래 글을 보기 전에 한번 차근자근 따져보기 바란다.


================================================================================
불필요한 작업은..

그래서 소스를 조금 수정해봤다.

이래놓고 봐도 도저히 마음에 들지 않는다. 이럴 땐 문제를 처음부터 다시 인식하는 과정이 필요하다.
완전제곱의 정의 : 다른 정수의 제곱으로 표현되는 정수
1조건 : 정수여야 한다.
2조건 : 다른 정수의 제곱으로 표현된다.(다시 말하면 기하평균이 정수다.)

이렇게 생각해보면 기하평균이 정수인지 확인해보면 되는 것이다. 기하평균이란 어떠한 수의 제곱근을 말하는 것으로 루트를 씌운 값이라고 생각하면 쉽다. 기하평균이 정수인지는 어떻게 판단하지? 난 아래와 같은 코드를 생각했다.

꽤 길고 복잡한 소스가 두줄로 줄었다. 심지어 이정도라면 함수를 따로 구현할 필요조차 없이 그냥 한줄로 넣어주면 된다. 문제를 제대로 인식하고 어떤 방법으로 접근할 것인가를 깊이 생각해보는 것은 프로그래머의 중요한 습관이다. 열심히 생각하고 노력하는 사람들도 실수를 많이 하는데 처음부터 함부러 뛰어드는 습관이 들어버린다면 당신은 프로그래머가 아니라 코더로 만족해야 한다.
728x90
728x90
커리큘럼을 복사해온 것을 보다가 연산자부분은 그냥 넘어가면 안되겠다 싶어서 손을 대게 되었다.
특히 비트연산자는 눈여겨볼 필요가 있다.
연산자 - 단항, 산술, 쉬프트-비트, 관계, 논리, 삼항, 대입
대략 이런 식으로 분류할 수 있단다.

1. 단항 연산자
말 그대로 operend가 하나다. 같은 수식도 위치에 따라 쓰임이 달라지는데 특히 단항 연산자가 그렇다.
종류 : + , - , ++, --
예 : int a = 10;이라고 가정해보자.
+10, -10, +a, -a (상수나 변수가 음수인지 양수인지를 나타낸다.)
++a, a++, --a, a-- (많이 사용되지만 결코 쉽지 않은 연산이다. ++은 a의 값을 1증가시켜 a에 대입하고 --는 그 반대다. 하지만 ++a처럼 연산이 앞에(선행) 있으면 해당 line에서 이미 연산이 되고 a++처럼 뒤에(후행) 있으면 다음 줄로 넘어갈 때 연산이 된다. 이 연산은 상수에는 사용할 수 없다.)
프로그래밍 습관에 대해서는 다른 카테고리에 계속 글을 올리겠지만 증가,감소연산자를 대입연산과 함께 사용하는 것은 아주 위험한 일이다.
=========================================
1.           a = 10;
             a = ++a - --a + a++;
             printf("%d\n",a);
-----------------------------------------
 2.        a = 10;
            printf("%d\n", ++a - --a + a++);
=========================================
1번과 2번 소스는 출력 결과가 다르게 나온다. 그런데 중요한 것은 이런 수식이 사용되면 안된다는 것이다. 이런 수식을 잘 사용한다고 자랑하는 것은 멀쩡한 손 놔두고 발로 젓가락질 할 줄 안다고 자랑하는 것과 비슷하다. 누누히 말하지만 소스를 보는 사람이 바보라고 생각하고 최대한 알아보기 쉽게 작성해야 한다.

2. 산술 연산자
종류 : + - * / %
예 : 우리가 생각하는 사칙연산과 똑같이 사용하면 된다. 사칙연산이라면서 왜 다섯개야?라고 생각한 당신! 눈치가 빠르다.
+ : 더하기
- : 빼기
* : 곱하기
/ : 나누기
%: 모듈러
+ -
는 단항연산에서도 사용되었다. 어떻게 쓰이느냐에 따라 연산이 달라진다는 것이다. 양쪽에 operend(피연산자)가 있으면 산술연산으로 계산되니 염두해두자. 그리고 C언어에서 이러한 연산들을 구분하는 것으로 띄어쓰기도 작용을 하므로 주의해야 한다. space bar한번에 전혀 엉뚱한 연산이 작동할 수도 있다.
b - --a, b - - -a, b-- -a 이 세가지가 모두 다르다는 말이다.
/연산은 나누기와 같은데 주의할 점은 C언어에서 int의 나누기연산이다. int는 정수를 취급하기 때문에 나누기 연산의 몫에서 정수부분만 가져온다. 이때 내림을 하는데 15/4의 경우 3.75가 아니라 3이 나온다.
%연산은 유용한 사용이 많으니 잘 기억해두자. 사칙연산도 아니면서 같이 껴 있으면 얼마나 중요한 녀석인지 감 잡아야 한다. 이녀석은 15%4의 결과로 3이 출력된다. %의 사용은 다방면으로 많은데 그중 흔히 사용되는 경우가 반복문 내에서 if문과 함께 사용되는 경우다.
if( i % 3 == 0) 이렇게 사용하면 i가 3의 배수일 때마다 if문이 작동한다.

3. 관계연산자
종류: <, >, <=, >=, ==, !=

A < B : A가 B보다 작다
A > B : A가 B보다 크다
A <= B : A가 B보다 작거나 같다. (작아도 true, 같아도 true)
A >= B : A가 B보다 크거나 같다. (커도 true, 같아도 true)
A == B : A와 B는 같다.
A != B : A와 B는 같지 않다.
주의할 것은 앞에 있는 A가 중심이고 식의 결과는 true나 false가 된다. C의 경우 true나 false의 개념이 없기 때문에 true는 1이 false는 0이 return된다.
(TIP: C에서는 0이면 false이고 나머지 다른 값이면 true가 된다.)

4. 삼항연산자
종류: 수식?A:B
예: (a>b) ? a++ : b++;
수식의 값이 참(true)이면 A가 실행되고 거짓(false)이면 B가 실행된다. 잘 사용되지 않는 수식이지만 복잡하고 긴 수식을 한방에 조지는 마법같은 효과가 있다.

5. 논리연산자
종류: &&, ||, !
ADN, OR, NOT이라고 부른다.
논리연산자는 계산식을 operend로 하는 것을 원칙으로 한다.
A && B : 두 식이 모두 참이다. (두 식이 모두 true면 true, 아니면 모두 false)
A || B : 둘중 하나는 참이다.(두 식이 모두 false면 false, 아니면 모두 true)
!A : A의 결과를 반대로~ (A가 true면 false, A가 false면 true)

6. 비트연산자
사실 내가 비트연산자 때문에 글을 쓰게 되었다. 비트연산은 조금쯤 깊이있게 생각해야 하기 때문에 일반적인 프로그래밍에서 많이 사용하지 않는 것이 좋다. 하지만 비트연산은 산술연산보다 확실히 빠르므로 반복횟수가 많고 계속적인 연산이 있을 경우, 비트연산이 편리한 수식일 경우 비트연산을 잘 사용하면 효율적이다.
종류 : &, |, ~
&(AND) : 비트가 둘다  1이면 1 아니면 0
|(OR) : 비트가 둘다 0이면 0 아니면 1
~(NOT): 비트 반대로
예)
이해만 확실히 하면 전혀 어려운 개념이 아니다. 다만 2진수로 생각해야 한다는 것이 문제다.

7. shift(쉬프트)
종류 : >>, <<
에) 20 << 3 이거 결과로 80 나온다. 왜 그런지 알아보자
20 : 0000 0001 0100
<<3
결과 : 0000 1010 0000
왼쪽으로 3칸 이동한 것을 볼 수 있다. shift연산자는 방향에 따라 이동하기때문에 헷갈리기 쉽다.
화살표가 있다고 생각하면 기억하기 쉽다.
<<------- 요녀석 왼쪽으로 이동하라는 이야기
------------>> 요녀석 오른쪽으로 이동하라는 이야기
주의: >> 요녀석 주의해야 한다. <<는 오른쪽에 0으로 무조건 채우면 된다.
그런데 >>는 MSB에 따라 달라진다. 그러니까 가장 왼쪽에 있는값이 1이면 1로 채우고 0이면 0으로 채워야 한다. 그러니까 양수면 0으로 채우고 음수면 1로 채우라는 이야기!
728x90

+ Recent posts