1 / 44

Chapter 5. General Linear List

Chapter 5. General Linear List. Internet Computing Laboratory @ KUT Youn-Hee Han. 0. Concept. General List a list in which operations, such as retrievals, insertions, changes, and deletions, can be done anywhere in the list 목록 또는 도표를 추상화 한 것 일상 생활에서의 예 Lists of employees Student lists

kelda
Télécharger la présentation

Chapter 5. General Linear List

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Chapter 5. General Linear List Internet Computing Laboratory @ KUT Youn-Hee Han

  2. 0. Concept • General List • a list in which operations, such as retrievals, insertions, changes, and deletions, can be done anywhere in the list • 목록 또는 도표를 추상화 한 것 • 일상 생활에서의 예 • Listsof employees • Student lists • Lists of our favorite songs Data Structure

  3. 0. Concept • 필요한연산은? • 주 연산: insertion, deletion, retrieval, traversal • 보조연산: … • 그렇다면, insertion에 대해서 다음 중 어떤 것을 제공해야 하는가?사용자는 어떤 것을 더 원하는가? 둘 다 원하는가? • insert (data) • insert (position, data) • Position-oriented List (위치 기반 리스트) 에서의 연산 정의 예 • insert(position, data) • 데이터를 주어진 위치(position)에 넣기 • delete(position) • 주어진 위치(position)의 데이터를 삭제 • retrieve(position, &data) • 주어진 위치(position)의 데이터를 Data 변수에 복사 • traversal • 리스트 안에 모든 Element에 대해 순서대로 일정한 작업 (예를 들어 단순 방문) 을 행한다. Data Structure

  4. 0. Concept • Ordered List (순서 리스트) 에서의 연산 정의 예 • 임의의 Sequence Rule 이 존재 • 예를 들어 주민번호 (SSN) 순서, 학번 순서, 이름순서… • insert(data) • 주어진 데이터를 정해진 Rule 에 따라 알맞은 위치에 넣기 • data 속에 key 값이 있다고 가정 • delete(data) • 주어진 데이터를 리스트에서 찾아 삭제 • data 속에 key 값이 있다고 가정 • retrieve(data1, &data2) • 주어진 데이터가 리스트에있는지 검색 • 관련된 데이터를 얻어옴 • traversal • 리스트 안에 모든 Element에 대해 순서대로 일정한 작업 (예를 들어 단순 방문) 을 행한다. • 교재에서는 Ordered List를 가정하여 코딩을 제시한다. Data Structure

  5. 1. Basic Operations • Insertion • In ordered list: maintained in sequence according to data • Key: one or more field that identifies the data (ex: SSN) • Deletion • Deletion requires search to locate the data to delete Data Structure

  6. 1. Basic Operations • Retrieval • provides a data without changing list • Search: finding an element in a list by some key • Traversal • process of visiting each element in a list in sequence to do something • Ex) print all elements in a list • Requires looping for all elements Data Structure

  7. 2. Implementation • Linked List implementation of a List • Data Structure of List ADT typedef struct node { Element data; struct node *link; } ListNode; typedef struct { int count; ListNode *head; } List; //head head node Data Structure

  8. 3. List ADT • Generic Coding for List Node • Data (including key) + pointer to next node • Stack과 Queue에서의 Node 정의도 이와 같은 Generic 방법을 사용하고 있음 typedef struct node { void* dataPtr; struct node* link; } NODE; data Generic coding Note] Heap memory for actual data should be allocated by using malloc() Data Structure

  9. 3. List ADT • Generic Coding for List Head • Data (including key) + pointer to next node • In our List ADT, data are stored in key sequence • How to arrange the elements in ordered mode • Solution  compare function • How to handle different types of parameters • Each type of data requires different functions to compare two data (keys) • Solution  function pointer of compare function • Application programmer writes a function to compare two data (keys) typedef struct { int count; NODE* pos; NODE* head; NODE* rear; int (*compare) (void* argu1, void* argu2); } LIST; Data Structure

  10. 3. List ADT • Generic Coding for List Head • int (*compare) (void* argu1, void* argu2); • 본교재에서는 다음과 같이 return 값이 정의됨 • Case I) argu1 의 데이터 > argu2 의 데이터  1 이 리턴됨 • Case II) argu1 의 데이터 < argu2 의 데이터  -1 이 리턴됨 • Case III) argu1 의 데이터 == argu2 의 데이터  0 이 리턴됨 • Examples int compareInt(void *argu1, void *argu2) { return *(int*)argu1 - *(int*)argu2; } int compareStr(void *argu1, void *argu2) { return strcmp((char*)argu1, (char*)argu2); } Data Structure

  11. 3. List ADT • Header file with List ADT Prototypes • File Name: list.h (이후모든 ADT 구현은 이 한 파일에 추가) typedef struct node { void* dataPtr; struct node* link; } NODE; typedef struct { int count; NODE* pos; NODE* head; NODE* rear; int (*compare) (void* argu1, void* argu2); } LIST; LIST* createList (int (*compare) (void* argu1, void* argu2)); LIST* destroyList (LIST* list); Data Structure

  12. 3. List ADT • Header file with List ADT Prototypes int addNode (LIST* pList, void* dataInPtr); bool removeNode (LIST* pList, void* keyPtr, void** dataOutPtr); bool searchList (LIST* pList, void* pArgu, void** pDataOut); bool retrieveNode (LIST* pList, void* pArgu, void** dataOutPtr); bool traverse (LIST* pList, int fromWhere, void** dataOutPtr); int listCount (LIST* pList); bool emptyList (LIST* pList); bool fullList (LIST* pList); static int _insert (LIST* pList, NODE* pPre, void* dataInPtr); static void _delete (LIST* pList, NODE* pPre, NODE* pLoc, void** dataOutPtr); static bool _search (LIST* pList, NODE** pPre, NODE** pLoc, void* pArgu); Data Structure

  13. 3. List ADT • List ADT functions Data Structure

  14. 3. List ADT • createList • Only parameter is the compare function required to compare two data (keys) LIST* createList (int (*compare) (void* argu1, void* argu2)) { LIST* list; list = (LIST*) malloc (sizeof (LIST)); if (list) { list->head = NULL; list->pos = NULL; // working pointer for list traversal list->rear = NULL; list->count = 0; list->compare = compare; } return list; } 0 In main()… list = createList (cmpYear); Data Structure

  15. 3. List ADT • addNode • Find the location to insert the node • Directly preceding node is necessary & Insert node after the preceding node int addNode (LIST* pList, void* dataInPtr) { bool found; bool success; NODE* pPre; NODE* pLoc; found = _search (pList, &pPre, &pLoc, dataInPtr); if (found) return (+1); success = _insert (pList, pPre, dataInPtr); if (!success) return (-1); return (0); } Inserting 55 pPre: dataInPtr을 포함하는 NODE가 삽입되어야 할 위치 바로 직전의 NODE를 가리키는 포인터 pLoc: dataInPtr과 같은 값을 지니는 NODE가 list내에 존재할 때 그 NODE를 가리키는 포인터 Data Structure

  16. 3. List ADT • _search • It is internal function • Two Macros • #define COMPARE ( ((* pList->compare) (pArgu, (*pLoc)->dataPtr)) ) • #define COMPARE_LAST ((* pList->compare) (pArgu, pList->rear->dataPtr)) Data Structure

  17. 3. List ADT • _search • Case (a) – 1 : 찾는 노드가 리스트의 첫 번째 노드일 때 bool _search (LIST* pList, NODE** pPre, NODE** pLoc, void* pArgu) { #define COMPARE ( ((* pList->compare) (pArgu, (*pLoc)->dataPtr)) ) #define COMPARE_LAST ((* pList->compare) (pArgu, pList->rear->dataPtr)) int result; *pPre = NULL; *pLoc = pList->head; if (pList->count == 0) return false; if ( COMPARE_LAST> 0) { *pPre = pList->rear; *pLoc = NULL; return false; } while ( (result = COMPARE) > 0 ) { *pPre = *pLoc; *pLoc = (*pLoc)->link; } if (result == 0) return true; else return false; } pList [TABLE 5-1] Target=first node pPre=NULL pLoc=First nodeReturn is True Data Structure

  18. 3. List ADT • _search • Case (a) – 2 : 찾는 노드가 리스트의 중간에 위치한 노드일 때 bool _search (LIST* pList, NODE** pPre, NODE** pLoc, void* pArgu) { #define COMPARE ( ((* pList->compare) (pArgu, (*pLoc)->dataPtr)) ) #define COMPARE_LAST ((* pList->compare) (pArgu, pList->rear->dataPtr)) int result; *pPre = NULL; *pLoc = pList->head; if (pList->count == 0) return false; if ( COMPARE_LAST > 0) { *pPre = pList->rear; *pLoc = NULL; return false; } while ( (result = COMPARE) > 0 ) { *pPre = *pLoc; *pLoc = (*pLoc)->link; } if (result == 0) return true; else return false; } [TABLE 5-1] Target=middle node pPre=Node’s predecessor pLoc=Equal node (middle node)Return is True Data Structure

  19. 3. List ADT • _search • Case (a) – 3 : 찾는 노드가 리스트의 마지막 노드일 때 bool _search (LIST* pList, NODE** pPre, NODE** pLoc, void* pArgu) { #define COMPARE ( ((* pList->compare) (pArgu, (*pLoc)->dataPtr)) ) #define COMPARE_LAST ((* pList->compare) (pArgu, pList->rear->dataPtr)) int result; *pPre = NULL; *pLoc = pList->head; if (pList->count == 0) return false; if ( COMPARE_LAST > 0) { *pPre = pList->rear; *pLoc = NULL; return false; } while ( (result = COMPARE) > 0 ) { *pPre = *pLoc; *pLoc = (*pLoc)->link; } if (result == 0) return true; else return false; } [TABLE 5-1] Target=last node pPre=Last’s predecessor pLoc=Last nodeReturn is True Data Structure

  20. 3. List ADT • _search • Case (b) – 1 : 찾는 노드가 리스트의 첫번째 노드 보다 작을 때 bool _search (LIST* pList, NODE** pPre, NODE** pLoc, void* pArgu) { #define COMPARE ( ((* pList->compare) (pArgu, (*pLoc)->dataPtr)) ) #define COMPARE_LAST ((* pList->compare) (pArgu, pList->rear->dataPtr)) int result; *pPre = NULL; *pLoc = pList->head; if (pList->count == 0) return false; if ( COMPARE_LAST > 0) { *pPre = pList->rear; *pLoc = NULL; return false; } while ( (result = COMPARE) > 0 ) { *pPre = *pLoc; *pLoc = (*pLoc)->link; } if (result == 0) return true; else return false; } pList [TABLE 5-1] Target<first node pPre=NULL pLoc=First nodeReturn is False Data Structure

  21. 3. List ADT • _search • Case (b) – 2 : 찾는 노드가 리스트에 존재하지 않고 그 값이 리스트 중간에 위치 bool _search (LIST* pList, NODE** pPre, NODE** pLoc, void* pArgu) { #define COMPARE ( ((* pList->compare) (pArgu, (*pLoc)->dataPtr)) ) #define COMPARE_LAST ((* pList->compare) (pArgu, pList->rear->dataPtr)) int result; *pPre = NULL; *pLoc = pList->head; if (pList->count == 0) return false; if ( COMPARE_LAST > 0) { *pPre = pList->rear; *pLoc = NULL; return false; } while ( (result = COMPARE) > 0 ) { *pPre = *pLoc; *pLoc = (*pLoc)->link; } if (result == 0) return true; else return false; } [TABLE 5-1] First<Target<Last pPre=Largest Node (< Target) pLoc=First Node (> Target)Return is False Data Structure

  22. 3. List ADT • _search • Case (b) – 3 : 찾는 노드가 리스트의 마지막 노드 보다 더 클 때 bool _search (LIST* pList, NODE** pPre, NODE** pLoc, void* pArgu) { #define COMPARE ( ((* pList->compare) (pArgu, (*pLoc)->dataPtr)) ) #define COMPARE_LAST ((* pList->compare) (pArgu, pList->rear->dataPtr)) int result; *pPre = NULL; *pLoc = pList->head; if (pList->count == 0) return false; if ( COMPARE_LAST > 0) { *pPre = pList->rear; *pLoc = NULL; return false; } while ( (result = COMPARE) > 0 ) { *pPre = *pLoc; *pLoc = (*pLoc)->link; } if (result == 0) return true; else return false; } [TABLE 5-1] Target>Last pPre=Last Node pLoc=NULLReturn is False Data Structure

  23. 3. List ADT • _search • PP. 249 연습문제 1 • _search 함수 내에서 pHead = pHead->link 와 같은 코딩을 사용하면 어떨까? • 왜 pPre와 pLoc을 별도로 사용할까? Data Structure

  24. 3. List ADT • _insert • Given the predecessor, there are three steps to the insertion • 1. Allocate memory for the new node and move data to the node • 2. Point the new node to its successor • 3. Point the new node’s predecessor to the new node. • Cases of Predecessor point • Case I) NULL (_search 결과 *pPre 가 NULL 인 경우, Case (b) - 1 ) • 1. The new node is inserted to the beginning of the list, or • 2. List is empty • Case II) contain the address of a node (_search 결과 *pPre 가 NULL 이 아닌 경우, Case (b) – 2,3 ) • 1. The new node is inserted in the middle of the list, or • 2. The new node is inserted at the end of the list Data Structure

  25. 3. List ADT • _insert • Case I – 1 : 삽입할 노드가 리스트의 첫번째 노드가되어야 할 때 static bool _insert (LIST* pList, NODE* pPre, void* dataInPtr) { NODE* pNew; if (!(pNew = (NODE*) malloc(sizeof(NODE)))) return false; pNew->dataPtr = dataInPtr; pNew->link = NULL; if (pPre == NULL) { pNew->link = pList->head; // 1) pList->head = pNew; // 2) if (pList->count == 0) pList->rear = pNew; } else { pNew->link = pPre->link; pPre->link = pNew; if (pNew->link == NULL) pList->rear = pNew; } (pList->count)++; return true; } 2) 1) Data Structure

  26. 3. List ADT • _insert • Case I – 2 : 비어있는 리스트에 노드를 삽입할 때 static bool _insert (LIST* pList, NODE* pPre, void* dataInPtr) { NODE* pNew; if (!(pNew = (NODE*) malloc(sizeof(NODE)))) return false; pNew->dataPtr = dataInPtr; pNew->link = NULL; if (pPre == NULL) { pNew->link = pList->head; // 1) pList->head = pNew; // 2) if (pList->count == 0) pList->rear = pNew; // 3) } else { pNew->link = pPre->link; pPre->link = pNew; if (pNew->link == NULL) pList->rear = pNew; } (pList->count)++; return true; } 0 1) 3) 2) 1 Data Structure

  27. 3. List ADT • _insert • Case II – 1 : 삽입할 노드가 리스트 중간에 위치 static bool _insert (LIST* pList, NODE* pPre, void* dataInPtr) { NODE* pNew; if (!(pNew = (NODE*) malloc(sizeof(NODE)))) return false; pNew->dataPtr = dataInPtr; pNew->link = NULL; if (pPre == NULL) { pNew->link = pList->head; pList->head = pNew; if (pList->count == 0) pList->rear = pNew; } else { pNew->link = pPre->link; // 1) pPre->link = pNew; // 2) if (pNew->link == NULL) pList->rear = pNew; } (pList->count)++; return true; } 2) 1) Data Structure

  28. 3. List ADT • _insert • Case II – 2 : 삽입할 노드가 리스트의 마지막 노드 보다 더 이후에 위치 static bool _insert (LIST* pList, NODE* pPre, void* dataInPtr) { NODE* pNew; if (!(pNew = (NODE*) malloc(sizeof(NODE)))) return false; pNew->dataPtr = dataInPtr; pNew->link = NULL; if (pPre == NULL) { pNew->link = pList->head; pList->head = pNew; if (pList->count == 0) pList->rear = pNew; } else { pNew->link = pPre->link; pPre->link = pNew; if (pNew->link == NULL) pList->rear = pNew; } (pList->count)++; return true; } 2) rear 1) Data Structure

  29. 3. List ADT • removeNode • pPre: _search() 호출 결과 삭제하고자 하는 노드의 바로 이전 노드의 포인터 • pLoc: _search() 호출 결과 삭제하고자 하는 노드의 포인터 bool removeNode (LIST* pList, void* keyPtr, void** dataOutPtr) { bool found; NODE* pPre; NODE* pLoc; found = _search(pList, &pPre, &pLoc, keyPtr); if (found) _delete(pList, pPre, pLoc, dataOutPtr); return found; } 삭제하고자 하는 노드의 데이터값 _delete() 이후에삭제된 노드의 데이터 값이 할당됨 Data Structure

  30. 3. List ADT • _delete • Case I) pPre가 NULL인 경우 • 1. 삭제하고자 하는 노드가 첫 번째 노드임 void _delete (LIST* pList, NODE* pPre, NODE* pLoc, void** dataOutPtr) { *dataOutPtr = pLoc->dataPtr; if (pPre == NULL) pList->head = pLoc->link; else pPre->link = pLoc->link; if (pLoc->link == NULL) pList->rear = pPre; (pList->count)--; free (pLoc); return; } Data Structure

  31. 3. List ADT • _delete • Case I) pPre가 NULL인 경우 • 2. 삭제하고자 하는 노드가 첫 번째 노드이고 그 첫번째 노드가 유일한 노드 void _delete (LIST* pList, NODE* pPre, NODE* pLoc, void** dataOutPtr) { *dataOutPtr = pLoc->dataPtr; if (pPre == NULL) pList->head = pLoc->link; else pPre->link = pLoc->link; if (pLoc->link == NULL) pList->rear = pPre; // NULL (pList->count)--; free (pLoc); return; } 1 0 rear Data Structure

  32. 3. List ADT • _delete • Case II) pPre가 NULL이아닌 경우 • 1. 삭제하고자 하는 노드가 중간 노드인 경우 void _delete (LIST* pList, NODE* pPre, NODE* pLoc, void** dataOutPtr) { *dataOutPtr = pLoc->dataPtr; if (pPre == NULL) pList->head = pLoc->link; else pPre->link = pLoc->link; if (pLoc->link == NULL) pList->rear = pPre; (pList->count)--; free (pLoc); return; } Data Structure

  33. 3. List ADT • _delete • Case II) pPre가 NULL이아닌 경우 • 2. 삭제하고자 하는 노드가 마지막 노드인 경우 void _delete (LIST* pList, NODE* pPre, NODE* pLoc, void** dataOutPtr) { *dataOutPtr = pLoc->dataPtr; if (pPre == NULL) pList->head = pLoc->link; else pPre->link = pLoc->link; if (pLoc->link == NULL) pList->rear = pPre; (pList->count)--; free (pLoc); return; } 2 1 rear Data Structure

  34. 3. List ADT • searchList bool searchList (LIST* pList, void* pArgu, void** pDataOut) { bool found; NODE* pPre; NODE* pLoc; found = _search (pList, &pPre, &pLoc, pArgu); if (found) *pDataOut = pLoc->dataPtr; else *pDataOut = NULL; return found; } 검색하고자 하는 노드의 데이터값 _search() 이후에검색된 노드의 데이터 값이 할당됨 Data Structure

  35. 3. List ADT • retrieveNode • 앞의 searchList와 그 기능이 동일함 • 함수선언 앞에 static이 있어서 내부 함수로서만 사용할 목적을 지님 static bool retrieveNode (LIST* pList, void* pArgu, void** dataOutPtr) { bool found; NODE* pPre; NODE* pLoc; found = _search (pList, &pPre, &pLoc, pArgu); if (found) { *dataOutPtr = pLoc->dataPtr; return true; } *dataOutPtr = NULL; return false; } 검색하고자 하는 노드의 데이터값 _search() 이후에검색된 노드의 데이터 값이 할당됨 Data Structure

  36. 3. List ADT • emptyList • fullList • listCount bool emptyList (LIST* pList) { return (pList->count == 0); } bool fullList (LIST* pList) { NODE* temp; if ((temp = (NODE*)malloc(sizeof(*(pList->head))))) { free (temp); return false; } return true; } int listCount(LIST* pList) { return pList->count; } Data Structure

  37. 3. List ADT • traverseList • fromWhere: 0 to start at the first element bool traverse (LIST* pList, int fromWhere, void** dataPtrOut) { if (pList->count == 0) return false; if (fromWhere == 0) { pList->pos = pList->head; *dataPtrOut = pList->pos->dataPtr; return true; } else { if (pList->pos->link == NULL) return false; else { pList->pos = pList->pos->link; *dataPtrOut = pList->pos->dataPtr; return true; } } } traverse() 함수는 한번 불리워질 때마다 현재 리턴하는 값을 지닌 노드 포인터를pList->pos에 저장을 해 둔다. 그래서, 다음 번 traverse()를 부를 때에는 이미 pList->pos는 바로 직전에 리턴받은 노드의 포인터를 가지고 있다. 즉, traverse() 함수는 main()에서 for나 wile 루프속에서 사용하여 전체 노드의 값들을 가져올 때 유용하게 사용할 수 있다. Data Structure

  38. 3. List ADT • traverseList • int traverseList(List *pList, int fromWhere, void** dataPtrOut); • pList: an ordered list • fromWhere: if fromWhere == 0 • pList->pos = pList->head (pos 포인터의 초기화) • return first data • dataPtrOut: an address to receive the next data • Return value: TRUE if next node exists, otherwise, FALSE • Usecase) Printing all data using traverseList operation int n = 0; // current index int* data; bool ret; do { ret = traverseList(pList, n++, (void**)&data); if(ret) printf("%d ", *data); } while(ret); Data Structure

  39. 3. List ADT • destroyList LIST* destroyList (LIST* pList) { NODE* deletePtr; if (pList) { while (pList->count > 0) { free (pList->head->dataPtr); deletePtr = pList->head; pList->head = pList->head->link; pList->count--; free (deletePtr); } free (pList); } return NULL; } Data Structure

  40. 참고. 배열과 연결 리스트 비교 • Linked List (연결 리스트) • It consists of a sequence of nodes,each containing arbitrary data fieldsand one or two references ("links") pointing to the next and/or previousnodes. • A linked list is a self-referential datatype because it contains a pointer or link to another data of the same type. D C E A • 메모리 안에서의 노드의 물리적 순서가 리스트의 논리적 순서와 일치할 필요 없음 B 메인 메모리 Data Structure

  41. 참고. 배열과 연결 리스트 비교 • (General) List • a list in which operations, such as retrievals, insertions, changes, and deletions, can be done anywhere in the list • 일상 생활에서의 예 • Listsof employees • Student lists • Lists of our favorite songs • List의 실제 구현시선택 방법 • 방법 1) 배열 • 방법 2) 연결 리스트 Data Structure

  42. 참고. 배열과 연결 리스트 비교 • 배열 vs. 연결 리스트 • 배열  메모리에 데이터가 일렬로 붙어 있음을 의미 • 연결 리스트  메모리에 떨어져 있지만 포인터에 의해 연결되어 있음을 의미 • 배열 (선형 자료구조)이 코딩이 더 쉬움? • 포인터 활용이 어려운사람의 주관적이 견해일 뿐 • 공간적인 면에서 비교 • 배열은 정적이므로 최대크기를 미리 예상해야 함. • 만들어 놓은 배열 공간이 실제로 쓰이지 않으면 낭비 • 연결 리스트는 실행 시 필요에 따라 새로운 노드 생성 공간 절약 • 연결 리스트는 포인터 변수공간을 요함. 하지만 데이터가 차지하는 공간에 비해서는 상대적으로 미미함 Data Structure

  43. 0 1 2 3 4 5 A B C D E C A B D E A B D E A B D E 참고. 배열과 연결 리스트 비교 • 배열을 활용한 삽입연산 & 삭제연산 N 0 1 2 3 4 5 A B C D E A B C D E A B C D E A B C D E A B N C D E Data Structure

  44. 참고. 배열과 연결 리스트 비교 • 검색시간의 비교 • 배열은 단번에 찾아감 • Implicit (묵시적)Addressing: 인덱스 연산 • 연결 리스트는 헤드부터 포인터를 따라감 • Explicit (현시적, 명시적)Addressing: 포인터 읽음 • 검색 시간면에서는 배열이 유리 • 삽입, 삭제 시간의 비교 • 배열의 삽입: 오른쪽 밀림(Shift Right) • 배열의 삭제: 왼쪽 밀림(Shift Left) • 연결 리스트: 인접 노드의 포인터만 변경 • 삽입, 삭제 시간 면에서는 연결 리스트가 유리 • 어떤 자료구조? • 검색위주이면 배열이 유리 • 삽입 삭제 위주라면 연결 리스트가 유리 • 최대 데이터 수가 예측 불가라면 연결 리스트 • 하지만, 일반적으로 대부분의 경우 연결 리스트를 활용한다. Data Structure

More Related