Trong phạm vi đề tài cơ sở, nhằm tìm hiểu về Danh sách liên kết đơn,cấu trúc và các ứng dụng của nó, em xin trình bày đề tài: Tìm hiểu Danh sách liên kết đơn và cài đặt một số bài toán t
Trang 1KHOA CÔNG NGHỆ THÔNG TIN
ĐỒ ÁN CƠ SỞ
ĐỀ TÀI:
TÌM HIỂU DANH SÁCH LIÊN KẾT ĐƠN VÀ CÀI ĐẶT MỘT SỐ BÀI
TOÁN TRÊN DANH SÁCH LIÊN KẾT ĐƠN
Giảng viên hướng dẫn : PHẠM KHÁNH LINH
Đà Nẵng, tháng 04/2011
Trang 2MỤC LỤC
LỜI NGỎ 4
PHẦN MỞ ĐẦU 5
1- Lý do chọn đề tài: 5
2- Mục tiêu của đề tài: 5
3- Phạm vi nghiên cứu: 5
4- Phương pháp nghiên cứu: 5
CHƯƠNG 1: CƠ SỞ LÝ THUYẾT 6
1.1 Dữ liệu kiểu con trỏ 6
1.1.1 Giới thiệu chung và định nghĩa con trỏ: 6
1.1.2 Khai báo: 7
1.1.3 Sử dụng: 7
1.2 Danh sách liên kết 8
1.2.1 Định nghĩa: 8
1.2.2 Phân loại: 8
1.2.3 Khai báo: 9
1.2.4 Các thao tác cơ bản trên Danh sách liên kết đơn : 10
1.2.4.1 Định nghĩa Node 10
1.2.4.2 Khai báo một Node 10
1.2.4.3 Chèn một Node P có giá trị x vào DSLK: 10
1.2.4.3.1 Chèn Node P có chứa giá trị x vào đầu danh sách liên kết 10
1.2.4.3.2 Chèn Node P có chứa giá trị x vào vị trí bất kỳ trên danh sách liên kết 11
1.2.4.3.3 Chèn Node P có chứa giá trị x vào cuối danh sách liên kết 13
1.2.5 Ưu điểm và nhược điểm của Danh sách liên kết đơn : 13
CHƯƠNG 2: PHÂN TÍCH VÀ THIẾT KẾ THUẬT TOÁN CÁC BÀI TOÁN CƠ BẢN TRÊN DSLK 15
2.1 Nhập DSLK: 15
2.2 Xuất DSLK: 15
2.3 Tính tổng các giá trị lẻ trong DSLK: 16
2.4 Tính trung bình cộng các số nguyên tố trong DSLK: 17
2.5 Đếm xem trong DSLK có bao nhiêu phần tử chẵn: 19
2.6 Kiểm tra DSLK có chứa các số chẵn hay không? 19
2.7 Tìm Node Q ở vị trí K trong DSLK: 21
2.8 Chèn giá trị X vào vị trí K trong DSLK: 21
2.9 Xoá một phần tử tại vị trí k trong DSLK: 23
2.10 Xoá các số âm trong DSLK: 24
CHƯƠNG 3: CÀI ĐẶT CHƯƠNG TRÌNH 25
3.1 Cài đặt chương trình trên Turbo C++ IDE 25
3.1.1 Tạo Danh sách liên kết: 25
3.1.2 Xuất Danh sách liên kết ra màn hình hiển thị: 26
3.1.3 Tính tổng các giá trị lẽ trong DSLK: 26
3.1.4 Tính trung bình cộng các số nguyên tố trong DSLK: 26
3.1.5 Kiểm tra có bao nhiêu phần tử chẵn trong DSLK: 27
3.1.6 Kiểm tra DSLK có chẵn hay không: 27
3.1.7 Tìm Node Q ở vị trí k trong DSLK: 28
3.1.8 Chèn một Node mới có giá trị x vào vị trí k trong DSLK: 28
3.1.9 Xóa một Node tại vị trí k trong DSLK: 29
3.1.10 Xóa các giá trị âm trong DSLK: 29
3.1.11 Hàm main: 30
Trang 33.2 Demo chương trình 31
KẾT LUẬN 33
Tài liệu tham khảo: 34
NHẬN XÉT CỦA GIÁO VIÊN HƯỚNG DẪN 35
NHẬN XÉT CỦA GIÁO VIÊN PHẢN BIỆN 36
Trang 4LỜI NGỎ
Trong nền khoa học và kỹ thuật ngày nay, ngành công nghệ thông tin đã có nhữngbước phát triển mạnh mẽ, có mặt hầu hết mọi nơi trong đời sống Ứng dụng của công nghệthông tin ngày càng mở rộng trong các lĩnh vực khác nhau của đời sống kinh tế - xã hội, từmột thiết bị nhỏ như điện thoại, hay đến các hệ thống lớn như hệ thống điều khiển giaothông hàng không, điều khiển hoạt động của các nhà máy điện nguyên tử, hay quản lý hoạtđộng của các bệnh viện v…v Chính vì các ứng dụng rộng rãi của công nghệ thông tin
mà các cá nhân cũng như các chuyên gia công nghệ thông tin quan tâm và nghiên cứu ranhững nguyên lý, công nghệ, giải pháp tối ưu để máy tính làm việc phục vụ cho đời sốngcon người ngày một tốt hơn và hiệu quả hơn
Với những đặc điểm trên đây ta có thể thấy rõ tầm quan trọng và đa dạng của ngànhcông nghệ thông tin, điều đó đòi hỏi những sinh viên ngành công nghệ thông tin cần nắmvững các nguyên lý và ứng dụng của các môn học nói chung và những cấu trúc dữ liệu vàgiải thuật nói riêng Trong phạm vi đề tài cơ sở, nhằm tìm hiểu về Danh sách liên kết đơn,cấu trúc và các ứng dụng của nó, em xin trình bày đề tài: Tìm hiểu Danh sách liên kết đơn
và cài đặt một số bài toán trên Danh sách liên kết đơn
Tuy đã cố gắng học hỏi và áp dụng dựa trên cơ sở kiến thức bộ môn “Cấu trúc dữ liệu
và giải thuật” đã được học và một số tài liệu tham khảo nhưng do khả năng và thời gian cóhạn nên chắc chắn đề tài này sẽ không tránh khỏi thiếu sót Mong quý thầy cô và các bạnnhìn nhận và cho ý kiến, góp ý để đồ án hoàn thiện hơn
Em xin chân thành cảm Giáo viên hướng dẫn - cô Phạm Khánh Linh đã quan tâmgiúp đỡ em nhiệt tình trong suốt thời gian qua để em có thể hoàn thành đồ án này!
Trang 5PHẦN MỞ ĐẦU
1- Lý do chọn đề tài:
- Với mong muốn hiểu rỏ hơn về dữ liệu kiểu con trỏ, về Danh sách liên kết đơn, từ
đó có thể ứng dụng Danh sách liên kết đơn để giải các bài toán nên em đã chon đề tài này
để nghiên cứu và làm báo cáo đồ án cơ sở
2- Mục tiêu của đề tài:
- Tìm hiểu về con trỏ
- Tìm hiểu về cấu trúc dữ liệu của Danh sách liên kết đơn
- Tìm hiểu về thuật toán và các phương pháp được sử dụng khi cài đặt một số bàitoán về Danh sách liên kết đơn bằng ngôn ngữ C++
3- Phạm vi nghiên cứu:
- Nghiên cứu lý thuyết môn học “ Cấu trúc dữ liệu và giải thuật”
- Nghiên cứu trọng tâm lý thyết về dữ liệu kiểu con trỏ
- Nghiên cứu trọng tâm lý thuyết về danh sách liên kết đơn
- Cài đặt một số bài toán trên danh sách liên kết đơn
4- Phương pháp nghiên cứu:
- Nghiên cứu lý thuyết từ các giáo trình môn học “ Cấu trúc dữ liệu và giải thuật”
và “Giáo trình Lập trình C++”, tìm thêm tài liệu từ các nguồn thông tin mở (web), từ đóviết các chương trình theo phạm vi nghiên cứu trên công cụ Turbo C++ IDE Chạy thửnhiệm và kiểm tra độ chính xác của các chương trình
Trang 6CHƯƠNG 1: CƠ SỞ LÝ THUYẾT
1.1 Dữ liệu kiểu con trỏ
1.1.1 Giới thiệu chung và định nghĩa con trỏ:
- Các biến được sử dụng từ trước đến nay đều là biến có kích thước và kiểu dữ liệuxác định, người ta gọi là biến tĩnh (static)
- Khi chạy chương trình, gặp những biến này, máy sẽ cung cấp lương bộ nhớ và địachỉ cho các biến đó mà không cần biết các biến đó sử dụng luc nào hoặc thậm chí có được
sử dụng hay không
- Các biến tĩnh tồn tại trong suốt thời gian thực hiện chương trình Vì vậy, nếu chạymột chương trình lớn trong khi máy lại hạn chế bộ nhớ thì sẽ xay ra tình trạng không đủ bộnhớ
- Đối với những chương trình mà ta không dự đoán trước được kích thước củachúng ra sao thì sẽ xảy ra tình trạng:
+ Cấp dư, gây lãng phí bộ nhớ
+ Cấp thiếu, chương trình không chạy được
- Để khắc phục những nhược điểm trên, các ngôn ngữ lập trình cấp cao như Pascal,Turbo C, … thường sử dụng biến động (dynamic) vì có những đặc điểm sau:
+ Biến động được sinh ra trong quá trình thực hiện chương trình
+ Biến động là loại biến có biến đổi được kích thước, vùng nhớ và địa chỉcủa vùng nhớ được cấp phát lúc chạy chương trình
+ Có thể giải phóng biến động sau kho đã sử dụng để tiết kiệm bộ nhớ
- Thế nhưng biến động cũng có nhược điểm là không thể truy cập đến nó được bởibiến động không chứa địa chỉ nhất định
- Để khắc phục nhược điểm này, người ta sử dụng một loại biến đặc biệt gọi là biếncon trỏ (pointer)
- Biến con trỏ có các đặc điểm:
+ Không chứa dữ liệu nhưng chứa địa của dữ liệu tức địa chỉ của biến khác.+ Kích thước của biến con trỏ không phụ thuộc vào đối tượng mà nó trỏ tới.+ Con trỏ có cùng kiểu dữ liệu với kiểu dữ liệu của biến mà nó trỏ tới
- Vậy: “Biến con trỏ là loại biến chuyên dùng để chứa chứa địa chỉ của các biến
động, giúp ta truy nhập đến biến động”
1.1.2 Khai báo:
- Cú pháp khai báo một con trỏ như sau
<kiểu dữ liệu> *<tên con trỏ>;
Trong đó:
+ Kiểu dữ liệu: có thể là các kiểu dữ liệu cơ bản của C++, hoặc là kiểu dữliệu có cấu trúc, hoặc là kiểu đối tượng do người dùng tự định nghĩa
+ Tên con trỏ: Tuân theo các quy tắc đặt tên biến của C++:
+ Chỉ được bắt đầu bằng một ký tự (chữ), hoặc dấu gạch dưới “_”
+ Bắt đầu từ ký tự thứ hai có thể có kiểu ký tự số+ Không có dấu trống (space bar) trong tên biến+ Có phân biệt chữ hoa và chữ thường
+ Không giới hạn độ dài tên biến
Ví dụ: Để khai báo một biến con trỏ có kiểu là int và tên là songuyen, ta viết như
Trang 7int* songuyen;
1.1.3 Sử dụng:
- Con trỏ dùng để truy cập biến thông qua địa chỉ biến và chương trình tham khảobiến gián tiếp qua địa chỉ này
- Con trỏ được sử dụng theo 2 cách:
+ Dùng con trỏ để lưu địa chỉ của biến: Lấy giá trị của biến do con trỏ trỏđến để thao tác
+ Dùng con trỏ để lưu địa chỉ của biến: Bản thân con trỏ sẽ được trỏ vào địachỉ của một biến có cùng kiểu dữ liệu với nó Cú pháp của phép gán nhưsau:
<tên con trỏ> = &<tên biến>;
Quy trình diễn ra như sau:
- Như vậy, mỗi Node có 2 thành phần là phần Info dùng để chứa dữ liệu cần xử lý
và phần liên kết dùng để liên kết với các Node khác
1.2.2 Phân loại:
- Có nhiều loại Danh sách liên kết như:
+ Danh sách liên kết đơn
+ Danh sách liên kết đôi/kép
+ Danh sách đa liên kết
+ Danh sách liên kết vòng
+ …
- Mỗi loại danh sách liên kết sẽ có cách biểu diễn các phần tử (cấu trúc dư liệu)riêng và các thao tác trên đó Trong nội dung bản báo cáo này chỉ đề cập đến loại danhsách liên kết cơ bản nhất là Danh sách liên kết đơn
- Danh sách liên kết đơn là danh sách mà mỗi Node của nó chỉ có một trường liên
kết.
Trang 8- Các hình dưới mô tả một danh sách liên kết đơn
1.2.3 Khai báo:
- Mỗi Node của danh sách có thể biểu diễn như sau:
- Trong đó:
+ Info: gồm các trường chứa nội dung thông tin của phần tử
+ Next: chứa địa chỉ của Node tiếp theo hay còn gọi là vùng liên kết
Định nghĩa Node:
struct Node {
- Khi làm việc trên danh sách liên kết đơn chúng ta cần có những chú ý sau:
+ Danh sách luôn có con trỏ trỏ đầu danh sách: con trỏ first
+ Danh sách luôn có một giá trị báo kết thúc danh sách: giá trị NULL.+ Trường Next của mỗi Node chỉ chứa địa chỉ Node ở sau nó, trừ Node cuốicùng
+ Trường Next của Node cuối cùng chứa giá trị NULL
+ Không tách danh sách thành hai danh sách con nếu danh sách phần sauchưa có con trỏ trỏ tới
+ Khởi tạo danh sách rỗng: first = NULL;
1.2.4 Các thao tác cơ bản trên Danh sách liên kết đơn :
1.2.4.1 Định nghĩa Node
struct Node
{
int Info; // khai báo trường Info là kiểu int
Node *Next; // khai báo con trỏ Next kiểu Node (vì nó chứa địa chỉ
trỏ tới 1 Node khác có 2 trường)};
Trang 91.2.4.2 Khai báo một Node
Node *MakeNode(int x) // Hàm MakeNode tạo ra một con trỏ kiểu
Node nên có kiểu trả về là Node{
Node *P; // khai báo biến con trỏ P kiểu Node
P=new Node; // cấp phát một Node cho con trỏ P
PInfo=x; // truy cập vào trường Info gán giá trị là xPNext=NULL; // truy cập vào trường Next, trỏ tới NULLreturn P; // trả về kiểu Node cho con trỏ P
}
1.2.4.3 Chèn một Node P có giá trị x vào DSLK:
1.2.4.3.1 Chèn Node P có chứa giá trị x vào đầu danh sách liên kết
Bước 2: Khởi tạo Node P có giá trị x
Bước 3: So sánh first với NULL Nếu first bằng NULL thì thực hiện bước 4, nếukhông thì qua bước 5
Bước 4: Gán first = P Thực hiện bước 6
Bước 5: Gán PNext=first, first=P
First=P;
}}
1.2.4.3.2 Chèn Node P có chứa giá trị x vào vị trí bất kỳ trên danh sách liên kết
Trang 10Bước 2: Khởi tạo Node P có giá trị x, chạy hàm Tìm Node Q có vị trí k.
Bước 3: So sánh Q với NULL Nếu Q bằng NULL thì thực hiện bước 4, nếu không thì qua
bước 5
Bước 4: Kết luận không chèn
Bước 5: Khai báo Node R=first
Bước 6: So sánh RNext với Q Nếu khác thì thực hiện bước 7, nếu không thì qua bước 8.Bước 7: Gán R=RNext Quay lại bước 6
Bước 8: Gán RNext=P và PNext=Q
Trang 11- Thuật toán:
Bước 1: Nhập giá trị x
Bước 2: Khởi tạo Node P có giá trị x
Bước 3: So sánh first với NULL Nếu first bằng NULL thì thực hiện bước 4, nếu không thì
qua bước 5
Bước 4: Gán first = P Thực hiện bước
Bước 5: Khai báo Node R=first
Bước 6: So sánh RNext với NULL Nếu khác NULL thì qua bước 7, nếu bằng NULL thì
qua bước 8
Bước 7: Gán R=RNext Quay lại bước 6
Bước 8: Gán RNext=P và PNext=NULL
1.2.5 Ưu điểm và nhược điểm của Danh sách liên kết đơn :
Ưu điểm
◦ Tận dụng được không gian bộ nhớ nhỏ để lưu trữ từng nút
◦ Việc thêm, xóa phần tử trong danh sách liên kết là dễ dàng, chỉ cần thayđổi mối liên kết của các phần tử với nhau
Trang 12CHƯƠNG 2: PHÂN TÍCH VÀ THIẾT KẾ THUẬT TOÁN
CÁC BÀI TOÁN CƠ BẢN TRÊN DSLK 2.1 Nhập DSLK:
- Dữ liệu:
Đầu vào : x, first
Đầu ra : DSLK
- Thuật toán:
Bước 1: Nhập số phần tử của DSLK cần tạo
Bước 2: Khai báo con chạy i=1
Bước 3: So sánh con chạy i với n Nếu i<=n thì chuyển sang bước 4, nếu không qua bước
6
Bước 4: Nhập giá trị x, thực thi hàm chèn một giá trị mới vào đầu DSLK PushTop
Bước 5: Giá trị i tăng thêm 1 Quay trở lại bước 3
Nhập x Thục thi hàm PushTop i=i+1
Bước 1: Khai báo Node R=first
Bước 2: So sánh R với NULL Nếu R khác NULL thì qua bước 3, nếu không qua bước 5.Bước 3: In giá trị RInfo ra màn hình
Bước 4: Gán R=RNext Quay lại bước 2
Bước 5: Kết thúc hàm
Trang 13Bước 1: Khai báo Node R=first, Tong Le=0.
Bước 2: So sánh R với NULL Nếu R khác NULL thì thực hiện bước 3, nếu không thì qua
bước 6
Bước 3: So sánh RInfo có chia hết cho 2 không, nếu không thì thực hiện bước 4, nếu
đúng thì thực hiện bước 5
Bước 4: TongLe bằng TongLe cộng với giá trị RInfo
Bước 5: Gán R=RNext Quay lại bước 2
Bước 6: Kết thúc hàm
- Sơ đồ khối:
Trang 14Đ S
Rà Info%2==1
Đ
S
R=Rà Next
2.4 Tính trung bình cộng các số nguyên tố trong DSLK:
- Dữ liệu:
Đầu ra : Trung bình cộng các số nguyên tố
- Thuật toán:
Bước 1: Khai báo Node R=first, Tong=0, DemSNT=0, TBC
Bước 2: So sánh R với NULL Nếu R khác NULL thì thực hiện bước 3, nếu không thì qua
bước 14
Bước 3: Gán RInfo=x
Bước 4: So sánh x với 2 Nếu x=2 thì chuyển qua bước 5, nếu không qua bước 9
Bước 5: Gán CheckNumber=1
Bước 6: So sánh CheckNumber với 1 Nếu CheckNumber =1 thì chuyển sang bước 7, nếu
không qua bước 8
Bước 7: DemSNT tăng thêm 1, Tong = Tong + x
Bước 8: Gán R=RNext Quay lại bước 2
Bước 9: Khai báo con chạy i=2:
Bước 10: So sánh I với x Nếu i<x thì qua bước 11, nếu không phải thì quay lại bước 6.Bước 11: So sánh xem x có chia hết cho I hay không Nếu sai thì qua bước 12, nếu đúng
thì qua bước 13
Bước 12: Gán CheckNumber=1, i tăng thêm 1 Quay lại bước 10
Bước 13: CheckNumber=0 Quay lại bước 6
Bước 14: TBC bằng Tong chia DemSNT
Bước 15: Kết thúc hàm
- Sơ đồ khối:
Trang 15Bước 1: Khai bào Node R=first Dem=0
Bước 2: So sánh R với NULL Nếu R khác NULL thì thực hiện bước 3, nếu không thì qua
bước 6
Bước 3: So sánh xem RInfo có chia hết cho 2 hay không Nếu có thì qua bước 4, nếu
không chuyển sang bước 5
Bước 4: Dem tăng thêm 1
Bước 5: Gán R=RNext Quay lại bước 2
Bước 6: Kết thúc hàm
Trang 16- Sơ đồ khối:
begin
R!=NULL
Dem=0 R=first
finish
Đ S
Rà Info%2==0 Đ
S R=Rà Next Dem++
2.6 Kiểm tra DSLK có chứa các số chẵn hay không?
- Dữ liệu:
Đầu vào : DSLK
Đầu ra : Kết luận DSLK có chẵn hay không
- Thuật toán:
Bước 1: Khai báo biến Check R=first
Bước 2: So sánh R với NULL Nếu R khác NULL thì thực hiện bước 3, nếu không thì qua
bước 7
Bước 3: So sánh xem RInfo có chia hết cho 2 hay không, nếu có thì qua bước 4, nếu
không qua bước 6:
Trang 17R!=NULL
Check R=first
finish
Đ
S
Rà Info%2==0Đ
S
R=Rà Next Check=1 Check=0break;
Bước 1: Khai báo Q=first Con chạy i=1
Bước 2: So sánh Q với NULL và I với k Nếu Q khác NULL đồng thời i<k thì thực hiện
bước 3, nếu không thì qua bước 4
Bước 3: Q=QNext i tăng thêm 1 Quay lại bước 2
Bước 4: Kết thúc hàm
- Sơ đồ khối:
Trang 18Q!=NULL i<k
Khai báo con trỏ Q kiểu Node Gán Q = first
Khai báo i=1
Q=Qà Next i++
Bước 2: Khởi tạo Node P có giá trị x, chạy hàm Tìm Node Q có vị trí k
Bước 3: So sánh Q với NULL Nếu Q bằng NULL thì thực hiện bước 4, nếu không thì qua
bước 5
Bước 4: Kết luận không chèn
Bước 5: Khai báo Node R=first
Bước 6: So sánh RNext với Q Nếu khác thì thực hiện bước 7, nếu không thì qua bước 8.Bước 7: Gán R=RNext Quay lại bước 6
Bước 8: Gán RNext=P và PNext=Q
Bước 9: Kết thúc hàm
- Sơ đồ khối: