이 블로그 검색

2011년 7월 20일 수요일

Single linked list | 싱글 링크드 리스트

이번 포스트는 자료구조의 가장 기본이 되는 링크드 리스트중의 가장 단순한 버전인

싱글 링크드 리스트의 구현이다.

일단 구현을 하기 전에 왜 링크드 리스트를 사용 하는지에 대하여 알아보자.

우선 배열에 대하여 생각해봐야 하는데 우선 배열의 특징은 다음과 같다.

1. 구현하기가 쉽다.

2. 빠르다.

하지만 그만큼 단점이 존재 하는데

1. 데이터의 삽입/삭제시 데이터의 이동연산이 많다.

2. 배열 사이즈의 변경이 힘들다.

이와 같은 이유로 링크드 리스트를 사용하게 된다.

우선 이번에 구현할 싱글 링크드 리스트의 그림을 보면 다음과 같다.


그림의 A ,B  ,C ,D 부분이 데이터부분 그리고 옆에 작은 네모 (링크)가 다음 리스트를 가르

키는 포인터이다. 이러한 데이터 부분과 링크부분을 합쳐서 노드라고 부르는데 일단 C언어로

구현한다고 생각해보면 데이터부분과 링크부분을 하나의 집합으로 구현하여야 하기 때문에 

구조체를 이용한다. ( 이 포스트에서는 간단한 구현을 위해 데이터부분에는 int형 정수 하나

만 들어가도록 만든다. )

typedef struct _Node{
    int key;
    struct _Node* next;
} Node;

Node* head = NULL;

Node 구조체는 앞에서 설명한데로 int형이 들어가는 데이터부분( int key )과  다음 리스트를 

가르키는 링크부분 ( struct_Node * next )가 존재하며 앞에서 설명하지 않은 전역 변수인 

Node * head를 선언하는 부분이 있는데 변수의 이름을 보면 알수 있듯이 링크드리스트의 처

음 부분을 가르키는 포인터 이다. 이 포인터를 만드는 이유는 배열의 배열명처럼 링크드리스

트의 시작번지를 가르키는 포인터가 필요하기 때문이다.

이 리스트를 관리 하기 위해서 이번 포스트에서는 다음과 같은 함수들을 만든다.

int InsertHead( int key );
int RemoveHead();
void  PrintList();

함수들의 이름만 봐도 어떠한 기능을 하는 함수 인지 알수 있을테니 하나씩 구현을 해보자

우선

int InsertHead( int key ) 
1. 인자로 들어온 key값으로 노드를 만들어서
2. 만얀 리스트가 비어 있다면 이 노드를 리스트의 헤드로
3. 리스트가 비어있지 않다면 이 노드를 기존의 헤드를 새로만든 노드의 다음 리스트로 연결하고 새로만든 노드를 헤드로 선언한다.

이런식으로 돌아가는 함수이다. 이 것을 코드로 나타내면 다음과 같다.

int InsertHead( int key ){

     //1. 노드를 생성한다
     Node* node = NULL;
     node = (Node*)malloc( sizeof(Node) );
     if( node == NULL ){
     return -1;
     }
     node->key  = key;

     // 2.리스트가 비어 있다면
     if( head == NULL ){
     node->next = NULL;
     tail = node;
     }
     else{ 3. 리스트가 비어 있지 않다면
     node->next = head;
     }

     head = node; // 2,3번의경우 둘다 사용되는 코드부분이므로 코드중복을 피하려고 밖으로 빼준다.

     return 1;
 }

int RemoveHead()
1. 지울 노드를 가르킬 포인터를 만들고 그 포인터가 리스트의 헤드를 가르키게 한다.
2. 리스트가 비어 있는 경우 지울것이 없기때문에 -1을 리턴한다.
3. 리스트의 노드가 한개인 경우 그 노드를 지우고 리턴한다.
4. 리스트의 노드가 여러개인 경우 지울 노드의 링크부분이  가르키고 있는 노드를 헤드로 만든다. 지울 노드를 메모리 free해준다.

