반응형

 

선택정렬(Selection sort)

- 제자리 정렬 알고리즘의 하나이다.

- 각 순회마다 제일 앞의 기준 원소를 잡고 다음 원소부터 차례차례로 검사하여 정렬하는 방법이다.

- 시간복잡도가 O(n^2)이지만, 메모리가 제한적인 경우 사용시 성능 상의 이점이 있다.

  ※ 같은 시간복잡도를 가지고 있는 버블정렬보다 선택정렬이 우수하다. (교환 횟수가 작기때문)

 

 

 

원리 (오름차순 기준)

  1. 각 순회마다 제일 앞의 원소를 기준 원소로 잡는다.

  2. 기준 원소의 다음 원소부터 배열 끝까지 돌면서 최소값을 탐색한다. (이 때, 최소값은 기준 원소값보다 작아야한다.)

  3. 최소값이 존재하면 원소의 위치를 바꿔준다.

    ※ 마지막 순회는 정렬할 필요가 없으므로 순회를 돌 필요가 없다.

 

 

 

코드

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define MAX 10

void SetArr(int arr[])
{
    for(int i = 0; i < MAX; i++)
    {
        arr[i] = rand() % 100;
    }
}

void PrintArr(int arr[])
{
    for (int i = 0; i < MAX; i++)
    {
        printf("%d\n", arr[i]);
    
    }
}

void SelectionSortAscending(int arr[])
{
    for (int i = 0; i < MAX - 1; i++)
    {
        int min = i;
        for (int j = i + 1; j < MAX; j++)
        {
            if (arr[min] > arr[j])
            {
                min = j;
            }
        }

        if (i != min)
        {
            int tmp = arr[min];
            arr[min] = arr[i];
            arr[i] = tmp;
        }
    }
}

void SelectionSortDescending(int arr[])
{
    for (int i = 0; i < MAX - 1; i++)
    {
        int min = i;
        for (int j = i + 1; j < MAX; j++)
        {
            if (arr[min] < arr[j])
            {
                min = j;
            }
        }

        if (i != min)
        {
            int tmp = arr[min];
            arr[min] = arr[i];
            arr[i] = tmp;
        }
    }
}

void main()
{
    srand(time(NULL));
    int iArr[MAX] = {0};
    
    SetArr(iArr);
    
    SelectionSortAscending(iArr);
    //PrintArr(iArr);
    
    SelectionSortDescending(iArr);
    //PrintArr(iArr);
}

 

반응형

'Stack > Algorithm' 카테고리의 다른 글

