Weitere ähnliche Inhalte Ähnlich wie 연결리스트 박진호 (20) 연결리스트 박진호2. 개요
사용 할 때, 말아야 할 때
연결리스트의 종류
단일 연결 리스트
원형(환형) 연결 리스트
이중 연결 리스트
3.
일정한 순서를 가지는 데이터 요소들을 표현하는 방법 중의 하나
배열과 다르게 데이터 요소들의 논리적인 순서만 유지되고 기억 장소 내에서
는 각 데이터 요소들은 논리적인 순서와는 상관없는 임의의 위치를 가지도록
하는 자료 구조
연결리스트에서는 각 데이터 요소들이 기억 장소 내의 어떤 위치에 어떤 항목
이 있는지를 표시해 주어야 함. 이를 위해 데이터 요소에는 데이터 값, 위치 정
보도 저장해 주어야 함.
즉, 배열에서의 단점을 제거하면서 메모리를 효율적으로 사용하고 삽입과 삭
제 가 쉬워 처리 시간이 단축되나, 관리 유지에 부가적 비용이 듦.
4. 개요
사용 할 때, 말아야 할 때
연결리스트의 종류
단일 연결 리스트
원형(환형) 연결 리스트
이중 연결 리스트
5.
저장할 데이터 개수가 가변적 인 경우
배열은 설정된 크기를 넘어가면 데이터가 넘쳐서 실행 도중 프로그램 오류가 발생
배열에 설정된 크기가 변할 때마다 재 컴파일하는 것을 방지하려고 넉넉한 크기로 큰 배열을 만
든다면 메모리 낭비가 발생 혹은 재 할 당 시 뒤로 한칸씩 밀고 중간에 값을 넣게되므로 속도 저하
list를 사용하면 저장 공간의 크기가 자동으로 변하므로 유연하게 사용
배열은 랜덤 접근이 가능하나 list는 순차 접근만 가능
중간에 데이터 삽입이나 삭제가 자주 일어날 경우
데이터를 랜덤하게 접근하는 경우가 많지 않을 경우
6.
저장할 데이터 개수가 많으면서 검색을 자주 할 때
List는 검색 속도가 느림
map이나 set, hash_map 사용
아이템을 자주 사용하는 온라인 게임에서는 아이템 사용 시 아이템 정보에 빈번하게 접근하므로
성능을 위해 메모리 낭비를 감수하고 배열로 데이터를 저장해서 랜덤 접근을 사용.
7. 개요
사용 할 때, 말아야 할 때
연결리스트의 종류
단일 연결 리스트
원형(환형) 연결 리스트
이중 연결 리스트
8.
단일 연결리스트(singly linked list)
원형(환형) 연결리스트(circular linked list)
포인터를 이용해서 한 쪽 방향 으로만 연결되어 있는 구조
원형(환형)큐와 마찬가지로 마지막 노드에서 처음 노드로 연결하여 원형으로 된 구조
이중 연결리스트(doubly linked list)
한 쪽 방향으로만 연결 된 경우 반대 방향의 노드를 접근하기 어렵다는 단점을 보안, 양방향으로
포인터를 이용해서 연결한 구조
9. 개요
사용 할 때, 말아야 할 때
연결리스트의 종류
단일 연결 리스트
원형(환형) 연결 리스트
이중 연결 리스트
10.
구조가 간단하고, 기억 장소의 소모가 적은 반면에 역방향으로 리스트를 검색
할 수 없음
-> 노드를 삽입하거나 삭제하려면 별도의 포인터가 필요
위 단점을 해결하기 위해
이중 연결리스트(doubly linlked list)를 사용
14. 개요
사용 할 때, 말아야 할 때
연결리스트의 종류
단일 연결 리스트
원형(환형) 연결 리스트
이중 연결 리스트
15.
맨 마지막 노드의 포인터를 NULL로 하는 대신에 맨 앞의 노드에 연결시켜서
원형구조를 만든것.
환영 연결리스트의 구조
head
A
B
C
<원형(환형) 연결리스트의 구조>
D
16. 개요
사용 할 때, 말아야 할 때
연결리스트의 종류
단일 연결 리스트
원형(환형) 연결 리스트
이중 연결 리스트
17.
노드가 양쪽 방향으로 연결되어 있는 리스트
이중 연결리스트의 구조
오른쪽 방향 : rlink(선행 노드)
왼쪽 방향 : llink(후행 노드)
<이중연결리스트의 노드 구조>
18.
단일 연결리스트는 오직 하나의 연결 부분(링크필드)을 가지고 있지만, 이중
연결 리스트는 연결부분을 두개로 하여 한 개일 때 보다는 기억장소의 낭비가
있지만 효율적인 리스트 운영이 가능
20. #ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
typedef struct tagNode
{
ElementType Data;
struct tagNode* NextNode;
} Node;
/* 함수원형선언*/
Node* SLL_CreateNode(ElementType NewData);
void SLL_DestroyNode(Node* Node);
void SLL_AppendNode(Node** Head, Node* NewNode);
void SLL_InsertAfter(Node* Current, Node* NewNode);
void SLL_InsertNewHead(Node** Head, Node*
NewHead);
void SLL_RemoveNode(Node** Head, Node* Remove);
Node* SLL_GetNodeAt(Node* Head, int Location);
int SLL_GetNodeCount(Node* Head);
#endif
#ifndef DOUBLY_LINKEDLIST_H
#define DOUBLY_LINKEDLIST_H
#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
typedef struct tagNode
{
ElementType Data;
struct tagNode* PrevNode;
struct tagNode* NextNode;
} Node;
/* 함수원형선언*/
Node* DLL_CreateNode( ElementType NewData );
void DLL_DestroyNode( Node* Node);
void DLL_AppendNode( Node** Head, Node* NewNode );
void DLL_InsertAfter( Node* Current, Node* NewNode );
void DLL_RemoveNode( Node** Head, Node* Remove );
Node* DLL_GetNodeAt( Node* Head, int Location );
int DLL_GetNodeCount( Node* Head );
#endif DOUBLY_LINKEDLIST_H
21. #include "LinkedList.h“
#include "DoubleList.h"
/* 노드생성*/
Node* SLL_CreateNode(ElementType NewData)
{
Node* NewNode = (Node*)malloc(sizeof(Node));
/* 노드생성*/
Node* DLL_CreateNode( ElementType NewData )
{
Node* NewNode = (Node*)malloc(sizeof(Node));
NewNode->Data = NewData; /* 데이터를저장한다. */
NewNode->NextNode = NULL;
/* 다음노드에대한포인터는NULL로초기화한다. */
NewNode->Data = NewData;
NewNode->PrevNode = NULL;
NewNode->NextNode = NULL;
return NewNode;/* 노드의주소를반환한다. */
return NewNode;
}
}
/* 노드소멸*/
void SLL_DestroyNode(Node* Node)
{
free(Node);
}
/* 노드소멸*/
void DLL_DestroyNode( Node* Node )
{
free(Node);
}
22. /* 노드추가*/
void SLL_AppendNode(Node** Head, Node* NewNode)
{
/* 헤드노드가NULL이라면새로운노드가Head */
if ( (*Head) == NULL )
{
*Head = NewNode;
}
else
{
/* 테일을찾아NewNode를연결한다. */
Node* Tail = (*Head);
while ( Tail->NextNode != NULL )
{
Tail = Tail->NextNode;
}
/* 노드추가*/
void DLL_AppendNode( Node** Head, Node* NewNode )
{
/* 헤드노드가NULL이라면새로운노드가Head */
if ( (*Head) == NULL )
{
*Head = NewNode;
}
else
{
/* 테일을찾아NewNode를연결한다. */
Node* Tail = (*Head);
while ( Tail->NextNode != NULL )
{
Tail = Tail->NextNode;
}
Tail->NextNode = NewNode;
Tail->NextNode = NewNode;
NewNode->PrevNode = Tail;
/* 기존의테일을새로운테일의PrevNode가가리킨
}
}
*/
}
}
X
NULL
head
A
NULL
B
B
C
D
NULL
23. /* 노드삽입*/
void SLL_InsertAfter(Node* Current, Node* NewNode)
{
NewNode->NextNode = Current->NextNode;
Current->NextNode = NewNode;
}
/* 노드삽입*/
void DLL_InsertAfter( Node* Current, Node* NewNode )
{
NewNode->NextNode = Current->NextNode;
NewNode->PrevNode = Current;
if ( Current->NextNode != NULL )
{
Current->NextNode->PrevNode = NewNode;
Current->NextNode = NewNode;
}
}
X
head
A
NULL
B
C
D
NULL
24. /* 노드제거*/
void SLL_RemoveNode(Node** Head, Node* Remove)
{
if ( *Head == Remove )
{
*Head = Remove->NextNode;
}
else
{
Node* Current = *Head;
while ( Current != NULL && Current->NextNode != Remove )
{
Current = Current->NextNode;
}
if ( Current != NULL )
Current->NextNode = Remove->NextNode;
}
}
25. /* 노드제거*/
void DLL_RemoveNode( Node** Head, Node* Remove )
{
head
A
if ( *Head == Remove )
{
*Head = Remove->NextNode;
NULL
if ( (*Head) != NULL )
(*Head)->PrevNode = NULL;
B
Remove->PrevNode = NULL;
Remove->NextNode = NULL;
}
else
{
Node* Temp = Remove;
if ( Remove->PrevNode != NULL )
Remove->PrevNode->NextNode = Temp->NextNode;
if ( Remove->NextNode != NULL )
Remove->NextNode->PrevNode = Temp->PrevNode;
Remove->PrevNode = NULL;
Remove->NextNode = NULL;
}
}
C
D
NULL
26. /* 노드탐색*/
Node* SLL_GetNodeAt(Node* Head, int Location)
{
Node* Current = Head;
/* 노드탐색*/
Node* DLL_GetNodeAt( Node* Head, int Location )
{
Node* Current = Head;
while ( Current != NULL && (--Location) >= 0)
{
Current = Current->NextNode;
}
while ( Current != NULL && (--Location) >= 0)
{
Current = Current->NextNode;
}
return Current;
return Current;
}
}
/* 노드수세기*/
int SLL_GetNodeCount(Node* Head)
{
int Count = 0;
Node* Current = Head;
/* 노드수세기*/
int DLL_GetNodeCount( Node* Head )
{
unsigned int Count = 0;
Node*
Current = Head;
while ( Current != NULL )
{
Current = Current->NextNode;
Count++;
}
while ( Current != NULL )
{
Current = Current->NextNode;
Count++;
}
return Count;
}
return Count;
}
27. void PrintNode( Node* _Node )
{
if ( _Node->PrevNode == NULL )
printf("Prev: NULL");
else
printf("Prev: %d", _Node->PrevNode->Data);
printf(" Current: %d ", _Node->Data);
if ( _Node->NextNode == NULL )
printf("Next: NULLn");
else
printf("Next: %dn", _Node->NextNode->Data);
}
28. int _tmain(int argc, _TCHAR* argv[])
{
int i = 0;
int Count = 0;
Node* List = NULL;
Node* NewNode = NULL;
Node* Current = NULL;
/* 리스트출력*/
Count = DLL_GetNodeCount( List );
for ( i = 0; i<Count; i++ )
{
Current = DLL_GetNodeAt( List, i );
printf( "List[%d] : %dn", i, Current->Data );
}
/* 노드5개추가*/
for ( i = 0; i<5; i++ )
{
NewNode = DLL_CreateNode( i );
DLL_AppendNode( &List, NewNode );
}
/* 모든노드를메모리에서제거 */
printf( "nDestroying List...n" );
Count = DLL_GetNodeCount(List);
for ( i = 0; i<Count; i++ )
{
Current = DLL_GetNodeAt( List, 0 );
/* 리스트출력*/
Count = DLL_GetNodeCount( List );
for ( i = 0; i<Count; i++ )
{
Current = DLL_GetNodeAt( List, i );
printf( "List[%d] : %dn", i, Current->Data );
}
if ( Current != NULL )
{
DLL_RemoveNode( &List, Current );
DLL_DestroyNode( Current );
}
}
/* 리스트의세번째칸뒤에노드삽입*/
printf( "nInserting 3000 After [2]...nn" );
Current = DLL_GetNodeAt( List, 2 );
NewNode = DLL_CreateNode( 3000 );
DLL_InsertAfter( Current, NewNode );
return 0;
}