Linked List Lecturer : Kritawan Siriboon, Room no. 913 Text : Data Structures & Algorithm Analysis in C, C++,… Mark Allen Weiss, Addison Wesley
Lists head insert / delete tail คือรายการของของ ของในรายการมีลำดับ การเอาของเข้า/ออก ทำได้ทุกที่ head tail insert / delete Superset of stack & queue
Sequential (Implicit) Array Implementation Problem Logical List : ABCD Physical List insert : shift out B C D tail = 3 delete : shift in B C D
Solve Inserting Problem 3 2 ? Logical Linked List
Solve Deleting Problem 2 p 1
Dynamic Implementation
Address-of Operator & 8 Take the address of the operand. int i = 8; &i ให้ค่า 0013FF60 &i 0013FF60 8 i
Pointer Type Dereference (Indirection) Operator * Pointer keeps the address (instead of normal data). int i = 8; &i ให้ค่า 0013FF60 int *pi = &i; *operand : location that the operand points to *pi is i as long as pi keep &i &i 0013FF60 i 8 *pi 0013FF60 pi
Test1 by Drawing What Happen ? int x = 8; int y = 5; int *p, *q; p = &x; q = &y; *p = *q + x; p = q; What happen ?
Pointer to Dynamic heap location & new function new int จอง (allocates) heap memory ขนาด int และ returns ค่า address ของ memory ที่จองได้ หากจองไม่ได้จะ ruturn ค่า null Heap can only access through pointer ! main() { int i = 8; int *pi = &i; int *q = new int; *q = 5; } stack heap *q 5 q main() pi *pi i 8 What happen? q = &i; Danger! memory leak.
constant null delete function delete p คืน (deallocates) heap memory ที่ชี้โดย p เมื่อ p เป็นตัวแปร pointer เมื่อ delete p ไปแล้ว ไม่ควรเรียก *p เพราะค่าของมันอาจเปลี่ยนไป โดยมีการนำ heap ส่วนนั้นไปใช้อย่างอื่นแล้ว constant null เป็นค่าคงที่สำหรับ pointer ไม่ว่าจะชี้ไปที่ datatype ใด นิยมใช้เป็นค่าตั้งต้น (initialize) ของตัวแปร pointer เช่น char* p = 0; node* = 0; หรือ เป็นค่าปิดท้าย linked list
Test2 by Drawing What Happen ? int *p, *q; p = new int; *p = 8; q = p; cout << *p << *q; *p = 1; *q = *p; q = p; //or q = 0; what happen?
Dynamic Implementation : node & constructor template<class T> class node{ public: T data; node* next; }; template<class T> struct node{ T data; node* next; node(const T& d): data(d),next(0) { } }; node //constructor int main() { node<char> n('A'); n.data = 'B'; n.next = 0; } n A n.data n.next //What happen? node<char> n; n.data = 'A'; n.next = 0;
h template<class T> struct node{ T data; node* next; Dynamic Node template<class T> struct node{ T data; node* next; node(const T& d): data(d),next(0) { } }; node int main() { node<char>* h = new node<char>(‘A'); (*h).data = ‘B'; h->data = ‘C'; } h A B node<char>* h (*h).data (*h).next h->data h->next
Creating Linked List node<char> *h , *t, *p; h = new node<char>(‘A’); t = h; p = new node<char>(‘B’); t->next = p; t = p; Looping to add a new node to the tail. t *h A h B (*t).data (*t).next p t->data t->next
printlist(h) p A template<class T> void printlist(node<T> *p){ while (p) { cout << p->data << ' '; p = p->next; } cout << '\n';
Insert After ? q insertafter(q,d); 3 2 ? insertafter(q,d); node<char> *p = new node<char>(d); p->next = q->next; q->next = p;
node<char> *p = q->next; q->next = p->next; Deleting After q 2 p 1 deleteafter(q); node<char> *p = q->next; q->next = p->next; p->next = 0; return p;
Passing by Value k p 9 *p 8 x 3 i 8 3 5 3 k 8 3 int i = 5; int i = k; int *p = &k; void f() { int k = 8; sth(k); sth(5); Add1(&k); Ad1(k); } void sth(int i){ int x = 3; i = x; } void Add1(int *p){ (*p)++; } //pass data //pass address void Ad1(int& ref){ ref++; } //pass by reference k f( ) Add1( ) p 9 *p 8 x 3 3 sth( ) i 8 3 5 3 k f( ) 8
Pass Address & Passing by Reference int i = 5; int *p = &k; int i = k; void f() { int k = 8; sth(k); sth(5); Add1(&k); Ad1(k); } void sth(int i){ int x = 3; i = x; } void Add1(int *p){ (*p)++; } //pass data int& ref = k; //pass address void Ad1(int& ref){ ref++; } //pass by reference x 3 3 sth( ) i p 8 3 5 3 Add1( ) k f( ) 8 ref k 8 9 10 *p f( )
Passing Parameters Pass data by Value เมื่อไม่ต้องการเปลี่ยน data ใน caller Pass address by Value / Pass data by reference เมื่อต้องการเปลี่ยน data ใน caller Pass data by const & เมื่อไม่ต้องการเปลี่ยน data ใน caller คืออยากจะ pass data by value นั่นเอง แต่ data ที่จะ pass มีขนาดใหญ่ ไม่ต้องการคัดลอกให้เสียเวลา (กรณีเป็นออปเจคต้องเรียก copy constructor ด้วย ทำให้เสียเวลามาก)