[유니티 C#] 퀵 정렬(Quick sort) 구현  (0) 2022.10.06
문자열, 숫자 뒤집기  (0) 2021.10.16
퀵정렬(Quick Sort) 구현  (0) 2021.09.19
삽입정렬(Insertion Sort) 구현  (0) 2021.09.18
버블정렬(Bubble Sort) 구현  (0) 2021.09.14
반응형

 

버블정렬(Bubble sort)

- 1순회마다 큰숫자가 제일 뒤로 밀려나는게 거품이 수중표면으로 올라가는것과 비슷해서 지어진 이름이다.

- 인접한 두 원소를 검사하여 정렬하는 방법이다.

- 시간복잡도가 O(n^2)이기 때문에 느리지만 코드가 단순하다.

 

 

 

 

원리 (오름차순 기준)

  ※ 모든 순회를 다 표현하기엔 이미지 양이 많아지므로 1순회만 기준으로 설명한다.

  1. 2중 반복문으로 원소들을 돌면서 바로 다음 원소와 대소관계를 비교한다.

  2. 비교한 다음 대소관계에 따라 해당 원소와 비교 원소의 위치를 바꿔준다.

    ※ 마지막 순회는 정렬할 필요가 없으므로 순회를 돌 필요가 없다.

 

 

코드

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define MAX 10

void SetArr(int arr[])
{
    for (int i = 0; i < MAX; i++)
    {
        arr[i] = rand() % 100;
    }
}

void PrintArr(int arr[])
{
    for (int i = 0; i < MAX; i++)
    {
        printf("%%d\n", i, arr[i]);
    }
}

void BubbleSortAscending(int arr[])
{
    for (int i = MAX - 1; i > 0; i--)
    {
        for (int j = 0; j < i; j++)
        {
            if (arr[j] > arr[j + 1])
            {
                int tmp = arr[j + 1];
                arr[j + 1] = arr[j];
                arr[j] = tmp;
            }
        }
    }
}

void BubbleSortDescending(int arr[])
{
    for (int i = MAX - 1; i > 0; i--)
    {
        for (int j = 0; j < i; j++)
        {
            if (arr[j] < arr[j + 1])
            {
                int tmp = arr[j + 1];
                arr[j + 1] = arr[j];
                arr[j] = tmp;
            }
        }
    }
}

void main()
{
    srand(time(NULL));
    int iArr[MAX] = { 0 };
    
    SetArr(iArr);
    
    BubbleSortAscending(iArr);
    //PrintArr(iArr);
    
    BubbleSortDescending(iArr);
    //PrintArr(iArr);
}
반응형

'Stack > Algorithm' 카테고리의 다른 글

[유니티 C#] 퀵 정렬(Quick sort) 구현  (0) 2022.10.06
문자열, 숫자 뒤집기  (0) 2021.10.16
퀵정렬(Quick Sort) 구현  (0) 2021.09.19
삽입정렬(Insertion Sort) 구현  (0) 2021.09.18
선택정렬(Selection Sort) 구현  (0) 2021.09.15
반응형

※ 해당 에러가나는 유니티 버전은 Hub에서 유니티 설치시, JDK를 같이 설치하는 버전부터이다.


구글 플레이 게임 서비스(이하 GPGS)를 연동하기위해 플러그인을 다운받아 유니티에 임포트를 하고 Resolve를 했는데, 난데없는 에러가 떴다.

 

Gradle failed to fetch dependencies.
ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

 

'JAVA_HOME'이라는게 설정되지 않았다고한다.

찾아보니 최근 유니티들은 Hub에서 유니티 설치시, SDK, NDK, JDK를 다 설치하다보니 JAVA를 따로 설치할 필요가 없다. 문제는 여기서 발생하는데 GPGS 플러그인 설치 후, Resolve를 할 때 에러가 발생하는것이다.

에러를 추가로 읽어보면,

 

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation.

 

JAVA가 설치된 곳을 JAVA_HOME 변수와 일치시켜달라고 한다. 즉, JAVA_HOME이라는 환경변수를 설정해주면 된다.

그럼 시작해보자!

 

환경변수 설정

1. 내 컴퓨터에서 속성에 들어간다.

2. 고급 시스템설정 - 환경변수 버튼을 눌러준다.

 

3. 시스템 변수 - 새로 만들기 버튼을 눌러 다음과 같이 설정한다.

4. 변수 값에 OpenJDK의 경로를 넘겨준다

  ※ 경로 : 유니티 설치 경로\Editor\Data\PlaybackEngines\AndroidPlayer\OpenJDK

 

 

여기까지 설정을 마쳤다면 이제 재부팅 후 다시 Resolve를 시도해보자!

그러면 Resolve가 진행되며 위와같이 정상적으로 성공 메세지를 받을 수 있다!

 

반응형
반응형

이 블로그는 프로그래밍을 컨텐츠로 하는 블로그이기 때문에 네이버 유입은 사실 별 관심이 없다. (아무래도 프로그래머들은 구글링을 위주로하니까..)

그런데 유튜브 알고리즘으로 추천된 영상을 보다가 티스토리 블로그는 네이버에 노출이 안된다고 해서, 유입을 찾아보니 정말로 네이버 유입은 0으로 표시되어있었다.

구글과 다음 검색 유입만 존재한다.

네이버 유입을 늘이기 위해서는 '네이버 서치어드바이저'라는 곳에 등록을 해야된다는걸 보고 흥미가 생겨 등록과정을 밟게 되었다.

생각보다 어렵지 않아서 기록을 해둘겸 작성하는 글이다.

 

 

네이버 서치어드바이저

1. 구글링이든 네이버에서 검색을 하든 해서 서치어드바이저 페이지에 들어간다.

  ※ 네이버 로그인이 되어있어도 새로 로그인을 해줘야한다.

2. 로그인을 누르면 이용동의 창이 뜨는데, 동의하고 확인을 누르면 로그인이 된다.

 

3. 우측 상단에 웹마스터 도구를 눌러준다.

 

4. 들어가면 사이트 등록이 뜨는데 여기에 티스토리 블로그 주소를 복사 붙여넣기 해준다.

 

5. HTML 태그를 이용한다.

  ※ HTML 파일 업로드는 스킨을 바꾸게되면 날아가기 때문에 새로 등록해줘야한다고 한다.

 

6. 티스토리 블로그의 관리창으로 들어가서 좌측 목록 중에 '플러그인' - '메타 태그 등록'을 눌러서 등록한다.

  ※ 첫 번째 칸에는 HTML 태그의 name = " "안의 내용, 두 번째 칸에는 content = " "의 내용을 복사 붙여넣기 해준뒤 적용을 눌러준다.

 

7. 다시 서치어드바이저 페이지로 돌아와 '소유 확인' 버튼을 눌러주면 보안 확인창이 뜨는데 확인하고 넘겨주면 등록이 끝이 나고, 사이트 목록에 등록한 사이트 목록이 나타난다.

 

 

 

RSS, 사이트 맵 등록

- 사이트 소유권 확인이 끝나면 RSS와 사이트맵을 등록해야한다. RSS와 사이트맵을 등록하기 위해선 사이트 목록에서 소유 확인이 끝난 블로그를 누르면 된다.

 

1. 요청 - RSS 제출을 눌러준다.

 

2. 블로그 주소/rss 기입한 뒤 확인을 눌러주면 RSS 제출이 완료된다.

 

3. 요청 - 사이트맵 제출을 눌러준다.

 

4. sitemap.xml을 기입한뒤 확인을 눌러주면 사이트맵 제출이 완료된다.

 

※ 원래는 RSS, 사이트맵을 따서 제출해야하지만 티스토리는 자체적으로 제공한다고 한다.

 

 

 

이걸로 네이버 서치어드바이저 등록 절차는 완료가 되었다.

앞으로 통계를 확인하면서 실제로 네이버 유입이 발생하면 그때 후기를 작성할 예정이다.

반응형

'Manage > Blog' 카테고리의 다른 글

티스토리 코드 블럭 서식 만들기  (0) 2021.10.03
반응형

  ※ 이 글은 코드 위주이니 설명은 아래 링크 확인 !

  ※ C AVL 트리(AVL Tree) 설명

 

C AVL 트리(AVL Tree) 설명

※ 트리의 개념과 이진탐색트리를 포함해서 설명이 진행되므로 모르면 아래 링크로 확인 ! ※ C 트리(Tree)설명 C 트리(Tree) 설명 트리 - 비선형 자료구조의 일종이다. - 계층적 관계(Hierarchical Relatio

srdeveloper.tistory.com


AVL 트리에 사용할 구조체

typedef struct Node
{
    int data;
    struct Node* Parent, * Left, * Right;
}Node;

  ※ 이전 이진탐색트리와는 다르게 코드의 간결함을 위해 부모 노드를 참조할 변수를 하나 더 만든다.

 

 

 

균형 인수(Balance Factor) 구하기

- 균형 인수 = 왼쪽 서브 트리의 높이 - 오른쪽 서브트리의 높이

int GetHeight(Node* node)
{
    if (node == NULL) return 0;
	
    int leftDepth = GetHeight(node->Left);
    int rightDepth = GetHeight(node->Right);
	
    return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;
}

int CalculateBalanceFactor(Node* node)
{
    return GetHeight(node->Left) - GetHeight(node->Right);
}

  ※ 균형 인수는 CalculateBalanceFactor를 호출하면 된다.

  ※ GetHeight는 재귀함수로 구성해서 단말노드까지의 높이를 반환한다.

 

 

 

LL(Left Left), RR(Right Right)

Node* LL(Node* node)
{
    Node* childNode = node->Left;
    node->Left = childNode->Right;
    if (childNode->Right != NULL)	
        childNode->Right->Parent = node;
	
    childNode->Right = node;
    childNode->Parent = node->Parent;
    node->Parent = childNode;
	
    return childNode;
}

  ※ LL은 다음과 같은 순서로 진행된다.

    1. Child node(이하 CNode)의 오른쪽 자식 참조를 Parent node(이하 PNode)의 왼쪽 자식으로 넣어준다.

      ※ 이 때 CNode의 오른쪽 자식 노드가 NULL이 아니면 오른쪽 자식노드의 부모 참조를 PNode로 변경해준다.

    2. CNode의 오른쪽 자식으로 PNode를 넣어준다.

    3. CNode가 PNode의 위치와 바뀌므로 CNode의 부모 참조를 PNode의 부모로 변경해준다.

    4. PNode의 부모는 CNode가 되므로 PNode의 부모 참조를 CNode로 변경해준다.

  ※ RR은 LL의 순서를 반대로 해주면 된다.

 

 

 

LR(Left Right) RL(Right Left)

Node* LR(Node* node)
{
    node->Left = RR(node->Left);
    return LL(node);
}

  ※ LR은 다음과 같은 순서로 진행된다.

    1. Parent node(이하 PNode)의 왼쪽 자식 노드를 RR회전 해준다.

    2. PNode를 LL회전 해준다.

  ※ RL은 LR의 순서를 반대로 해주면 된다.

 

 

AVL 리밸런싱

- AVL의 균형을 맞추는 함수는 다음과 같이 작성하면 된다.

Node* AVLSet(Node* node)
{
    int depth = CalculateBalanceFactor(node);
    if (depth >= 2)
    {
        depth = CalculateBalanceFactor(node->Left);
        if (depth >= 1)
        {
            //LL : Left Left
            node = LL(node);
        }
        else
        {
            //LR : Left Right
            node = LR(node);
        }
    }
    else if (depth <= -2)
    {
        depth = CalculateBalanceFactor(node->Right);
        if (depth <= -1)
        {
            //RR : Right Right
            node = RR(node);
        }
        else
        {
            //RL : Right Left
            node = RL(node);
        }
    
    }
	
    return node;
}

  ※ 어떤 서브트리의 부모노드를 대상으로 균형 인수를 구한다. (절대값이 2차이가 나면 균형을 잡아준다.)

  ※ 이 때, CalcualteBalanceFactor함수에서 왼쪽 서브트리의 높이에서 오른쪽 서브트리의 높이를 뺴고있으니 반환값이 양수면 왼쪽 서브트리, 음수면 오른쪽 서브트리의 높이가 높다는 것이다.

  ※ 균형 인수의 절대값이 2가 되면 높이가 높은 서브트리를 대상으로 균형 인수를 한번더 계산해서 서브트리가 LL상태(혹은 RR)인지 LR상태(혹은 RL)상태인지 알아본 뒤, 상태에 따라 알맞은 함수를 적용해서 리밸런싱을 진행한다.

 

 

자, 여기까지 이해를 했다면 일단 AVL 트리의 리밸런싱 코드는 끝이났다.

이걸 어떤 타이밍에 적용해줘야 할까? 답은 트리에 변경점이 발생하는 시점이다.

즉, 데이터를 추가(Insert) 할 때, 데이터를 삭제(Delete) 할 때 위의 함수를 넣어주면 된다. 이점을 잘 생각해서 다음 풀 소스코드를 이해해보자. (이번엔 양이 양인만큼 코드가 길다.)

이번 코드에 활용할 트리 구조

#include <stdio.h>

typedef struct Node
{
    int data;
    struct Node* Parent, * Left, * Right;
}Node;

int GetHeight(Node* node)
{
    if (node == NULL) return 0;
	
    int leftDepth = GetHeight(node->Left);
    int rightDepth = GetHeight(node->Right);
	
    return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;
}

int CalculateBalanceFactor(Node* node)
{
    return GetHeight(node->Left) - GetHeight(node->Right);
}

Node* RR(Node* node)
{
    Node* childNode = node->Right;
    node->Right = childNode->Left;
    if (childNode->Left != NULL)
        childNode->Left->Parent = node;
	
    childNode->Left = node;
    childNode->Parent = node->Parent;
    node->Parent = childNode;
	
    return childNode;
}

Node* LL(Node* node)
{
    Node* childNode = node->Left;
    node->Left = childNode->Right;
    if (childNode->Right != NULL)
        childNode->Right->Parent = node;
	
    childNode->Right = node;
    childNode->Parent = node->Parent;
    node->Parent = childNode;
	
    return childNode;
}

Node* LR(Node* node)
{
    node->Left = RR(node->Left);
    return LL(node);
}

Node* RL(Node* node)
{
    node->Right = LL(node->Right);
    return RR(node);
}

Node* AVLSet(Node* node)
{
    int depth = CalculateBalanceFactor(node);
    if (depth >= 2)
    {
        depth = CalculateBalanceFactor(node->Left);
        if (depth >= 1)
        {
            //LL : Left Left
            node = LL(node);
        }
        else
        {
            //LR : Left Right
            node = LR(node);
        }
    }
    else if (depth <= -2)
    {
        depth = CalculateBalanceFactor(node->Right);
        if (depth <= -1)
        {
            //RR : Right Right
            node = RR(node);
        }
        else
        {
            //RL : Right Left
            node = RL(node);
        }
    
    }
	
    return node;
}

Node* Insert(Node* node, int data)
{
    if (node == NULL)
    {
        node = (Node*)malloc(sizeof(Node));
        node->Left = NULL;
        node->Right = NULL;
        node->Parent = NULL;
        node->data = data;
		
        return node;
    }
    else if (data < node->data)
    {
        node->Left = Insert(node->Left, data);
        node->Left->Parent = node;
        node = AVLSet(node);
    }
    else if (data > node->data)
    {
        node->Right = Insert(node->Right, data);
        node->Right->Parent = node;
        node = AVLSet(node);
    }
    else
    {
        //데이터가 중복되므로 추가하지 않는다.
    }
	
    return node;
}

Node* GetMinNode(Node* node, Node* parent)
{
    if (node->Left == NULL)
    {
        if (node->Parent != NULL)
        {
            if (parent != node->Parent)
            {
                node->Parent->Left = node->Right;
            }
            else
            {
                node->Parent->Right = node->Right;
            }
			
            if (node->Right != NULL)
            {
                node->Right->Parent = node->Parent;
            }
        }
		
        return node;
    }
    else
    {
        return GetMinNode(node->Left, parent);
    }
}

Node* Delete(Node* node, int data)
{
    if (node == NULL) return NULL;
	
    if (data < node->data)
    {
        node->Left = Delete(node->Left, data);
        node = AVLSet(node);
    }
    else if (data > node->data)
    {
        node->Right = Delete(node->Right, data);
        node = AVLSet(node);
    }
    else
    {
        if (node->Left == NULL && node->Right == NULL)
        {
            node = NULL;
        }
        else if (node->Left != NULL && node->Right == NULL)
        {
            node->Left->Parent = node->Parent;
            node = node->Left;
        }
        else if (node->Left == NULL && node->Right != NULL)
        {
            node->Right->Parent = node->Parent;
            node = node->Right;
        }
        else
        {
            Node* deleteNode = node;
            Node* minNode = GetMinNode(node->Right, deleteNode);
			
            minNode->Parent = node->Parent;
			
            minNode->Left = deleteNode->Left;
            if (deleteNode->Left != NULL)
            {
                deleteNode->Left->Parent = minNode;
            }
			
            minNode->Right = deleteNode->Right;
            if (deleteNode->Right != NULL)
            {
                deleteNode->Right->Parent = minNode;
            }
			
            node = minNode;
            free(deleteNode);
        }
    }
	
    return node;
}

void Inorder(Node* node)
{
    if (node == NULL) return;
	
    Inorder(node->Left);
    printf("%d ", node->data);
    Inorder(node->Right);
}

void main()
{
    Node* root = NULL;
    
    //INSERT
    root = Insert(root, 4);
    root = Insert(root, 10);
    root = Insert(root, 13);
    root = Insert(root, 20);
    root = Insert(root, 25);
    root = Insert(root, 32);
    root = Insert(root, 55);
    
    Inorder(root);
    //결과 : 4 10 13 20 25 32 55 (root data : 20)
    
    //DELETE
    root = Delete(root, 4);
    root = Delete(root, 10);
    root = Delete(root, 13);
    
    Inorder(root);
    //결과 : 20 25 32 55 (root data : 25)
}

  ※ main 함수의 Insert를 보면 앞에서 다뤘던 이진탐색트리 때와는 다르게 수를 오름차순으로 넣어줘도 똑같은 트리가 만들어진 결과를 볼 수 있다.

  ※ Delete에서는 일부터 왼쪽 서브트리의 데이터를 모두 삭제했다. 그 결과, 리밸런싱을 통해 Root 노드가 25의 키값을 가진 노드로 변경이되어 양쪽 서브트리의 균형이 맞춰진걸 확인할 수 있다.

반응형

'Stack > Data struct' 카테고리의 다른 글

[C#] 자료구조 힙(Heap) 트리 구현  (0) 2022.10.04
C AVL 트리(AVL Tree) 설명  (0) 2021.09.10
C 트리 순회(Tree traversal) 구현  (0) 2021.09.10
C 이진탐색트리(Binary search tree) 구현  (0) 2021.09.09
C 트리(Tree) 설명  (0) 2021.09.09

+ Recent posts