이것을 코드로 나타내면 다음과 같다.

 int RemoveHead()
 {
     Node * removeNode = head;//1. 지울 노드를 가르킬 포인터를 만들고 그 포인터가 리스트의 헤드를 가르키게 한다.

     if( removeNode == NULL )
     {
         return -1; // 2. 리스트가 비어 있는 경우 지울것이 없기때문에 -1을 리턴한다.
     }
     else
     {
         if(removeNode->next == NULL)
         {
             head = NULL; //3. 리스트의 노드가 한개인 경우 그 노드를 지우고 리턴한다.
             return 0;
         }
         head = removeNode->next; //4. 리스트의 노드가 여러개인 경우 지울 노드의 링크부분이  가르키고 있는 노드를 헤드로 만든다. 지울 노드를 메모리 free해준다.
         free(removeNode);
         return 0;
     }
 }

마지막으로 

void  PrintList()
리스트의 내용을 화면에 출력 하는 함수 이다.

1. 리스트를 탐색할 커서 노드 포인터를 만든다.
2. 노드 포인터를 헤드를 가르키게 한다.
3. 노드 포인터를 다음 링크의 주소로 바꿔주면서 노드의 값을 출력한다.

코드로 나타내면 다음과 같다.

void PrintList(){
 
    int i = 1;
    Node* cur = NULL; //1. 커서 노드 포인터를 만든다.

    cur = head; // 2. 노드 포인터를 헤드를 가르키게 한다.
     while( cur != NULL ){
     printf( "%2d list key is  %d\n",i++, cur->key );
     cur = cur->next; //3. 노드 포인터를 다음 링크의 주소로 바꿔주면서 노드의 값을 출력한다.
     }
 }











2011년 7월 19일 화요일

옵션 메뉴 | onCreateOptionsMenu && onOptionsItemSelected

모바일 디바이스들은 제한된 디스플레이 크기를 가지므로 (dell 의 스트릭 같은 변태기종이 있

긴 하지만) 주어진 디스플레이 크기를 효율적으로 사용해야 합니다.

안드로이드는 그렇기 때문에 메뉴같은 것들은 사용자가 필요할때만 화면에 나타도록 설계 되었

습니다. 이번 포스트는 그러한 메뉴를 어떻게 구현을 하는지가 주된 내용이 되겠습니다.

 

다음과 같이 사용자가 메뉴 버튼을 눌렀을때 메뉴바를 표시합니다.

메뉴바를 구현하기 위해서는 액티비티에서 onCreateOptionMenu() 와

onOptionsItemSelected() 메서드를 오버라이딩 하면 되는데 다음과 같이 합니다.

메뉴바를 만들 엑티비티의 소스에서 오른쪽 버튼을 클릭한후 


soure->Override/Implement Methods 를 선택합니다. 그럼 다음과 같은 창이 나오는데


우리가 오버라이딩할 onCreateOptionMenu() 와 onOptionsItemSelected()를 체크한뒤 확인

을 누르면


다음과 같은 2개의 메서드를 만들어 줍니다( 주석 된 코드부분 제외) 이 두 메서드를 구현함

으로서 메뉴바를 사용할수 있게 되는데 우선 

OnCreateOptionsMenu() 메서드는 액티비티의 옵션 메뉴를 초기화 하는 메서드입니다.

인자로 들어오는 Menu 클래스의 add()메서드 즉 Menu.Add()메서드를 이용하여 메뉴에 아

이템을 추가하는데 Menu 클래스의 존재하는 4가지의 Add()메서드중 이번 포스트에서 사용

할 메서드는 다음과 같습니다.

abstract MenuItem add( int groupId, int itemId, int order, CharSequence title)

이 함수에서 처음 인자인 groupId 같은 경우는 메뉴 아이템을 그룹화할때 사용하지만 이번 포

스트에서는 사용하지 않습니다.

두번째인 itemId 같은경우는 다음에 구현할 onOptionsItemSelected메서드에서 어떤 메뉴가 

선택이 되었는지 구분하는 아이디 이기 때문에 각각 메뉴별로 구분할수 있는 값을 넣어 주어

야 합니다.

세번째 order는 메뉴에 아이템들이 출력될 순서를 지정합니다. 이번 포스트에는 사용 하지 않

