Bài giảng Ngôn ngữ lập trình - Chương 3: Danh sách - Phạm Thanh An

Danh sách

Định nghĩa danh sách

Danh sách là dãy hữu hạn có thứ tự bao gồm một số biến động các phần tử thuộc cùng một lớp đối tượng nào đó.

Mô tả danh sách : L = (a1, a2, . . . ,an)

Danh sách tuyến tính: là danh sách mà quan hệ lân cận giữa các phần tử được hiển thị

Lưu trữ danh sách

Tổ chức lưu trữ danh sách trong bộ nhớ

Sử dụng mảng - Danh sách đặc

Đối tượng lớp - danh sách liên kết

Mỗi node là một đối tượng lớp

Các phép toán trên danh sách

Thêm

Loại bỏ

Sắp xếp:

Tìm kiếm

Tách

Ghép

Duyệt:

ppt 72 trang kimcuc 3360
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Ngôn ngữ lập trình - Chương 3: Danh sách - Phạm Thanh An", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

Tóm tắt nội dung tài liệu: Bài giảng Ngôn ngữ lập trình - Chương 3: Danh sách - Phạm Thanh An

Bài giảng Ngôn ngữ lập trình - Chương 3: Danh sách - Phạm Thanh An
Ths. Phạm Thanh An 
Bộ môn Khoa học máy tính - Khoa CNTT 
Trường Đại học Ngân hàng TP.HCM 
Chương 3 DANH SÁCH 
Nội dung trình bày 
Danh sách và các phép toán trên danh sách 
Danh sách đặc 
Định nghĩa, Cách biểu diễn và các phép toán 
Ưu và nhược điểm của danh sách đặc 
Tổ chức Stack và Queue theo kiểu danh sách đặc 
Danh sách liên kết 
Khái niệm , Biểu diễn, Các phép toán 
Ưu và nhược điểm 
Tổ chức Stack và Queue theo kiểu danh sách liên kết 
Danh sách liên kết kép 
Danh sách 
Định nghĩa danh sách 
Danh sách là dãy hữu hạn có thứ tự bao gồm một số biến động các phần tử thuộc cùng một lớp đối tượng nào đó. 
Mô tả danh sách : L = (a 1 , a 2 , . . . ,a n ) 
Danh sách tuyến tính: là danh sách mà quan hệ lân cận giữa các phần tử được hiển thị 
Lưu trữ danh sách 
Tổ chức lưu trữ danh sách trong bộ nhớ 
Sử dụng mảng - Danh sách đặc 
Đối tượng lớp - danh sách liên kết 
Mỗi node là một đối tượng lớp 
Các phép toán trên danh sách 
Thêm 
Loại bỏ 
Sắp xếp: 
Tìm kiếm 
Tách 
Ghép 
Duyệt: 
Danh sách đặc (condensed list) 
Định nghĩa 
Là danh sách có các phần tử được xếp kế tiếp nhau trong bộ nhớ 
Đặc điểm 
d: chiều dài mỗi phần tử trong danh sách 
l 0 : địa chỉ của phần tử đầu tiên 
 địa chỉ của phần tử thứ i là: l i =l 0 +(i-1)d 
a 1 
 a 2 
a 3 
. 
a n-1 
a n 
Danh sách đặc (condensed list) 
Ưu điểm 
Nhược điểm 
Mảng danh sách đặc phổ biến 
Mảng một chiều a[ ] 
Khai báo: 
Cách 1: [] tên_mảng; 
Tên_mảng = new [size]; 
Ví dụ: 
int[] myIntArray; myIntArray = new int[5]; 
int[] numbers; numbers = new int[] {0,1,2,3,4}; 
Hình ảnh mảng 
Hình ảnh một biến 
Mảng 2 chiều 
Mảng hai chiều a[,] 
Khai báo mảng 2 chiều:int[,] grades = new int[2,3]; // 2 hàng, 3 cột 
Truy cập phần tử của mảng [dòng, cột] 
0 
1 
4 
1 
2 
5 
Khởi tạo mảng 2 chiều 
int[,] grades = new int[,] {{1, 82, 74, 89, 100}, 
	{2, 93, 96, 85, 86}, 
	{3, 83, 72, 95, 89}, 
	{4, 91, 98, 79, 88}} 
