You are on page 1of 30

SEMINAR

CẤU TRÚC DỮ LIỆU


next

LIST TRONG C++ elem node

trailer
header node
NULL

elem

NGUYỄN VIỆT HƯNG


Kiểu dữ liệu trừu tượng LIST (LIST ADT)
❖ Mô hình cấu trúc dữ liệu trừu tượng Linked List là một dãy các vị trí
lữu trữ các đối tượng với số lượng tùy ý.
❖ Nó thiết lập một mối quan hệ trước/sau giữa các vị trí

❖ Danh sách liên kết đơn (Singly Linked List)


❖ Danh sách liên kết kép (Doubly Linked List)
Cấu trúc của một Node
Các thuộc tính
 Element elem;
 Node *next;
Các phương thức
 Node *getnext() - Trả lại địa chỉ của nút kế tiếp
 Element getElem() - Trả lại giá trị phần tử lưu trữ trong nút
 void setNext(Node *) - Gán địa chỉ cho thuộc tính next
 void setElem(Element e) - Gán giá trị e cho thuộc tính elem
Các thao tác chính trên Danh sách liên kết đơn
Singly Linked List
❑ Cấu trúc dữ liệu List trong thư việc STL của C++ cung cấp 3 nhóm tính năng chính:
❖ Modifiers (Thêm, sửa, xóa các phần tử)
❖ Element access (truy cập các phần tử)
❖ Iterators (Duyệt các phần tử)
❖ Capacity (Kích thước lưu trữ)

Modifiers Element access Iterators Capacity


1.push_front() 1.front() 1.begin() 1.size()
2.pop_front() 2.back() 2.end() 2.empty()
3.push_back()
4.pop_back()
5.insert()
6.erase()
7.clear()
Mô tả DSLK Đơn - Singly linker list
front() insert() push_back()
push_front()

trail=600
Elem=40 Elem=50 Elem=70 Elem=10
Address: 900
head=300
next=500 next=400 next=600 next=NULL
Address: 100

Address: 300 Address: 500 Address: 400 Address: 600


NULL

pop_front() pop_back()
size() back()
erase()
begin()
end()
Push Front – Chèn 1 phần tử vào đầu danh sách
Hình ảnh phép toán push_front()

trailer
header

NULL
A B C
trailer
header

NULL

A B C
X q
trailer
header

NULL

X A B C
6
Push Back – Chèn 1 phần tử vào cuối danh sách
Hình ảnh phép toán push_back()
trailer
header

NULL

A B C
trailer
header
NULL

A B C NULL

X q
trailer
header

NULL

A B C X
Insert – Chèn 1 phần tử vào 1 vị trí trong danh sách
Hình ảnh phép toán insert(p, X)

trailer
header p
NULL

A B C
trailer
header
NULL

A B C
X
trailer
header

NULL

A B X C
erase – Xóa 1 phần tử khỏi danh sách
Hình ảnh phép toán erase(p)

header
p trailer

NULL

A B X C
trailer
header
p
A B C
X NULL

trailer
header

NULL