습니다.

네번째 title은 각 아이템에 출력될 문자열을 넣습니다.

이렇게 menu.Add()를 이용하여 메뉴에 아이템을 넣어주면 메뉴를 화면에 출력하는 것 까지

는 구현이 되었습니다.

다음 으로는 onOptionsItemSelected() 메서드인데 이 메서드의 인자로 MenuItem item이 넘

어옵니다. 이 item을 이용하여 어떠한 것이 클릭 되었는지를 구분하는데 item.getItemId()메

서드를 이용하면 클릭된 메뉴의 Id를 받아올수 있습니다. 이 id에 있는 값이 좀전에  

onCreateOptionMenu() 메서드 안에서 menu.add() 에 두번째 인자로 들어갔던 그 값 입니

다. 그렇기 떄문에 switch문을 이용해서 클릭된 아이템의 아이디 별로 실행될 코드를 작성 해

주시면 됩니다.

그럼 다음 포스트에서 봐요~

( 위의 스크린샷중 코드부분의 주석처리가 되어있는 부분을 보시면 이해가 빠르실 거라고 생

각합니다.)

2011년 7월 17일 일요일

ListActivity 와 ListView

안드로이드 개발자 공식 사이트중 노트패드 튜토리얼을 보면서 따라하던중
http://developer.android.com/resources/tutorials/notepad/notepad-ex1.htm

컴파일을 해보고 돌려보니 처음 레이아웃을 불러오는 지점에서 프로그램이 죽었다. 왜 그러는지 열심히 삽을 들고 찾아보던 도중 튜토리얼에 나와있는 코드와 나의 코드를 비교해보니 이 부분이 틀렸다.

레이아웃을 설정하는 xml부분에서

튜토리얼:
  <ListView android:id="@android:id/list"
  android:id="@+id/list" 라고 사용한 것이 문제 였다.

공식 홈페이지에서 ListActivity 에 관하여 찾아보면 다음과 같은 글이 있다.

ListActivity has a default layout that consists of a single, full-screen list in the center of the screen. However, if you desire, you can customize the screen layout by setting your own view layout with setContentView() in onCreate(). To do this, your own view MUST contain a ListView object with the id "@android:id/list" (or list if it's in code)

다음부터는 이런 뻘짓 하지 않기를 바라면서 이상 끝

2011년 7월 16일 토요일

vim 환경설정

학교에서 친구들을 보면 거의 대부분?이 cui환경을 싫어하고 비주얼 스튜디오에서 코드를 작성하고 그 코드를 리눅스로 포팅?시키는 식의 작업을 많이 하길래 이번 포스팅은 리눅스 cui환경의 대표적인 에디터는 vim에 대한 환경설정 입니다.

환경설정 없이 vim을 실행한다면


다음과 같이 들여쓰기와 라인번호 등등이 나오지 않습니다. 이러한 기능을 쓰기위해서는 설정을 해줘야 하는데 스샷의 저화면에서 esc를 눌러 명령모드로 바꾼다음에 다음과 같이 입력합니다.

:set number ->라인별로 행번호가 나오게 합니다.
:set cindent  -> 자동 들여쓰기를 합니다.
:set smartindent 
:set autoindent 
:set ts=4 -> 탭간격을 4로 합니다.

일단 이렇게만 해도 기본적인 코딩하는데는 문제가 없을듯 합니다.
하지만 vim을 킬때마다 저렇게 해준다는것이 은근 귀찮기 때문에 다음과 같이 합니다.

자신의 홈폴더에 .vimrc 파일을 만들고 그 파일안에 위의 내용을 넣습니다.
(ex. 나의 아이디가 taekk2인경우 /home/taekk2/.vimrc)

마지막으로 vim을 사용하면서 유용하게 쓰이는 단축키 모음을 올려드립니다.


2011년 7월 15일 금요일

첫 포스트

다들 이상하게 블로그를 하는사람도 하나둘씩 생기고 지원서에도 블로그를 쓰는 란이 따로 있기도 한경우가 많고 가장 중요한건 내가 공부 했던 것들을 기록하기위해 나도 한번 시작해 봐야겠습니다.