Ví dụ cài đặt danh sách 
class CArray { 
	private int [] arr; 
	private int upper; 
	private int numElements; 
	public CArray(int size) { 
	arr = new int[size]; 
	upper = size-1; 
	numElements = 0; 
	 } 
Mảng danh sách đặc phổ biến 
public void Insert(int item) { 
	arr[numElements] = item; 
	numElements++; 
	} 
public void DisplayElements() { 
	for(inti=0;i<= upper; i++) 
	Console.Write(arr[i]+""); 
	} 
Mảng danh sách đặc phổ biến 
static void Main() { 
	CArray nums = new CArray(); 
	for(inti=0;i<=49; i++) 
	nums.Insert(i); 
	nums.DisplayElements(); 
} 
Mảng danh sách đặc phổ biến 
static void Main() { 
	CArray nums = new CArray(); 
	Random rnd = new Random(100); 
	for(inti=0;i<10; i++) 
	nums.Insert((int)(rnd.NextDouble() * 100)); 
	nums.DisplayElements(); 
	} 
Cài đặt danh sách bằng mảng 
Thêm một phần tử vào mảng 
10 
5 
13 
11 
5 
8 
13 
? 
18 
10 
5 
13 
11 
5 
8 
13 
10 
5 
18 
13 
11 
5 
8 
13 
Cài đặt danh sách bằng mảng 
Xóa phần tử ra khỏi mảng 
10 
5 
18 
13 
11 
5 
8 
? 
10 
5 
13 
11 
5 
8 
? 
10 
5 
13 
11 
5 
8 
? 
? 
Cài đặt danh sách bằng mảng 
Tìm kiếm phần tử trong mảng 
13 
10 
5 
13 
11 
5 
8 
? 
? 
10 
5 
13 
11 
5 
8 
? 
? 
10 
5 
13 
11 
5 
8 
? 
? 
13 
13 
Bài tập 
Nhập một dãy số nguyên từ bàn phím, và sắp xếp chúng theo thứ tự tăng dần 
Input: 5 2 4 18 9 1 
Output: 1 2 4 5 9 18 
Nhập một dãy số nguyên từ bàn phím, và cho biết số lần xuất hiện của từng số trong dãy số 
Input: 1 3 2 9 4 3 2 9 8 1 1 3 2 9 1 
Ouput: (1,4) (2,3) (3,3) (4,1) (8,1) (9,3) 
Tổ chức Stack theo kiểu danh sách đặc 
Top 
Push 
Pop 
Tổ chức Stack theo kiểu danh sách đặc 
Cấu trúc của STACK 
Dùng 1 mảng (StkArray) để chứa các phần tử 
Dùng 1 số nguyên (StkMax) để lưu số phần tử tối đa trong Stack 
Dùng 1 số nguyên (StkTop) để lưu chỉ số đỉnh của STACK 
Tổ chức Stack theo kiểu danh sách đặc 
Tổ chức Stack theo kiểu danh sách đặc 
Các thao tác cơ bản trên Stack: 
Stack: khởi tạo Stack rỗng 
IsEmpty: kiểm tra Stack rỗng ? 
IsFull: kiểm tra Stack đầy ? 
Push: thêm 1 phần tử vào đỉnh Stack, có thể làm Stack đầy 
Pop: lấy ra 1 phần tử từ đỉnh Stack, có thể làm Stack rỗng 
Tổ chức Stack theo kiểu danh sách đặc 
Khao báo lớp Stack 
Thao tác “Khởi tạo Stack rỗng” 
class Cstack { 
	private int [] StkArr; 
	private int StkTop; 
	private int StkMax; 
	public Cstack(int size) { 
	StkArr = new int[size]; 
	 StkMax = size; 
	StkTop = -1; // Stack rỗng 
	 } 
Kiểm tra Stack rỗng 
boolean IsEmpty() 
{ 
	if (StkTop == -1) return true; // Stack rỗng 
	return false; // Stack không rỗng 
} 
Kiểm tra Stack đầy 
boolean IsFull() 
{ 
	if (StkTop == StkMax-1) 
	return true; // Stack đầy 
	return false; // Stack chưa đầy 
} 
Thêm một phần tử vào Stack 
boolean Push(int newitem) 
{ 
if (IsFull()) 
return false; // Stack đầy, không thêm vào được 
StkTop++; 
StkArr[StkTop] = newitem; 
return true; // Thêm thành công 
} 
Lấy một phần tử ra khỏi Stack 
Thao tác “Pop”: lấy ra 1 phần tử từ đỉnh Stack 
boolean Pop(int outitem) 
{ 
if (IsEmpty()) 
Return false; // Stack rỗng, không lấy ra được 
outitem = StkArr[StkTop]; 
StkTop--; 
return true; // Lấy ra thành công 
} 
Tổ chức Queuetheo kiểu danh sách đặc 
Queue là 1 cấu trúc dữ liệu: 
Gồm nhiều phần tử có thứ tự 
Hoạt động theo cơ chế “Vào trước – Ra trước” (FIFO – First In, First Out) 
cinemark 
Tổ chức Queuetheo kiểu danh sách đặc 
Append 
Front 
Take 
Tổ chức Queuetheo kiểu danh sách đặc 
Cấu trúc của Queue 
Dùng 1 mảng (QArray) để chứa các phần tử 
Dùng 1 số nguyên (QMax) để lưu số phần tử tối đa trong hàng đợi 
Dùng 2 số nguyên (QFront, QRear) để xác định vị trí Đầu, Cuối hàng đợi 
Dùng 1 số nguyên (QNumItems) để lưu số phần tử hiện có trong hàng đợi 
Tổ chức Queuetheo kiểu danh sách đặc 
Tổ chức Queuetheo kiểu danh sách đặc 
Các thao tác trên Queue 
Queue: khởi tạo Queue rỗng 
IsEmpty: kiểm tra Queue rỗng ? 
IsFull: kiểm tra Queue đầy ? 
Append: thêm 1 phần tử vào cuối Queue, có thể làm Queue đầy 
Take: lấy ra 1 phần tử ở đầu Queue, có thể làm Queue rỗng 
Khai báo lớp Queue 
// Giả sử Queue chứa các phần tử kiểu nguyên (int) 
Class Queue { 
	private int [] QArray; 
	private int QMax; 
	private int QNumItems; 
 private int QFront; 
	private int QRear; 
Khai báo lớp Queue 
// Khởi tạo Queue chứa các phần tử kiểu nguyên (int) 
 public Queue(int size) { 
	QArray = new int[size]; 
	 QMax = size; 
	 QFront = Qrear= -1; // Queue rỗng 
	QNumItems = 0; // chưa có phần tử nào trong Queue 
	 } 
Kiểm tra Queue rỗng, đầy 
Thao tác “Kiểm tra Queue rỗng” 
boolean IsEmpty() 
{ 
if (QNumItems==0) 
return true; // Queue rỗng 
return false; // Queue không rỗng 
} 
Thao tác “Kiểm tra Queue đầy” 
boolean IsFull() 
{ 
if (QNumItems == QMax) 
return true; // Queue đầy 
return false; // Queue không đầy 
} 
Thêm 1 phần tử vào Queue 
Thao tác: thêm 1 phần tử vào cuối Queue 
boolean Append(int newitem) 
{ 
if (IsFull()) return false; // Queue đầy, không thêm vào được 
QRear++; 
QArray[q.QRear] = newitem; // thêm phần tử vào cuối Queue 
QNumItems++; 
return true; // Thêm thành công 
} 
Lấy một phần tử ra khỏi Queue 
Thao tác Take: lấy ra 1 phần tử ở đầu Queue 
	 boolean Take(int itemout) 
{ 
if (IsEmpty()) return false; // Queue rỗng, không lấy ra được 
itemout = QArray[QFront]; // lấy phần tử đầu ra 
QFront++; 
QNumItems--; 
if (QFront==QMax) // nếu đi hết mảng  
QFront = QRear = -1 ; //  quay trở về đầu mảng 
return true; // lấy thành công 
} 
Hạn chế của Queuetheo kiểu danh sách đặc 
Khi thêm nhiều phần tử, sẽ làm “tràn” mảng “Tràn giả” 
 [0] [1] [2] [3] [4] [5] [6] [7] 
Queue Rear 
Queue Front 
Giải pháp 
Giải pháp cho tình huống “tràn giả”: xử lý mảng như là 1 mảng vòng tròn 
 [0] [1] [2] [3] [4] [6] 
Rear 
Front 
Tổ chức Queuetheo kiểu danh sách đặc 
 [2] [3] [2] [3] 
 [1] [4][1] [4] 
[0] [5] [0] [5] 
front =0 
rear = 5 
front =4 
rear =3 
J2 J3	 
J1 J4 
 J5 
J6 J5 
J7 
J8 J9 
Bài tập 
Viết lại các giải thuật, bổ sung, lấy phần tử cho QUEUE nối vòng 
DANH SÁCH LIÊN KẾT 
Đặt vấn đề: 
Nếu muốn chèn vào 1 phần tử vào mảng ? 
Chi phí là O(n) 
Muốn xóa một phần tử trong mảng ? 
Chi phí O(n) 
DANH SÁCH LIÊN KẾT 
Ta tách rời các phần tử của mảng, và kết nối chúng lại với nhau bằng một “móc xích” 
 15  
 5  
 7  
 6  
 3  
 12  
 7  
 6  
 3  
 15  
 5  
 12  
 7  
 6  
 3  
 15  
 5  
DANH SÁCH LIÊN KẾT 
Một dãy tuần tự các nút (Node) 
Giữa hai nút có một tham chiếu 
Các nút không cần phải lưu trữ liên tiếp nhau trong bộ nhớ 
Có thể mở rộng tuỳ ý (chỉ giới hạn bởi dung lượng bộ nhớ) 
Thao tác Chèn/Xóa không cần phải dịch chuyển phần tử 
Quản lý danh sách bới con trỏ đầu pHead 
Có thể truy xuất đến các phần tử khác thông qua con trỏ liên kết 
DANH SÁCH LIÊN KẾT 
Cấu tạo nút 
Tạo lập bằng cách cấp phát bộ nhớ động 
Mỗi nút có 2 thông tin: 
Dữ liệu (data) 
Tham chiếu liên kết đến phần tử kế tiếp trong danh sách (Next pointer link) 
 12  
Phần dữ liệu 
Phần liên kết 
DANH SÁCH LIÊN KẾT 
Cấu tạo nút : Gồm 2 thành phần 
public class Node { 
	public Object Element; 
	public Node Link; 
	public Node() { 
	Element = null; 
	Link = null; 
	} 
 public Node(Object theElement) { 
	Element = theElement; 
	Link = null; 
	} 
	} 
Nút có một trường dữ liệu 
Cấu tạo của danh sách liên kết 
Quản lý danh sách qua con trỏ đầu pHead, có thể thêm con tro cuối pTail 
Có hai cách tổ chức danh sách 
pHead, pTail là một nút của danh sách 
pHead, pTail không phải là nút mà chỉ là con trỏ trỏ đến nút đầu và nút cuối của danh sách 
Cấu tạo của danh sách liên kết 
 12  
 7  
 6  
 3  
 15  
 5  
pHead 
 12  
 7  
 6  
 3  
 15  
 5  
pHead 
pTail 
ƯU VÀ NHƯỢCCỦA DANH SÁCH LIÊN KẾT 
Ưu điểm 
Tận dụng được không gian nhớ để lưu trữ 
Các nút không cần lưu trữ kế tiếp nhau 
Có thể mở rộng kích thước tùy ý (phụ thuộc bộ nhớ) 
Việc thêm vào hay loại bỏ được tiến hành dễ dàng O(1) 
Dễ dàng kết nối hay phân rã danh sách 
Nhược điểm 
Truy xuất tuần tự từng phần tử 
Các loại danh sách liên kết 
Danh sách liên kết đơn (Single-Linked list) 
Mỗi nút chỉ có 1 con trỏ liên kết (pNext) 
Danh sách liên kết đôi (Double-Linked list) 
Mỗi nút có 2 con trỏ liên kết (pPrev, pNext) 
Danh sách đa liên kết (Multi-Linked list) 
Mỗi nút có nhiều hơn 2 con trỏ liên kết 
Danh sách liên kết vòng (Circular-Linked list) 
Liên kết ở nút cuối cùng của danh sách chỉ đến nút đầu tiên trong danh sách 
Danh sách liên kết đơn 
Mỗi nút, bao gồm hai phần, 
Phần Data: chứa dữ liệu, có thể nhiều hơn 1 trường 
Phần next: chỉ có duy nhất một liên kết đến nút kế tiếp 
Phần tử cuối cùng có liên kết NULL 
MẢNG & DANH SÁCH LIÊN KẾT 
Mảng 
Phải biết trước số phần tử 
Lưu trữ tuần tự 
Khi chèn và xóa phải dịch chuyển các phần tử 
Truy xuất qua chỉ mục 
Danh sách liên kết 
Số phân tử tùy biến 
Sử dụng con trỏ 
Khi chèn/xóa chỉ cần thay đổi con trỏ liên kết 
Truy xuất tuần tự 
Các thao táctrên danh sách liên kết đơn 
Tạo lập danh sách rỗng 
Kiểm tra danh sách rỗng 
Đếm số phần tử trong danh sách 
Thêm 1 nút vào danh sách 
Xóa 1 nút khỏi danh sách 
Duyệt danh sách 
Tìm 1 phần tử trong danh sách 
Tạo lập danh sách rỗng 
public class LinkedList { 
	protected Node header; 
	public LinkedList() { 
	header = new Node("header"); 
	} 
... 
} 
Tạo lập danh sách rỗng 
Tạo lập danh sách rỗng 
	void Init_List( Node pHead) 
{ 
	pHead = NULL; 
} 
Các thao táctrên danh sách liên kết đơn 
Kiểm tra danh sách rỗng 
boolean IsEmptyList( pHead) 
	{ return (pHead ==NULL); } 
Đếm số phần tử trong danh sách 
int CountNode(Node pHead){ 
 int count = 0; 
 Node p = pHead; 
	while (p != NULL) 
 { cout++ ; p = p.Link; } 
 return cout; 
 } 
Các thao táctrên danh sách liên kết đơn 
Thêm một nút p vào đầu danh sách 
Nếu Danh sách rỗng Thì 
Gán: pHead = p; 
Ngược lại 
p.Link = pHead; 
pHead = p; 
NULL 
A 
B 
C 
D 
E 
pHead 
X 
p 
Chèn nút P vào cuối Danh sách 
Chèn nút p vào cuối 
Nếu Danh sách rỗng Thì 
Gán: pHead = p; 
Ngược lại 
Gán q = pHead; 
Đi về nút cuối của danh sách 
 (while (q.Link != NULL) q = q.Link;) 
q.Link = p; 
A 
B 
C 
D 
E 
pHead 
X 
q 
p 
Thêm một nút p vào vào sau nút q 
Nếu (q != NULL) 
P.Link = q.Link; 
Q.Link = p ; 
Ngược lại: q = p; 
A 
B 
C 
D 
E 
pHead 
X 
q 
p 
Các thao táctrên danh sách liên kết đơn 
Xóa một nút khỏi danh sách 
Xóa nút đầu danh sách 
Xóa một nút đứng sau nút q 
Xóa một nút có khóa k 
Các thao táctrên danh sách liên kết đơn 
Xóa nút đầu danh sách 
Nếu (pHead != NULL) thì 
 p = pHead;	 // p là nút cần xóa 
 pHead = pHead.Link; 
A 
B 
X 
Z 
Y 
pHead 
p 
Các thao táctrên danh sách liên kết đơn 
Xóa một nút p, đứng sau q 
Nếu (q!= NULL) thì 
 p = q.Next;	 // p là nút cần xóa 
Q.Next = p.Next; // tách p ra khỏi ds 
 delete p;	 // Giải phóng p 
Ngược lại: 
Xóa nút đầu danh sách 
A 
B 
C 
D 
E 
pHead 
q 
p 
Các thao táctrên danh sách liên kết đơn 
Xóa một nút có khóa k 
Tìm nút p có khóa k và phần tử q đứng trước nó 
Nếu ( p != NULL) // tìm thấy k 
xóa p đứng sau nút q; 
Ngược lại 
Báo không có k; 
A 
B 
X 
Z 
Y 
pHead 
Xóa nút có khóa là X 
P 
q 
Các thao táctrên danh sách liên kết đơn 
Duyệt danh sách 
 p = pHead; 
Trong khi chưa hết danh sách 
Xử lý nút p ; 
p= p.pNext; 
A 
B 
C 
D 
E 
pHead 
P 
Duyệt danh sách 
void TraverseList( Node pHead ) 
 { 
	Node p = pHead; 
	while (p !=NULL) { 
	; 
	p = p.Link; // chuyển sang nút kế 
	} 
 } 
Bài tập 
Dùng danh sách liên kết quản lý sinh viên trong lớp (mssv, họ, tên, ngày sinh, điểm tổng kết học kỳ). 
Thực hiện các thao tác: thêm, bớt, sắp xếp sinh viên (theo điểm tổng kết) trong danh sách 
Danh sách liên kết vòng 
Các thao tác trên danh sách liên kết vòng 
Giải thuật thêm một nút vào đầu danh sách 
Giải thuật thêm một nút vào danh sách 
Giải thuật loại một nút ra khỏi danh sách 
A 
B 
X 
Z 
Y 
Head 
Danh sách liên kết kép 
Mỗi nút có 2 con trỏ liên kết: 
Khai báo: 
A 
B 
C 
D 
Danh sách liên kết kép 
Khi xóa 1 nút, không cần phải duyệt danh sách để tìm phần tử đứng trước 
Được sử dụng đối với các dữ liệu mà ta cần truy xuất theo cả 2 chiều: 
Bài tập: Viết các giải thuật, khởi tạo, bổ sung, tìm kiếm, duyệt, xóa trên danh sách liên kết kép. 
Tổ chức STACK và QUEUEbằng danh sách liên kết 
Sinh viên tự cài đặt. 
Tổ chức ngăn xếp (Stack) 
Tổ chức hàng đợi (Queue) 
Q&A 

File đính kèm:

  • pptbai_giang_ngon_ngu_lap_trinh_chuong_3_danh_sach_pham_thanh_a.ppt