A B C
// list::push_front
#include <iostream>
#include <list>
using namespace std;
int main () {
list<int> mylist (2,100); // two ints with a value of 100
mylist.push_front (200); mylist.push_front (300);
cout << "mylist contains:";
for (list<int>::iterator it=mylist.begin(); it!=mylist.end();
++it) cout << ' ' << *it;
cout << '\n’;
return 0;
}
// list::pop_front
#include <iostream>
#include <list>
using namespace std;
int main () {
list<int> mylist;
mylist.push_back (100);
mylist.push_back (200);
mylist.push_back (300);
cout << "Popping out the elements in mylist:";
while (!mylist.empty()) {
cout << ' ' << mylist.front();
mylist.pop_front();
}
cout << "\nFinal size of mylist is " << mylist.size() << '\n’;
return 0;
}
// list::push_back
#include <iostream>
#include <list>
using namespace std;
int main () {
list<int> mylist;
int myint;
cout << "Please enter some integers (enter 0 to end):\n";
do
{ scin >> myint;
mylist.push_back (myint);
} while (myint);
cout << "mylist stores " << mylist.size() << " numbers.\n";
return 0;
}
// list::pop_back
#include <iostream>
#include <list>
using namespace std;
int main () {
list<int> mylist;
int sum (0);
mylist.push_back (100);
mylist.push_back (200);
mylist.push_back (300);
while (!mylist.empty()) {
sum+=mylist.back();
mylist.pop_back();
}
cout << "The elements of mylist summed " << sum << '\n’;
return 0; }
// inserting into a list
#include <iostream>
#include <list>
#include <vector>
using namespace std;
int main () {
list<int> mylist;
list<int>::iterator it;
// set some initial values:
for (int i=1; i<=5; ++i) mylist.push_back(i); // 1 2 3 4 5
it = mylist.begin();
++it; // it points now to number 2 ^
mylist.insert (it,10); // 1 10 2 3 4 5
// "it" still points to number 2 ^
mylist.insert (it,2,20); // 1 10 20 20 2 3 4 5
--it; // it points now to the second 20 ^
vector<int> myvector (2,30);
mylist.insert (it,myvector.begin(),myvector.end()); // 1 10 20 30 30 20 2 3 4 5 // ^
cout << "mylist contains:";
for (it=mylist.begin(); it!=mylist.end(); ++it)
cout << ' ' << *it;
cout << '\n’;
return 0; }
// erasing from list
#include <iostream>
#include <list>
int main () {
list<int> mylist
list<int>::iterator it1,it2;
// set some values: for (int i=1; i<10; ++i) mylist.push_back(i*10); // 10 20 30 40 50 60 70 80 90
it1 = it2 = mylist.begin();
++it1;
it1 = mylist.erase (it1); // 10 30 40 50 60 70 80 90
it2 = mylist.erase (it2); // 10 30 40 50 60 80 90
++it1;
--it2;
mylist.erase (it1,it2); // 10 30 60 80 90 // ^
cout << "mylist contains:";
for (it1=mylist.begin(); it1!=mylist.end(); ++it1)
cout << ' ' << *it1;
cout << '\n’;
return 0; }
// list::front
#include <iostream>
#include <list>
int main () {
list<int> mylist;
mylist.push_back(77);
mylist.push_back(22); // now front equals 77, and back 22
mylist.front() -= mylist.back();
cout << "mylist.front() is now " << mylist.front() << '\n’;
return 0; }
// list::back
#include <iostream>
#include <list> int main () {
list<int> mylist;
mylist.push_back(10);
while (mylist.back() != 0)
{
mylist.push_back ( mylist.back() -1 );
}
cout << "mylist contains:";
for (list<int>::iterator it=mylist.begin(); it!=mylist.end() ; ++it)
cout << ' ' << *it; std::cout << '\n’;
return 0; }
Bài tập
Xây dựng lớp ứng dụng sử dụng lớp Danh sách liên kết đơn để lưu trữ
1 danh sách sinh viên. Mỗi sinh viên gồm các thông tin sau: MaSv,
Hoten, Ngay, Thang, Nam sinh, gioi tinh, que quan.
Yêu cầu lớp có các chức năng sau:
-Thêm một sinh viên vào cuối DS
- Thêm một sinh viên vào đầu DS
- Xóa bỏ một sinh viên thu i khỏi DS
- Thay thế sinh viên thứ i bằng một sinh viên mới
Xây dựng chương trình để chạy lớp ứng dụng
Danh sách liên kết kép
Các nút (node) được cài đặt bao gồm: prev next
◼ Phần tử lưu trữ trong nó
◼ Một liên kết đến nút trước nó
◼ Một liên kết đến nút kế tiếp
Có hai nút đặc biệt là trailer và header elem n

header node NULL

NULL trailer

Elem
Mô tả DSLK Kép - Doubly linker list
front()
insert()

NULL

push_back()
push_front() prev prev=300 prev=500 Prev=400

