data structure 3
TRANSCRIPT
자료구조 세미나
포인터
포인터는 추상적이다 ?
• 포인터는 추상적으로 가질 수 없는 개념이다 .
• 포인터에 대한 개념을 추상적으로 가질 경우 포인터를 100% 활용할 수 없다 .
• 그렇다면 포인터를 어떻게 바라봐야 할까
포인터의 정체
• 포인터는 int 변수
• int 변수가 하드웨어 및 운영체제에 따라 그 크기가 달라지는 것처럼 포인터 변수의 크기도 같이 달라짐
• sizeof( 포인터 변수 ) == sizeof( int )
• sizeof( char * ) > sizeof( char )
• 그렇다면 왜 따로 포인터 변수라는 것을 사용하는가 ?
어셈블러에서포인터
• 어셈블러에서 OFFSET 이나 ADDR 의 값을 저장할 때 모드에 따라 DWORD 나 WORD 를 사용했다 .
– 즉 , 어셈블러에서도 포인터 변수는 int 였다 .
– 하지만 어셈블러에서는 포인터 변수가 따로 없어서 주소에 있는 값을 참조할 때 여러 가지 처리를 해줘야 했다 . 크기를 모르기 때문에 PTR 을 사용해야 했고 크기에 따라 다르게 주소 값을 증가시켰다 .
어셈블러에서포인터
• 어셈블러에서 포인터 사용
mov esi, myaddress
mov ax, WORD PTR [esi]
add esi, TYPE myaddress
mov ax, WORD PTR [esi]
C언어에서포인터
• 포인터는 가리키는 메모리가 어떤 메모리인지 알 수 있게 한다 .
• char * 형의 포인터 변수는 1 바이트 변수를 가리키고 있다 .
• FILE * 형의 포인터 변수는 FILE 구조체를 가리키고 있으며 FILE 구조체의 멤버변수에 접근할 수 있게 한다 .
C언어에서포인터
• C 언어에서 포인터 사용
int a, b, c, k[10], *addr;
addr = &k[0]; // &k[0] == k
a = *addr;
addr++;
b = *addr;
c = *(addr + 4)
자료구조 세미나
링크드 리스트
정의
• 메모리상에서 인접하지 않은 데이터들을 인접한 것처럼 포인터로 연결한 자료구조
• 동적으로 생성되는 메모리에 기반
• 삽입 삭제가 빠르고 메모리의 낭비가 적음
개념도
데이터 데이터
데이터 데이터
head
tail
구조체
• 구조체의 정의
typedef struct _link
{
int data;
_link *prev;
_link *next;
} LINK;
초기화• 초기화 코드
LINK *head, *tail;
void init()
{
head = new LINK;
tail = new LINK;
head->next = tail;
head->prev = head;
tail->next = tail;
tail->prev = head;
}
초기화• 구조
– [ data ][ prev ][ next ]
– 앞에서부터 data, previous, next
• 진행과정– head [ ][ ][ ]
– tail [ ][ ][ ]
– 초기화 후
– head(10680 번지 ) [ ][ 10680 ][ 10692 ]
– tail(10692 번지 ) [ ][ 10680 ][ 10692 ]
삽입• 삽입 코드
void put( int a )
{
LINK *t;
t = new LINK;
t->data = a;
t->next = head->next;
t->prev = head;
head->next->prev = t;
head->next = t;
}
삽입• 진행과정
– put( 5 ) 를 실행
– head(10680 번지 ) [ ][ 10680 ][ 10692 ]
– tail(10692 번지 ) [ ][ 10680 ][ 10692 ]
– t(10704 번지 ) [ ][ ][ ]
– head(10680 번지 ) [ ][ 10680 ][ 10692 ]
– tail(10692 번지 ) [ ][ 10680 ][ 10692 ]
– t(10704 번지 ) [ 5 ][ ][ ]
삽입• 진행과정
– head(10680 번지 ) [ ][ 10680 ][ 10692 ]
– tail(10692 번지 ) [ ][ 10680 ][ 10692 ]
– t(10704 번지 ) [ 5 ][ 10680 ][ 10692 ]
– head(10680 번지 ) [ ][ 10680 ][ 10704 ]
– tail(10692 번지 ) [ ][ 10704 ][ 10692 ]
– t(10704 번지 ) [ 5 ][ 10680 ][ 10692 ]
삭제
• 삭제 코드
void pop(LINK *k)
{
k->next->prev = k->prev;
k->prev->next = k->next;
}
삭제• 진행과정
– pop( head->next ) 을 실행
– head(10680 번지 ) [ ][ 10680 ][ 10704 ]
– tail(10692 번지 ) [ ][ 10680 ][ 10692 ]
– k(10704 번지 ) [ 5 ][ 10680 ][ 10692 ]
– head(10680 번지 ) [ ][ 10680 ][ 10692 ]
– tail(10692 번지 ) [ ][ 10680 ][ 10692 ]
– k(10704 번지 ) [ 5 ][ 10680 ][ 10692 ]
탐색
• 탐색 코드
LINK *t;
for( t=head->next ; t!=tail ; t=t->next )
{
.. 처리 ..
}
트리 구현
• 트리 또한 링크드 리스트로 구현이 가능
• 구조체typedef struct _node
{
int data;
_node *child[ MAX ], *parent;
} NODE;
• 자식노드 또한 링크드 리스트로 만들 수 있다 .