Presentation is loading. Please wait.

Presentation is loading. Please wait.

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

Similar presentations


Presentation on theme: "Chapter 5. General Linear List Internet Computing KUT Youn-Hee Han."— Presentation transcript:

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

2 Data Structure2 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 Lists of our favorite songs PositionNameQuantity 1Beer10 2Gum5 3Apple4 4Potato8 5Onion8...

3 Data Structure3 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 에 대해 순서대로 일정한 작업 ( 예를 들어 단순 방문 ) 을 행한다. positionnamequantity 1Beer10 2Gum5 3Apple4...

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

5 Data Structure5 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

6 Data Structure6 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

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

8 Data Structure8 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()

9 Data Structure9 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;

10 Data Structure10 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); }

11 Data Structure11 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);

12 Data Structure12 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);

13 Data Structure13 3. List ADT List ADT functions

14 Data Structure14 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; } In main()… list = createList (cmpYear); 0

15 Data Structure15 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 를 가리키는 포인터

16 Data Structure16 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))

17 Data Structure17 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 node Return is True

18 Data Structure18 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

19 Data Structure19 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 node Return is True

20 Data Structure20 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 node Return is False

21 Data Structure21 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

22 Data Structure22 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=NULL Return is False

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

24 Data Structure24 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

25 Data Structure25 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; } 1) 2)

26 Data Structure26 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 2) 1) 3)

27 Data Structure27 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; } 1)2)

28 Data Structure28 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; } 1) 2) rear

29 Data Structure29 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() 이후에 삭제된 노드의 데이터 값이 할당됨

30 Data Structure30 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; }

31 Data Structure31 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

32 Data Structure32 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; }

33 Data Structure33 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; } rear 2 1

34 Data Structure34 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() 이후에 검색된 노드의 데이터 값이 할당됨

35 Data Structure35 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() 이후에 검색된 노드의 데이터 값이 할당됨

36 Data Structure36 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; }

37 Data Structure37 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 루프 속에서 사용하여 전체 노드의 값들을 가져올 때 유용하게 사용할 수 있다.

38 Data Structure38 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);

39 Data Structure39 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; }

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

41 Data Structure41 참고. 배열과 연결 리스트 비교 (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  Lists of our favorite songs List 의 실제 구현시 선택 방법  방법 1) 배열  방법 2) 연결 리스트

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

43 Data Structure43 참고. 배열과 연결 리스트 비교 배열을 활용한 삽입연산 & 삭제연산 ABCDE 01 2 34 5 ABC D E ABC DE ABNCDE ABCDE N ABCDE 012345 ABDE ABD E ABDE C

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


Download ppt "Chapter 5. General Linear List Internet Computing KUT Youn-Hee Han."

Similar presentations


Ads by Google