trail=600
elem elem elem elem
Address: 900
head=300
next=500 next=400 next=600 next=NULL
Address: 100

Address: 300 Address: 500 Address: 400 Address: 600 NULL

pop_front() pop_back()
size() back()
erase()
begin()
end()
Insert First
Hình ảnh phép toán insertFirst(X), phép toán trả lại vị trí q
header trailer

A B C
header trailer

q A B C

X
header q p trailer

X A B C
Insert Last
Hình ảnh phép toán insertLast( X), phép toán trả lại vị trí q
header trailer

A B C
header trailer

A B C q

X
header q trailer

A B C X
Insert After
Hình ảnh phép toán insertAfter(p, X), phép toán trả lại vị trí q
p

A B C
p

A B q C

X
p q

A B X C
Thuật toán Insert After
Algorithm insertAfter(p,e): //Bổ sung phần tử e vào sau
phần tử nút p
Tạo ra một nút mới q
q->setElement(e) //Đặt gia trị e vào nút q
q->setNext(p->getNext())//liên kết với phần tử sau nó
p.getNext()->setPrev(q)//Liên kết phần tử sau p với q
q->setPrev(p) //liên kết q với phần tử trước nó
p->setNext(q) //liên kết p với q
return q //trả lại vị trí của q
Insert Before
Hình ảnh phép toán insertBefore(p, X), phép toán trả lại vị trí q
header p trailer

A B C
header p trailer

A q B C

X
header p q trailer

A X B C
Xóa - Remove
Hình ảnh minh họa phép toán remove(p), ở đây p = last()
header
p trailer

A B C D
header trailer

A B C p

D
header trailer

A B C
Thuật toán remove
Algorithm remove(Node *p):
//kết nối phần tử trước p với phần tử sau p
p->getPre()->setNext(p->getNext())
//kết nối phần tử sau p với pần tử trước p
p->getNext()->setPre(p->getPre())
//bỏ kết nối p với phần tử trước nó
p.setPre(NULL)
p.setNext(NULL)
delete p
So sánh mảng và danh sách liên
kết
Những đặc trưng của mảng Những đặc trưng của danh
sách liên kết
Bộ nhớ sử dụng lưu trữ phụ Bộ nhớ sử dụng để lưu trữ
thuộc vào việc cài đặt chứ tương ứng với số lượng các
không phải số lượng thực sự phần tử thực sự cần lưu tai bất
cần lưu. kỳ thời điểm nào.
Mối quan hệ giữa phần tử đầu Sử dụng một con trỏ để lưu
và các phần tử khác là rất ít phần tử đầu, từ đó đi đến các
phần tử khác.
Các phần tử được sắp xếp cho
phép tìm kiếm rất nhanh Việc bổ sung và xóa bỏ các
phần tử không phải di chuyển
Việc chèn và xóa phần tử đòi các phần tử
hỏi phải di chuyển các phần tử.
Truy nhập đến các phần tử chỉ
có thể thực hiện được bằng
cách đi dọc theo chuỗi mắt xích
từ phần tử đầu. Vì vậy đối với
danh sách liên kết đơn thì thời
gian tìm kiếm một phần tử sẽ là
O(n).
Bài tập
- Xây dựng lớp Node
- Xây dựng lớp DblList
- Xây dựng lớp DblItr //Lớp bộ lặp
- Xây dựng lớp ứng dụng sử dụng lớp Danh sách liên kết kép để
lưu trữ 1 danh sách sinh viên. Mỗi sinh viên gồm các thông tin
sau: MaSv, Hoten, Ngay, Thang, Nam sinh, gioi tinh, que quan.

Yêu cầu lớp có các các chức năng sau:


- Thêm một sinh viên vào cuối DS
- Thêm một sinh viên vào đầu DS
- Xóa bỏ sinh viên thứ i khỏi DS
- Thay thế sinh viên thứ i bằng một sinh viên mới
Xây dựng chương trình để chạy lớp ứng dụng

You might also like