Bài giảng Cấu trúc dữ liệu và Giải thuật - Chương 3: Danh Sách Liên Kết - Nguyễn Hà Giang

1. Danh sách liên kết đơn (Singly Linked List)  Giới thiệu  Cài đặt  Thao tác  Ứng dụng 2. Danh sách vòng (Circular Linked List) 3. Danh sách liên kết kép (Doubly Linked List)

pdf91 trang | Chia sẻ: candy98 | Lượt xem: 974 | Lượt tải: 1download
Bạn đang xem trước 20 trang tài liệu Bài giảng Cấu trúc dữ liệu và Giải thuật - Chương 3: Danh Sách Liên Kết - Nguyễn Hà Giang, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
Danh Sách Liên Kết - Linked List ThS. Nguyễn Hà Giang Khoa CNTT - Hutech Nguyen Ha Giang - 20082 Nội dung  Danh sách liên kết đơn  Giới thiệu  Cài đặt  Thao tác  Ứng dụng  Danh sách vòng  Danh sách liên kết kép Nguyen Ha Giang - 20083 Singly Linked List - Giới thiệu  Mảng 1 chiều  Kích thước cố định (fixed size)  Chèn 1 phần tử vào mảng rất khó  Các phần tử tuần tự theo chỉ số 0  n-1  Truy cập ngẫu nhiên (random access) 0 1 2 3 4 n-2 n-1 chèn Nguyen Ha Giang - 20084 Singly Linked List - Giới thiệu  Danh sách liên kết  Cấp phát động lúc chạy chương trình  Các phần tử nằm rải rác ở nhiều nơi trong bộ nhớ  Kích thước danh sách chỉ bị giới hạn do RAM  Thao tác thêm xoá đơn giản Insert, Delete Nguyen Ha Giang - 20085 Singly Linked List - định nghĩa  DSLK đơn là chuỗi các node, được tổ chức theo thứ tự tuyến tính  Mỗi node gồm 2 phần:  Phần Data, information  Phần link hay con trỏ trỏ đến node kế tiếp Data Link Node Nguyen Ha Giang - 20086 Singly Linked List – Ôn pointer  Nhắc lại pointer int i, *pi; i 1FF0 ? pi 1FF4 ? pi = &i; pi 1FF4 1FF0 i 1FF0 ?*pi i = 10 hoặc *pi = 10 pi 1FF4 1FF0 i 1FF0 10*pi Nguyen Ha Giang - 20087 Singly Linked List – Minh hoạ  Mô tả DSLK A1 A2 A3 An Header Node Node Tail Node null Data Link Nguyen Ha Giang - 20088 Singly Linked List – Minh họa  VD: ‘D’ 500 ‘S’ 600 ‘L’ 300 ‘D’ null 700 700 500 600 300 Địa chỉ pHead Nguyen Ha Giang - 20089 Singly Linked List – Khai báo phần data  Khai báo DSLK - DataType  Kiểu dữ liệu định nghĩa trước  Chứa dữ liệu, thông tin của từng node typedef int DataType; typedef char DataType; typedef struct{ char Ten[30]; char MaSo[10]; DateTime NgaySinh; char Khoa[10]; }SinhVien; typedef SinhVien DataType; Nguyen Ha Giang - 200810 Singly Linked List – Khai báo phần Data typedef struct node { DataType info; struct node * next; }NODE; typedef struct node { int info; struct node * next; }NODE; typedef struct node { SinhVien info; struct node * next; }NODE; Cấu trúc node Nguyen Ha Giang - 200811 Singly Linked List – Khai báo DSLK  Khai báo và khởi tạo typedef struct node { DataType info; struct node * next; }NODE; typedef NODE * NodePtr; NodePtr pHead; pHead = NULL; pHead quản lý ds Khởi tạo dslk Nguyen Ha Giang - 200812 Singly Linked List – Thao tác cơ bản  Các thao tác cơ bản  Init  IsEmpty  FreeNode  NewNode  ShowList  InsertFirst  InsertAfter  DeleteFirst  DeleteAfter  Search  Sort Phần minh hoạ sẽ dùng DataType là int Nguyen Ha Giang - 200813 Singly Linked List – thao tác khởi tạo  Init: khởi động danh sách, ban đầu chưa có phần tử  NewNode: cấp phát một node cho ds, trả về địa chỉ node vừa cấp phát void Init(NodePtr *pHead) { *pHead = NULL; } NodePtr NewNode() { NodePtr newnode; newnode = (NodePtr) malloc(sizeof(NODE)); return newnode; } Nguyen Ha Giang - 200814 Singly Linked List- giải phóng node  FreeNode: giải phóng vùng nhớ cấp phát cho node  IsEmpty: kiểm tra danh sách rỗng void FreeNode(NodePtr p) { free(p); } int IsEmpty(NodePtr pHead) { return (pHead==NULL)? TRUE:FALSE; } Nguyen Ha Giang - 200815 Singly Linked List – In danh sách  ShowList: in toàn bộ danh sách void ShowList(NodePtr pHead) { NodePtr p; p = pHead; while (p!=NULL) { ShowNode(p); p = p->next; } } Nguyen Ha Giang - 200816 Singly Linked List – Minh họa in danh sách p = pHead; while (p!=NULL) { ShowNode(p); p = p->next; } 3000 “Tran” 5000 “Ngoc” 4000 “Thao” NULL 3000 5000 4000pHead p Nguyen Ha Giang - 200817 Singly Linked List – Minh họa in danh sách p = pHead; while (p!=NULL) { ShowNode(p); p = p->next; } 3000 “Tran” 5000 “Ngoc” 4000 “Thao” NULL 3000 5000 4000 3000 pHead p Nguyen Ha Giang - 200818 Singly Linked List – Minh họa in danh sách p = pHead; while (p!=NULL) { ShowNode(p); p = p->next; } 3000 “Tran” 5000 “Ngoc” 4000 “Thao” NULL 3000 5000 4000 3000 pHead p Nguyen Ha Giang - 200819 Singly Linked List – Minh họa in danh sách p = pHead; while (p!=NULL) { ShowNode(p); p = p->next; } 3000 “Tran” 5000 “Ngoc” 4000 “Thao” NULL 3000 5000 4000 3000 pHead p Nguyen Ha Giang - 200820 Singly Linked List – Minh họa in danh sách p = pHead; while (p!=NULL) { ShowNode(p); p = p->next; } 3000 “Tran” 5000 “Ngoc” 4000 “Thao” NULL 3000 5000 4000 5000 pHead p Nguyen Ha Giang - 200821 Singly Linked List – Minh họa in danh sách p = pHead; while (p!=NULL) { ShowNode(p); p = p->next; } 3000 “Tran” 5000 “Ngoc” 4000 “Thao” NULL 3000 5000 4000 5000 pHead p Nguyen Ha Giang - 200822 Singly Linked List – Minh họa in danh sách p = pHead; while (p!=NULL) { ShowNode(p); p = p->next; } 3000 “Tran” 5000 “Ngoc” 4000 “Thao” NULL 3000 5000 4000 5000 pHead p Nguyen Ha Giang - 200823 Singly Linked List – Minh họa in danh sách p = pHead; while (p!=NULL) { ShowNode(p); p = p->next; } 3000 “Tran” 5000 “Ngoc” 4000 “Thao” NULL 3000 5000 4000 4000 pHead p Nguyen Ha Giang - 200824 Singly Linked List – Minh họa in danh sách p = pHead; while (p!=NULL) { ShowNode(p); p = p->next; } 3000 “Tran” 5000 “Ngoc” 4000 “Thao” NULL 3000 5000 4000 4000 pHead p Nguyen Ha Giang - 200825 Singly Linked List – Minh họa in danh sách p = pHead; while (p!=NULL) { ShowNode(p); p = p->next; } 3000 “Tran” 5000 “Ngoc” 4000 “Thao” NULL 3000 5000 4000 4000 pHead p Nguyen Ha Giang - 200826 Singly Linked List – Minh họa in danh sách p = pHead; while (p!=NULL) { ShowNode(p); p = p->next; } 3000 “Tran” 5000 “Ngoc” 4000 “Thao” NULL 3000 5000 4000 NULL pHead p Nguyen Ha Giang - 200827 Singly Linked List – Minh họa in danh sách p = pHead; while (p!=NULL) { ShowNode(p); p = p->next; } 3000 “Tran” 5000 “Ngoc” 4000 “Thao” NULL 3000 5000 4000 NULL pHead p Kết thúc Nguyen Ha Giang - 200828 Singly Linked List – thêm vào đầu  Thêm vào đầu danh sách pHead pHead newnode new pHead newnode pHead newnode Nguyen Ha Giang - 200829 Singly Linked List – thêm vào đầu  InsertFirst: thêm nút có nội dung x vào đầu ds void InsertFirst(NodePtr &pHead, int x) { NodePtr node; node = NewNode(); node->info = x; node->next = pHead; pHead = node; } Nguyen Ha Giang - 200830 Singly Linked List – thêm vào sau 1 phần tử  Thêm vào sau node p trong danh sách p p newnode new p newnode p newnode Nguyen Ha Giang - 200831 Singly Linked List – thêm vào sau 1 phần tử  InsertAfter: thêm node có nội dung x sau node p void InsertAfter(NodePtr &p, int x) { NodePtr node; if (p == NULL) printf(“Cannot insert new node!”); else { node = NewNode(); node->info = x; node->next = p->next; p->next = node; } } Nguyen Ha Giang - 200832 Singly Linked List – Xoá phần tử đầu  Xoá phần tử đầu danh sách pHead pHead pHead pHead Nguyen Ha Giang - 200833 Singly Linked List – Xoá phần tử đầu  DeleteFirst: xóa node đầu tiên của danh sách void DeleteFirst(NodePtr &pHead) { NodePtr p; if (IsEmpty(pHead)) printf(“List is empty!”); else { p = pHead; pHead = pHead->next; FreeNode(p); } } Nguyen Ha Giang - 200834 Singly Linked List – Xoá phần tử sau 1 node  Xoá phần tử sau node p trong danh sách p q qp p Nguyen Ha Giang - 200835 Singly Linked List – Xoá phần tử sau 1 node  DeleteAfter: xoá node sau node p trong danh sách void DeleteAfter(NodePtr &p) { NodePtr q; if (p->next ==NULL) printf(“Cannot delete node!”); else { q = p->next; p->next = q->next; FreeNode(q); } } Nguyen Ha Giang - 200836 Singly Linked List – Xoá toàn bộ danh sách  Xoá toàn bộ danh sách pHead p pHead p Nguyen Ha Giang - 200837 Singly Linked List – Xoá toàn bộ danh sách pHead p pHead p Nguyen Ha Giang - 200838 Singly Linked List – Xoá toàn bộ danh sách pHead p pHead p Nguyen Ha Giang - 200839 Singly Linked List – Xoá toàn bộ danh sách pHead p pHead p pHead p pHead p Nguyen Ha Giang - 200840 Singly Linked List – Xoá toàn bộ danh sách  DeleteAll: xoá toàn bộ danh sách void DeleteAll(NodePtr &pHead) { NodePtr p; while (pHead!=NULL) { p = pHead; pHead = p->next; FreeNode(p); } } Nguyen Ha Giang - 200841 Singly Linked List – Tìm kiếm  Search: Tìm kiếm phần tử x trong danh sách NodePtr Search(NodePtr pHead, int x) { NodePtr p; p = pHead; while ( p != NULL && p->info != x) p = p->next; return p; } Nguyen Ha Giang - 200842 Singly Linked List - Sắp xếp  Sắp xếp ds theo thứ tự tăng dần, dùng Selection Sort void Sort(NodePtr &pHead) { NodePtr q, min, p = pHead; while (p!=NULL) { min = p; q = p; while (q!=NULL) { if (q->info info) min = q; q = q->next; } Swap(p->info, min->info); p = p->next; } } Nguyen Ha Giang - 200843 Singly Linked List – Bài tập bổ sung  Các thao tác bổ sung (SV cài đặt) 1. Thêm vào cuối danh sách 2. Sắp xếp danh sách theo phương pháp Interchange Sort 3. Xoá 1 phần tử có khoá là x 4. Thêm phần tử x vào ds đã có thứ tự (tăng) sao cho sau khi thêm vẫn có thứ tự (tăng). 5. Xoá các phần tử trùng nhau trong danh sách, chỉ giữ lại duy nhất một phần tử (*) 6. Trộn hai danh sách có thứ tự tăng thành một danh sách cũng có thứ tự tăng. (*) 7. Xác định vị trí của node x trong danh sách 8. Xác định kích thước của danh sách (số phần tử) 9. Chèn một phần tử có khoá x vào vị trí pos trong ds Nguyen Ha Giang - 200844 Nguyen Ha Giang - 200845 Circular Linked List  Tương tự như danh sách liên kết đơn.  Trường next của nút cuối chỉ đến đầu danh sách A1 A2 A3 An Trường Next của nút cuối ko còn trỏ đến NULL, mà trỏ đến nút đầu Nguyen Ha Giang - 200846 Circular Linked List  Mô tả CLL  Sử dụng pList trỏ đến phần tử cuối của danh sách A1 A2 A3 An Node Tail Node pList Nguyen Ha Giang - 200847 Circular Linked List  Khai báo & khởi tạo typedef struct node { DataType info; struct node * next; }NODE; typedef NODE * NodePtr; NodePtr pList; pList = NULL; pList trỏ nút cuối ds Khởi tạo dslk Nguyen Ha Giang - 200848 Circular Linked List  Các thao tác  InsertFirst  InsertLast  DeleteFirst  DeleteLast  ShowList  Search Nguyen Ha Giang - 200849 Circular Linked List  Chèn vào đầu – pList = NULL pList newnode new pList newnode pList newnode pList Nguyen Ha Giang - 200850 Circular Linked List  Chèn vào đầu – pList ≠ NULL pList pList newnode new pList newnode pList newnode Nguyen Ha Giang - 200851 Circular Linked List void InsertFirst(NodePtr &pList, int x) { NodePtr newNode; newNode = NewNode(); newNode->Info = x; if (pList == NULL){ pList = newNode; pList->next = pList } else { newNode->next = pList->next; pList->next = newNode; } } Nguyen Ha Giang - 200852 Circular Linked List  InsertLast: pList = NULL pList newnode new pList newnode pList newnode pList Nguyen Ha Giang - 200853 Circular Linked List  InsertLast: pList ≠ NULL pList pList newnode new pList newnode pList newnode Nguyen Ha Giang - 200854 Circular Linked List void InsertLast(NodePtr &pList, int x) { NodePtr newNode; newNode = NewNode(); newNode->Info = x; if (pList == NULL){ pList = newNode; pList->next = pList; } else { newNode->next = pList->next; pList->next = newNode; pList = newNode; } } Nguyen Ha Giang - 200855 Circular Linked List  DeleteFirst: pList->next = pList pList pList Nguyen Ha Giang - 200856 Circular Linked List  DeleteFirst: pList->next ≠ pList pList pList p pList p pList p Nguyen Ha Giang - 200857 Circular Linked List void DeleteFirst(NodePtr &pList) { NodePtr p; if (pList == NULL) return; else if (pList == pList->next) { FreeNode(pList); pList = NULL; } else { p = pList->next; pList->next = p->next; FreeNode(p); } } Nguyen Ha Giang - 200858 Circular Linked List  DeleteLast: pList->next = pList pList pList Nguyen Ha Giang - 200859 Circular Linked List  DeleteLast: pList->next ≠ pList pList pListq p pListq p pListq p Nguyen Ha Giang - 200860 Circular Linked List void DeleteLast(NodePtr &pList) { } Nguyen Ha Giang - 200861 Circular Linked List  ShowList:  Duyệt từ đầu danh sách  Đến khi nào quay lại phần tử đầu thì dừng void ShowList(NodePtr pList) { NodePtr p; if (pList == NULL ) return; p = pList->next; do { ShowNode(p); p = p->next; } while (p!=pList->next); } Nguyen Ha Giang - 200862 Circular Linked List 1000 “Tran” 5000 “Ngoc” 1000 “Thao” 8000 8000 5000 1000 pList p p = pList->next; do { ShowNode(p); p = p->next; } while (p != pList->next); Nguyen Ha Giang - 200863 Circular Linked List p = pList->next; do { ShowNode(p); p = p->next; } while (p != pList->next); 1000 “Tran” 5000 “Ngoc” 1000 “Thao” 8000 8000 5000 1000 8000 pList p Nguyen Ha Giang - 200864 Circular Linked List p = pList->next; do { ShowNode(p); p = p->next; } while (p != pList->next); 1000 “Tran” 5000 “Ngoc” 1000 “Thao” 8000 8000 5000 1000 8000 pList p Nguyen Ha Giang - 200865 Circular Linked List p = pList->next; do { ShowNode(p); p = p->next; } while (p != pList->next); 1000 “Tran” 5000 “Ngoc” 1000 “Thao” 8000 8000 5000 1000 8000 pList p “Tran” Nguyen Ha Giang - 200866 Circular Linked List p = pList->next; do { ShowNode(p); p = p->next; } while (p != pList->next); 1000 “Tran” 5000 “Ngoc” 1000 “Thao” 8000 8000 5000 1000 5000 pList p “Tran” Nguyen Ha Giang - 200867 Circular Linked List p = pList->next; do { ShowNode(p); p = p->next; } while (p != pList->next); 1000 “Tran” 5000 “Ngoc” 1000 “Thao” 8000 8000 5000 1000 5000 pList p “Tran” true Nguyen Ha Giang - 200868 Circular Linked List p = pList->next; do { ShowNode(p); p = p->next; } while (p != pList->next); 1000 “Tran” 5000 “Ngoc” 1000 “Thao” 8000 8000 5000 1000 5000 pList p Tran Ngoc Nguyen Ha Giang - 200869 Circular Linked List p = pList->next; do { ShowNode(p); p = p->next; } while (p != pList->next); 1000 “Tran” 5000 “Ngoc” 1000 “Thao” 8000 8000 5000 1000 1000 pList p Tran Ngoc Nguyen Ha Giang - 200870 Circular Linked List p = pList->next; do { ShowNode(p); p = p->next; } while (p != pList->next); 1000 “Tran” 5000 “Ngoc” 1000 “Thao” 8000 8000 5000 1000 1000 pList p Tran Ngoc true Nguyen Ha Giang - 200871 Circular Linked List p = pList->next; do { ShowNode(p); p = p->next; } while (p != pList->next); 1000 “Tran” 5000 “Ngoc” 1000 “Thao” 8000 8000 5000 1000 1000 pList p Tran Ngoc Thao Nguyen Ha Giang - 200872 Circular Linked List p = pList->next; do { ShowNode(p); p = p->next; } while (p != pList->next); 1000 “Tran” 5000 “Ngoc” 1000 “Thao” 8000 8000 5000 1000 8000 pList p Tran Ngoc Thao Nguyen Ha Giang - 200873 Circular Linked List p = pList->next; do { ShowNode(p); p = p->next; } while (p != pList->next); 1000 “Tran” 5000 “Ngoc” 1000 “Thao” 8000 8000 5000 1000 8000 pList p Tran Ngoc Thao false Nguyen Ha Giang - 200874 Circular Linked List  Search:  Xuất phát từ đầu danh sách  Nếu tìm thấy trả về địa chỉ nút đó  Ngược lại qua phần tử tiếp theo  Điều kiện dừng khi quay lại phần tử đầu tiên  Không tìm thấy trả về NULL Nguyen Ha Giang - 200875 Circular Linked List NodePtr Search(NodePtr pList, int x) { NodePtr p; if (pList ==NULL) return NULL; p = pList->next; while (p->info != x && p != pList->next) p = p->next; if ( p->info == x) return p; return NULL; } Nguyen Ha Giang - 200876 Circular Linked List  Nối danh sách vòng pList2 vào pList 1 pList1 pList2 Nguyen Ha Giang - 200877 Circular Linked List  Nối danh sách vòng pList2 vào pList 1 pList1 pList2 pHead Nguyen Ha Giang - 200878 Circular Linked List  Nối danh sách vòng pList2 vào pList 1 pList1 pList2 pHead Nguyen Ha Giang - 200879 Circular Linked List  Nối danh sách vòng pList2 vào pList 1 pList1pList2 pHead Nguyen Ha Giang - 200880 Circular Linked List void AddList(NodePtr &pList1, NodePtr &pList2) { } Nguyen Ha Giang - 200881 Nguyen Ha Giang - 200882 Doubly Linked List  Cho phép di chuyển 2 chiều đến nút trước và sau.  Liên kết nút trước là: prev  Liên kết nút sau là: next  Nút đầu có prev là NULL  Nút cuối có next là NULL A1 A2 An Nguyen Ha Giang - 200883 Doubly Linked List  Khai báo typedef struct node { DataType info; struct node * prev; struct node * next; }NODE; typedef NODE * NodePtr; NodePtr pHead; pHead = NULL; pHead quản lý ds kép Khởi tạo dslk trỏ đến nút trước trỏ đến nút sau Nguyen Ha Giang - 200884 Doubly Linked List  Các thao tác cơ bản  NewNode, FreeNode, Init, IsEmpty  InsertFirst: chèn vào đầu  InsertPrev: chèn trước nút p  InsertNext: chèn sau nút p  DeleteFirst: xoá nút đầu  DeleteNode: xóa nút p  ShowList: duyệt ds  ShowReverse: duyệt từ cuối danh sách  ClearList: xoá toàn bộ ds Nguyen Ha Giang - 200885 Doubly Linked List  InsertPrev: chèn vào trước nút p p p newnewnode Nguyen Ha Giang - 200886 Doubly Linked List p newnode p Nguyen Ha Giang - 200887 Doubly Linked List void InsertPrev(NodePtr &pHead, NodePtr &p, int x){ NodePtr newnode, left; if (p == NULL) return; if (p ==pHead) InsertFirst(pHead,x); else { newnode = NewNode(); newnode->info = x; left = p->prev; newnode->prev = left; left->next = newnode; newnode->next = p; p->prev = newnode; } Nguyen Ha Giang - 200888 Doubly Linked List  DeleteNode: xoá nút p p p Nguyen Ha Giang - 200889 Doubly Linked List void DeleteNode(NodePtr &pHead, NodePtr &p) { NodePtr left, right; if (p == NULL) return; if (p==pHead) DeleteFirst(pHead); else { left = p ->prev; right = p->next; left->next = right; if (right != NULL) right->prev = left; FreeNode(p); } } Nguyen Ha Giang - 200890 Doubly Linked List  Các thao tác còn lại SV tự làm! Nguyen Ha Giang - 200891 Bài tập  Xây dựng cấu trúc danh sách liên kết đôi vòng  Mỗi nút trên danh sách có hai trường liên kết  Prev: trỏ đến nút trước  Next: trỏ đến nút sau  Nút cuối cùng trong danh sách có trường next là nút đầu tiên  Nút đầu tiên có trường prev là nút cuối cùng.  Các thao tác trên danh sách:  Init, IsEmpty, NewNode, FreeNode  InsertFrist, InsertLast, InsertPrev, InsertNext, InsertPos  DeleteFirst, DeleteLast, DeleteNext, DeletePrev, DeletePos  ShowList, ShowInvert  Search, Sort.  ClearList