Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 60 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
60
Dung lượng
1,25 MB
Nội dung
TRƯỜNG CAO ĐẲNG NGHỀ ĐẮK LẮK KHOA ĐIỆN TỬ - TIN HỌC GIÁO TRÌNH CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT NGHỀ: CƠNG NGHỆ THƠNG TIN TRÌNH ĐỘ: CAO ĐẲNG NGHỀ - TRUNG CẤP NGHỀ Người biên soạn: Lưu hành nội - 2014 Nguyễn Thị Thu Hà Lời nói đầu Hiện nay, Trường chưa có giáo trình Cấu trúc liệu & giải thuật Đặc biệt thị trường khơng có tài liệu học tập, tham khảo phù hợp với chương trình khung Cao đẳng nghề, trung cấp nghề thuộc nghề Công nghệ thông tin (CNTT) q trình đào tạo nghề Nhóm tác giả biên soạn giáo trình lập trình nhằm mục đích giúp học sinh, sinh viên (HSSV) sử dụng giáo trình làm tài liệu nghiên cứu học tập cách thuận tiện Chương trình mơn học sử dụng để giảng dạy cho sinh viên cao đẳng nghề Công nghệ thông tin (ứng dụng phần mềm) làm tài liệu tham khảo cho nghề thuộc ngành nghề kỹ thuật Vậy, mong góp ý bạn đọc để tài liệu ngày hoàn thiện hơn, xin chân thành cảm ơn Đắk Lắk, ngày 02 tháng 09 năm 2014 Tham gia biên soạn Chủ biên: Nguyễn Thị Thu Hà ThS Lê Văn Tùng CHƯƠNG TRÌNH MƠN HỌC CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT Mã số môn học: MH 12; Thời gian môn học: 75 giờ; (Lý thuyết: 24 giờ; Thực hành: 51 giờ) I VỊ TRÍ, TÍNH CHẤT CỦA MÔN HỌC: Cấu trúc liệu giải thuật môn sở nghề bắt buộc, học sau mơn học Tin học, Lập trình II MỤC TIÊU CỦA MÔN HỌC: - Hiểu mối quan hệ cấu trúc liệu giải thuật việc xây dựng chương trình; - Hiểu ý nghĩa, cấu trúc, cách khai báo, thao tác loại cấu trúc liệu: mảng, danh sách liên kết, giải thuật xử lý cấu trúc liệu đó; - Xây dựng cấu trúc liệu mô tả tường minh giải thuật cho số toán ứng dụng cụ thể; - Cài đặt số giải thuật ngôn ngữ lập trình C; Coi việc học mơn tảng cho môn học chuyên môn tiếp theo, nghiêm túc tích cực việc học lý thuyết làm tập, chủ động tìm kiếm nguồn tài liệu liên quan đến môn học III NỘI DUNG MÔN HỌC: Nội dung tổng quát phân bổ thời gian: Số TT I II III IV V VI Tên chương, mục Thiết kế phân tích giải thuật Các kiểu liệu sở Mảng, danh sách kiểu liệu trừu tượng Cây Sắp xếp Tìm kiếm Tổng cộng Thời gian Thực hành, Bài tập 11 Kiểm tra* (LT TH) 0 20 13 15 10 75 22 10 49 0 Tổng số Lý thuyết 15 Chương 1: Thiết kế phân tích giải thuật Mở đầu: Có thể nói khơng có chương trình máy tính mà khơng có liệu để xử lý Dữ liệu liệu đưa vào (input data), liệu trung gian liệu đưa (output data) Do vậy, việc tổ chức để lưu trữ liệu phục vụ cho chương trình có ý nghĩa quan trọng toàn hệ thống chương trình Việc xây dựng cấu trúc liệu định lớn đến chất lượng công sức người lập trình việc thiết kế, cài đặt chương trình Thiết kế giải thuật: Khái niệm giải thuật hay thuật giải mà nhiều gọi thuật toán dùng để phương pháp hay cách thức (method) để giải vần đề Giải thuật minh họa ngôn ngữ tự nhiên (natural language), sơ đồ (flow chart) mã giả (pseudo code) Trong thực tế, giải thuật thường minh họa hay thể mã giả tựa hay số ngơn ngữ lập trình (thường ngơn ngữ mà người lập trình chọn để cài đặt thuật toán), chẳng hạn C, Pascal, ? Khi xác định cấu trúc liệu thích hợp, người lập trình bắt đầu tiến hành xây dựng thuật giải tương ứng theo yêu cầu toán đặt sở cấu trúc liệu chọn Để giải vấn đề có nhiều phương pháp, lựa chọn phương pháp phù hợp việc mà người lập trình phải cân nhắc tính tốn Sự lựa chọn góp phần đáng kể việc giảm bớt cơng việc người lập trình phần cài đặt thuật tốn ngơn ngữ cụ thể Phân tích giải thuật: Mối quan hệ cấu trúc liệu Giải thuật minh họa đẳng thức: Cấu trúc liệu + Giải thuật = Chương trình Như vậy, có cấu trúc liệu tốt, nắm vững giải thuật thực việc thể chương trình ngơn ngữ cụ thể vấn đề thời gian Khi có cấu trúc liệu mà chưa tìm thuật giải khơng thể có chương trình ngược lại khơng thể có Thuật giải chưa có cấu trúc liệu Một chương trình máy tính hồn thiện có đầy đủ Cấu trúc liệu để lưu trữ liệu Giải thuật xử lý liệu theo yêu cầu toán đặt 3.1 Đánh giá cấu trúc liệu giải thuật 3.1.1 Các tiêu chuẩn đánh giá cấu trúc liệu Để đánh giá cấu trúc liệu thường dựa vào số tiêu chí sau: - Cấu trúc liệu phải tiết kiệm tài nguyên (bộ nhớ trong), - Cấu trúc liệu phải phản ảnh thực tế toán, - Cấu trúc liệu phải dễ dàng việc thao tác liệu 3.2 Đánh giá độ phức tạp thuật toán Việc đánh giá độ phức tạp thuật tốn khơng dễ dàng chút Ở dây, muốn ước lượng thời gian thực thuận tốn T(n) để có so sánh tương đối thuật toán với Trong thực tế, thời gian thực thuật tốn cịn phụ thuộc nhiều vào điều kiện khác cấu tạo máy tính, liệu đưa vào, xem xét mức độ lượng liệu đưa vào ban đầu cho thuật toán thực Để ước lượng thời gian thực thuật tốn xem xét thời gian thực thuật toán hai trường hợp: - Trong trường hợp tốt nhất: Tmin - Trong trường hợp xấu nhất: Tmax Từ ước lượng thời gian thực trung bình thuật toán: Tavg Một số giải thuật bản: 4.1: Thuật tốn đơn giản Có thể nói khơng có chương trình máy tính mà khơng có liệu để xử lý Dữ liệu liệu đưa vào (input data), liệu trung gian liệu (output data) Ví dụ: Nhập vào số chữ số, in tổng chữ số #include int n, dv, ch, tr, tong; void main() { printf(“Nhap vao mot so chu so:”); scanf(“%d”, &n); dv = n mod 10; ch = (n div 10) mod 10; tr = (n div 100) mod 10; tong = dv+ ch+ tr; printf(“Tong so la: %d”, tong); getchar(); } 4.2: Thuật toán phức tạp: Ví dụ : Dãy số Fibonacci 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, … Bắt đầu 1, số tổng hai số trước Dãy Fibonacci khai báo đệ quy sau: Fibonacci(0) = Fibonacci(1) = Fibonacci(n) = Fibonacci(n – 1) + Fibonacci(n – 2) 4.3: Giải thuật đệ quy: Bất hàm triệu gọi hàm khác, hàm tự triệu gọi Kiểu hàm gọi hàm đệ quy Phương pháp đệ quy thường dùng phổ biến ứng dụng mà cách giải thể việc áp dụng liên tiếp giải pháp cho tập hợp tốn Ví dụ 1: tính n! n! = 1*2*3*…*(n-2)*(n-1)*n với n >= 0! = /* Ham tinh giai thua */ #include #include void main(void) { int in; long giaithua(int); printf("Nhap vao so n: "); scanf("%d", &in); printf("%d! = %ld.\n", in, giaithua(in)); getch(); } long giaithua(int in) { int i; long ltich = 1; if (in == 0) return (1L); else { for (i = 1; i Để khai báo biến kiểu ký tự ta khai báo biến kiểu unsigned char Mỗi số miền giá trị kiểu unsigned char tương ứng với ký tự bảng mã ASCII Kiểu char: lưu số nguyên từ -128 đến 127 Kiểu char sử dụng bit trái để làm bit dấu => Nếu gán giá trị > 127 cho biến kiểu char giá trị biến số âm (?) 2.2 Kiểu số nguyên bytes (16 bits) Kiểu số nguyên bytes gồm có kiểu sau: enum Từ -32,768 đến 32,767 unsigned int Từ đến 65,535 short int Từ -32,768 đến 32,767 int Từ -32,768 đến 32,767 Kiểu enum, short int, int : Lưu số nguyên từ -32768 đến 32767 Sử dụng bit bên trái để làm bit dấu => Nếu gán giá trị >32767 cho biến có kiểu giá trị biến số âm Kiểu unsigned int: Kiểu unsigned int lưu số nguyên dương từ đến 65535 2.3 Kiểu số nguyên byte (32 bits) Kiểu số nguyên bytes hay gọi số nguyên dài (long) gồm có kiểu sau: unsigned long Từ đến 4,294,967,295 long Từ -2,147,483,648 đến 2,147,483,647 Kiểu long : Lưu số nguyên từ -2147483658 đến 2147483647 Sử dụng bit bên trái để làm bit dấu => Nếu gán giá trị >2147483647 cho biến có kiểu long giá trị biến số âm Kiểu unsigned long: Kiểu unsigned long lưu số nguyên dương từ đến 4294967295 Kiểu số thực thường thực với phép toán: O =?{+, -, *, /, , =, =, ?}? 2.4 Kiểu số thực: Kiểu số thực dùng để lưu số thực hay số có dấu chấm thập phân gồm có kiểu sau: float bytes Từ 3.4 * 10-38 đến 3.4 * 1038 double bytes Từ 1.7 * 10-308 đến 1.7 * 10308 long double 10 bytes Từ 3.4 *10-4932 đến 1.1 *104932 Mỗi kiểu số thực có miền giá trị độ xác (số số lẻ) khác Tùy vào nhu cầu sử dụng mà ta khai báo biến thuộc kiểu Ngồi ta cịn có kiểu liệu void, kiểu mang ý nghĩa kiểu rỗng không chứa giá trị Kiểu số nguyên thường thực với phép toán: O =?{+, -, *, /, DIV, MOD, , =, =, ?}? 2.5 Kiểu ký tự: Có thể có kích thước sau: + Kiểu ký tự byte + Kiểu ký tự bytes Kiểu ký tự thường thực với phép toán: O =??{+, -, , =, =, ORD, CHR, ?}? - Kiểu chuỗi ký tự: Có kích thước tùy thuộc vào ngơn ngữ lập trình Kiểu chuỗi ký tự thường thực với phép toán: O =??{+,???, , =, =, Length, Trunc, ?}? - Kiểu luận lý: Thường có kích thước byte Kiểu luận lý thường thực với phép toán: O =?{NOT, AND, OR, XOR, , =, =, ?}? Các kiểu liệu có cấu trúc 3.1 Khái niệm: Kiểu cấu trúc (Structure) kiểu liệu bao gồm nhiều thành phần có kiểu khác nhau, thành phần gọi trường (field) Sự khác biệt kiểu cấu trúc kiểu mảng là: phần tử mảng kiểu phần tử kiểu cấu trúc có kiểu khác Hình ảnh kiểu cấu trúc minh họa: 3.2 Định nghĩa kiểu cấu trúc struct { ; ; …… ; }; Trong đó: - : tên đặt theo quy tắc đặt tên danh biểu; tên mang ý nghĩa tên kiểu cấu trúc - (i=1 n): trường cấu trúc có liệu thuộc kiểu (tên trường phải tên đặt theo quy tắc đặt tên danh biểu) Ví dụ 1: Để quản lý ngày, tháng, năm ngày năm ta khai báo kiểu cấu trúc gồm thông tin: ngày, tháng, năm struct NgayThang { unsigned char Ngay; unsigned char Thang; unsigned int Nam; }; typedef struct { 45 tm = tr; tr= tr->pRight; } else{ Node *q = tr; Node *p = q->pLeft; while (p->pLeft!=NULL){ q= p; p = p->pLeft; } tm= p; q->pLeft= p->pRight; return tm; } void main() { XoaNut(Root, 10); } 4.5 Xóa tồn nhị phân Việt xóa nhị phân thực đệ quy sau: void XoaCay(Tree &t) • Xóa bên trái • Xóa bên phải • Xóa nút gốc } 46 { if (t!= NULL){ XoaCay(t->pLeft); XoaCay(t->pRight); delete t; } } void main() { XoaCay(Root); } Bài tập: 1.Trình bày thuật tốn cài đặt tất thao tác nhị phân tìm kiếm, câynhị phân tìm kiếm cân trường hợp chấp nh ận trùng khóa nhận diện nút cây? Trình bày tất thuật tốn cài đặt tất thuật toán để thực việc hủymột nút nhị phân tìm kiếm có 02 con? Theo bạn, thuật tốn đơn giản? Cho nhận xét thuật toán? Trình bày cài đặt tất thuật toán để thực thao tá c nhịphân tìm kiếm, nhị phân tìm kiếm cân hai trường hợp: Chấp nhận vàKhông chấp nhận trùng lắp khóa nút cách khơng sử dụng thuật_toán đệ quy (Trừ thao tác trình bày tài liệu)? Trình bày thuật tốn cài đặt chương trình thực cơng việc sau nhị phân: a) Tính số nút b) Tính số nút trung gian c) Tính chiều dài đường tới nút có khóa K d) Cho biết cấp nút có khóa K 47 Trình bày thuật tốn cài đặt chương trình thực cơng việc tạo nhị phântìm kiếm mà khóa nút khóa nút t rong danh sách liên kết đôisao cho tối ưu hóa nhớ Biết rằng, d anh sách liên kết đôi ban đầu không cần thiết sau tạo xong nhị phân tìm kiếm giả sử khơng cho phép trùng khóa nút Với yêu cầu tập trên, trường hợp danh sách l iên kết có nhiềunút có thành phần liệu giống nhau, bạn đề xu ất phương án giải đểkhông bị liệu sau tạo xong nhị phân tìm kiếm Trình bày thuật tốn cài đặt chương trình thực cơng việc chuyển nhị_phân tìm kiếm thành danh sách liên kết đơi cho tối ưu hóa nhớ Biết rằng,cây nhị phân tìm kiếm ban đầu không cần thiết_sau tạo xong danh sách liên kết (ngược với yêu cầu tập 8) 48 Chương 5: Các phương pháp Sắp xếp Khái quát xếp: Để thuận tiện giảm thiểu thời gian thao tác mà đặc biệt để tìm kiếm liệu dễ dàng nhanh chóng, thơng thường trước thao tác liệu mảng, tập tin có thứ tự Do vậy, thao tác xếp liệu thao tác cần thiết thường gặp trình lưu trữ, quản lý liệu Thứ tự xuất liệu thứ tự tăng (không giảm dần) thứ tự giảm (không tăng dần) Trong phạm vi chương thực việc xếp liệu theo thứ tự tăng Việc xếp liệu theo thứ tự giảm hồn tồn tương tự Có nhiều thuật tốn xếp song phân chia thuật tốn xếp thành hai nhóm vào vị trí lưu trữ liệu máy tính, là: - Các giải thuật xếp thứ tự nội (sắp xếp thứ tự dãy/mảng), - Các giải thuật xếp thứ tự ngoại (sắp xếp thứ tự tập tin/file) Các giải thuật xếp (Sắp xếp dãy/mảng) Ở đây, toàn liệu cần xếp đưa vào nhớ (RAM) Do vậy, số phần tử liệu không lớn giới hạn nhớ trong, nhiên tốc độ xếp tương đối nhanh Các giải thuật xếp nội bao gồm nhóm sau: - Sắp xếp phương pháp đếm (counting sort), - Sắp xếp phương pháp đổi chỗ (exchange sort), - Sắp xếp phương pháp chọn lựa (selection sort), - Sắp xếp phương pháp chèn (insertion sort), - Sắp xếp phương pháp trộn (merge sort) Trong phạm vi giáo trình trình bày số thuật toán xếp tiêu biểu thuật tốn xếp nhóm giả sử thứ tự xếp N phần tử có kiểu liệu T mảng M thứ tự tăng 2.1 Sắp xếp phương pháp đổi chỗ (Exchange Sort) Các thuật tốn phần tìm cách đổi chỗ phần tử đứng sai vị trí (so với mảng xếp) mảng M cho để cuối tất phần tử mảng M vị trí mảng xếp 49 Các thuật toán xếp phương pháp đổi chỗ bao gồm: - Thuật toán xếp bọt (bubble sort), - Thuật toán xếp lắc (shaker sort), - Thuật toán xếp giảm độ tăng hay độ dài bước giảm dần (shell sort), - Thuật toán xếp dựa phân hoạch (quick sort) Ở trình bày hai thuật tốn phổ biến thuật toán xếp bọt xếp dựa phân hoạch a Thuật toán xếp bọt (Bubble Sort): - Tư tưởng: + Đi từ cuối mảng đầu mảng, trình phần tử (đứng phía sau) nhỏ phần tử đứng (trước) theo ngun tắc bọt khí phần tử nhẹ bị "trồi" lên phía phần tử nặng (hai phần tử đổi chỗ cho nhau) Kết phần tử nhỏ (nhẹ nhất) đưa lên (trồi lên) bề mặt (đầu mảng) nhanh + Sau lần đưa phần tử trồi lên chỗ Do vậy, sau N-1 lần tất phần tử mảng M có thứ tự tăng - Thuật tốn: B1: First = B2: IF (First = N) Thực Bkt B3: ELSE B3.1: Under = N B3.2: If (Under = First) Thực B4 B3.3: Else B3.3.1: if (M[Under] < M[Under - 1]) Swap(M[Under], M[Under - 1]) B3.3.2: Under-B3.3.3: Lặp lại B3.2 B4: First++ B5: Lặp lại B2 Bkt: Kết thúc - Cài đặt thuật tốn: Hàm BubbleSort có prototype sau: void BubbleSort(T M[], int N); 50 //Đổi chỗ phần tử cho Hàm thực việc xếp N phần tử có kiểu liệu T mảng M theo thứ tự tăng dựa thuật toán xếp bọt Nội dung hàm sau: void BubbleSort(T M[], int N) { for (int I = 0; I < N-1; I++) for (int J = N-1; J > I; J ) if (M[J] < M[J-1]) Swap(M[J], M[J-1]); return; }? Hàm Swap có prototype sau: void Swap(T????X, T????Y); Hàm thực việc hoán vị giá trị hai phần tử X Y cho Nội dung hàm sau: void Swap(T????X, T????Y) { T Temp = X; X = Y; Y = Temp; return; }? - Ví dụ minh họa thuật tốn: Giả sử ta cần xếp mảng M có 10 phần tử sau (N = 10): M: 15 10 20 10 25 35 22 30 Ta thực lần (N - = 10 - = 9) để xếp mảng M: - Phân tích thuật tốn: + Trong trường hợp: Số phép gán: G = Số phép so sánh: S = (N-1) + (N-2) + ? + = ½N(N-1) + Trong trường hợp tốt nhất: mảng ban đầu có thứ tự tăng Số phép hoán vị: Hmin = + Trong trường hợp xấu nhất: mảng ban đầu có thứ tự giảm Số phép hoán vị: Hmin = (N-1) + (N-2) + ? + = ½N(N-1) + Số phép hốn vị trung bình: Havg = ¼N(N-1) - Nhận xét thuật toán bọt: + Thuật toán xếp bọt đơn giản, dễ hiểu dễ cài đặt 51 + Trong thuật toán xếp bọt, lần từ cuối mảng đầu mảng phần tử nhẹ trồi lên nhanh phần tử nặng lại "chìm" xuống chậm chạp không tận dụng chiều xuống (chiều từ đầu mảng cuối mảng) + Thuật toán bọt không phát đoạn phần tử nằm hai đầu mảng nằm vị trí để giảm bớt qng đường lần 2.2 sắp_xếp_chọn: Vấn đề xếp tiền : Có xấp tiền gồm nhiều tờ có mệnh giá khác để lộn xộn, cần xếp lại theo thứ tự tiền nhỏ trước, tiền lớn sau Phương pháp xếp tiền là: chọn tờ tiền từ nhỏ đến lớn để xếp hết xấp tiền Đối với mảng, bước thực là: • • • Trong N phần tử mảng, chọn phần tử bé nhất, chuyển lên đầu mảng Trong N-1 phần tử lại, chọn phần tử bé nhất, chuyển vào vị trí thứ Tiếp tục xếp hết 2.3 xếp chèn: Phương pháp: • • • • Giống cách xếp chia quân Quân nhận chèn vào quân có tay Các quân tay ln xếp Thuật tốn: void InsertionSort(int a[], int N) { int i, j, temp; for(i = 1; i< N; i++) { temp = a[i]; j = i- 1; while ((j>=0)&&(a[j]>a[j+1])) { a[j+1] = a[j]; j ; 52 } if (j!=i-1) a[j+1] = temp; } 2.4 Sắp xếp phân đoạn: – Phương pháp: Dùng giải pháp đệ quy (chia để trị) • • • • • Bước 1: Phân hoạch mảng A ban đầu thành mảng B C cho bi cj bi B, cj C Bước 2: Sắp xếp mảng B đệ quy Bước 3: Sắp xếp mảng C đệ quy Điều kiện dừng: mảng cần có phần tử xem Vì B, C bi cj nên mảng A 2.5 Sắp xếp hòa nhập: –Cũng sửPhương pháp: dụng giải pháp chia để trị • • • Bước 1: Chia mảng A ban đầu thành mảng B C Bước 2, 3: Sắp xếp mảng B C đệ quy (Điều kiện dừng: mảng cần có phần tử) Bước 4: Trộn (merge) mảng B, C thành mảng A Thuật toán: int Partition(int a[], int p, int r) { int t; // phân hoạch return t; } void QuickSort(int a[], int p, int r) { int t = Partition(a, p, r); if (p< t-1) QuickSort(a, p, t-1); if (t+1< r) QuickSort(a, t+1, r); 53 } Chương 6: Tìm Kiếm Khái quát tìm kiếm Trong thực tế, thao tác, khai thác liệu lúc phải thực thao tác tìm kiếm Việc tìm kiếm nhanh hay 54 chậm tùy thuộc vào trạng thái trật tự liệu Kết việc tìm kiếm khơng có (khơng tìm thấy) có (tìm thấy) Nếu kết tìm kiếm có tìm thấy nhiều cịn phải xác định xem vị trí phần tử liệu tìm thấy đâu? Trong phạm vi chương tìm cách giải câu hỏi Trước vào nghiên cứu chi tiết, giả sử phần tử liệu xem xét có thành phần khóa (Key) để nhận diện, có kiểu liệu T đó, thành phần cịn lại thông tin (Info) liên quan đến phần tử liệu Như phần tử liệu có cấu trúc liệu sau: typedef { T struct DataElement Key; InfoType } DataType; Info; Trong tài liệu này, nói tới giá trị phần tử liệu muốn nói tới giá trị khóa (Key) phần tử liệu Để đơn giản, giả sử phần tử liệu thành phần khóa nhận diện Việc tìm kiếm phần tử diễn dãy/mảng (tìm kiếm nội) diễn tập tin/ file (tìm kiếm ngoại) Phần tử cần tìm phần tử cần thỏa mãn điều kiện tìm kiếm (thường có giá trị giá trị tìm kiếm) Tùy thuộc vào tốn cụ thể mà điều kiện tìm kiếm khác song việc tìm kiếm liệu thường vận dụng theo thuật tốn trình bày sau Tìm (Linear Search) Thuật tốn tìm tuyến tính cịn gọi Thuật tốn tìm kiếm (Sequential Search) a Tư tưởng: Lần lượt so sánh phần tử mảng M với giá trị X phần tử tìm đến phần tử có giá trị X duyệt qua hết tất phần tử mảng M kết thúc b Thuật tốn: B1: k = B2: IF M[k]?? X AND k?? N B2.1: k++ 55 B2.2: Lặp lại B2 B3: IF k?? N Tìm thấy vị trí k B4: ELSE //Duyệt từ đầu mảng //Nếu chưa tìm thấy chưa duyệt hết mảng Khơng tìm thấy phần tử có giá trị X B5: Kết thúc c Cài đặt thuật tốn: Hàm LinearSearch có prototype: int LinearSearch (T M[], int N, T X); Hàm thực việc tìm kiếm phần tử có giá trị X mảng M có N phần tử Nếu tìm thấy, hàm trả số nguyên có giá trị từ đến N-1 vị trí tương ứng phần tử tìm thấy Trong trường hợp ngược lại, hàm trả giá trị -1 (không tìm thấy) Nội dung hàm sau: int LinearSearch (T M[], int N, T X) { int k = 0; while (M[k] != X??? k < N) k++; if (k < N) return (k); return (-1); }? d Phân tích thuật tốn: - Trường hợp tốt phần tử mảng có giá trị X: Số phép gán: Gmin = Số phép so sánh: Smin = + = - Trường hợp xấu khơng tìm thấy phần tử có giá trị X: Số phép gán: Gmax = Số phép so sánh: Smax = 2N+1 - Trung bình: Số phép gán: Gavg = Số phép so sánh: Savg = (3 + 2N + 1) : = N + e Cải tiến thuật toán: Trong thuật toán trên, bước lặp cần phải thực phép so sánh để kiểm tra tìm thấy kiểm sốt hết mảng q trình duyệt mảng Chúng ta giảm bớt phép so sánh thêm vào cuối mảng phần tử cầm canh (sentinel/stand 56 by) có giá trị X để nhận diện hết mảng duyệt mảng, thuật tốn cải tiến lại sau: B1: k = B2: M[N+1] = X B3: IF M[k]?? X B3.1: k++ B3.2: Lặp lại B3 B4: IF k < N Tìm thấy vị trí k B5: ELSE //Phần tử cầm canh //k = N song phần tử cầm canh Khơng tìm thấy phần tử có giá trị X B6: Kết thúc Hàm LinearSearch viết lại thành hàm LinearSearch1 sau: int LinearSearch1 (T M[], int N, T X) { int k = 0; M[N] = X; while (M[k] != X) k++; if (k < N) return (k); return (-1); }? f Phân tích thuật tốn cải tiến: - Trường hợp tốt phần tử mảng có giá trị X: Số phép gán: Gmin = Số phép so sánh: Smin = + = - Trường hợp xấu không tìm thấy phần tử có giá trị X: Số phép gán: Gmax = Số phép so sánh: Smax = (N+1) + = N + - Trung bình: Số phép gán: Gavg = Số phép so sánh: Savg = (2 + N + 2) : = N/2 + - Như vậy, thời gian thực phép gán khơng đáng kể thuật toán cải tiến chạy nhanh thuật toán nguyên thủy 57 Tìm nhị phân (Binary Search) Thuật tốn tìm tuyến tính tỏ đơn giản thuận tiện trường hợp số phần tử dãy không lớn Tuy nhiên, số phần tử dãy lớn, chẳng hạn tìm kiếm tên khách hàng danh bạ điện thoại thành phố lớn theo thuật tốn tìm thực nhiều thời gian Trong thực tế, thơng thường phần tử dãy có thứ tự, thuật tốn tìm nhị phân sau rút ngắn đáng kể thời gian tìm kiếm dãy có thứ tự Trong thuật tốn giả sử phần tử dãy có thứ tự tăng (khơng giảm dần), tức phần tử đứng trước ln có giá trị nhỏ (khơng lớn hơn) phần tử đứng sau Khi đó, X nhỏ giá trị phần tử đứng dãy (M[Mid]) X tìm thấy nửa đầu dãy ngược lại, X lớn phần tử M[Mid] X tìm thấy nửa sau dãy a Tư tưởng: Phạm vi tìm kiếm ban đầu từ phần tử dãy (First = 1) phần tử cuối dãy (Last = N) So sánh giá trị X với giá trị phần tử đứng dãy M M[Mid] Nếu X = M[Mid]: Tìm thấy Nếu X < M[Mid]: Rút ngắn phạm vi tìm kiếm nửa đầu dãy M (Last = Mid-1) Nếu X > M[Mid]: Rút ngắn phạm vi tìm kiếm nửa sau dãy M (First = Mid+1) Lặp lại trình tìm thấy phần tử có giá trị X phạm vi tìm kiếm khơng cịn (First > Last) b Thuật tốn đệ quy (Recursion Algorithm): B1: First = B2: Last = N B3: IF (First > Last) B3.1: Khơng tìm thấy B3.2: Thực Bkt B4: Mid = (First + Last)/ B5: IF (X = M[Mid]) //Hết phạm vi tìm kiếm B5.1: Tìm thấy vị trí Mid B5.2: Thực Bkt 58 B6: IF (X < M[Mid]) Tìm đệ quy từ First đến Last = Mid - B7: IF (X > M[Mid]) Tìm đệ quy từ First = Mid + đến Last Bkt: Kết thúc c Cài đặt thuật tốn đệ quy: Hàm BinarySearch có prototype: int BinarySearch (T M[], int N, T X); Hàm thực việc tìm kiếm phần tử có giá trị X mảng M có N phần tử có thứ tự tăng Nếu tìm thấy, hàm trả số ngun có giá trị từ đến N-1 vị trí tương ứng phần tử tìm thấy Trong trường hợp ngược lại, hàm trả giá trị -1 (khơng tìm thấy) Hàm BinarySearch sử dụng hàm đệ quy RecBinarySearch có prototype: int RecBinarySearch(T M[], int First, int Last, T X); Hàm RecBinarySearch thực việc tìm kiếm phần tử có giá trị X mảng M phạm vi từ phần tử thứ First đến phần tử thứ Last Nếu tìm thấy, hàm trả số nguyên có giá trị từ First đến Last vị trí tương ứng phần tử tìm thấy Trong trường hợp ngược lại, hàm trả giá trị -1 (khơng tìm thấy) 4.Câu hỏi Bài tập Trình bày tư tưởng thuật tốn tìm kiếm: Tuyến tính, Nhị phân, Chỉ mục? Các thuật tốn vận dụng trường hợp nào? Cho ví dụ? Cài đặt lại thuật tốn tìm tuyến tính cách: - Sử dụng vòng lặp for, - Sử dụng vòng lặp … while? Có nhận xét cho trường hợp? Trong trường hợp phần tử dãy có thứ tự tăng, cải tiến lại thuật tốn tìm tuyến tính? Cài đặt thuật tốn cải tiến? Đánh giá so sánh thuật toán nguyên thủy với thuật toán cải tiến Trong trường hợp phần tử dãy có thứ tự giảm, trình bày cài đặt lại thuật tốn tìm nhị phân hai trường hợp: Đệ quy Không đệ quy? Vận dụng thuật tốn tìm nhị phân, cải tiến cài đặt lại thuật tốn tìm kiếm dựa theo tập tin mục? Đánh giá so sánh thuật toán nguyên thủy với thuật toán cải tiến? 59 Sử dụng hàm random C để tạo dãy (mảng) M có tối thiểu 1.000 số nguyên, sau chọn ngẫu nhiên (cũng hàm random) giá trị nguyên K Vận dụng thuật tốn tìm tuyến tính, tìm nhị phân để tìm kiếm phần tử có giá trị K mảng M Với liệu nhau, cho biết thời gian thực thuật tốn Trình bày cài đặt thuật tốn tìm tuyến tính phần tử mảng hai chiều hai trường hợp: - Không sử dụng phần tử “Cầm canh” - Có sử dụng phần tử “Cầm canh” Cho biết thời gian thực hai thuật toán hai trường hợp Sử dụng hàm random C để tạo tối thiểu 1.000 số nguyên lưu trữ vào mot tập tin có tên SONGUYEN.DAT, sau chọn ngẫu nhiên (cũng hàm random) giá trị nguyên K Vận dụng thuật tốn tìm tuyến tính để tìm kiếm phần tử có giá trị K tập tin SONGUYEN.DAT ... lập trình phần cài đặt thuật tốn ngơn ngữ cụ thể Phân tích giải thuật: Mối quan hệ cấu trúc liệu Giải thuật minh họa đẳng thức: Cấu trúc liệu + Giải thuật = Chương trình Như vậy, có cấu trúc liệu. .. giá cấu trúc liệu Để đánh giá cấu trúc liệu thường dựa vào số tiêu chí sau: - Cấu trúc liệu phải tiết kiệm tài nguyên (bộ nhớ trong), - Cấu trúc liệu phải phản ảnh thực tế toán, - Cấu trúc liệu. .. chưa có cấu trúc liệu Một chương trình máy tính hồn thiện có đầy đủ Cấu trúc liệu để lưu trữ liệu Giải thuật xử lý liệu theo yêu cầu toán đặt 3.1 Đánh giá cấu trúc liệu giải thuật 3.1.1 Các tiêu