Bài giảng Kĩ thuật lập trình - Chương 10: Thuật toán tổng hợp
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Kĩ thuật lập trình - Chương 10: Thuật toán tổng hợp", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
Tài liệu đính kèm:
- bai_giang_ki_thuat_lap_trinh_chuong_10_thuat_toan_tong_hop.pdf
Nội dung text: Bài giảng Kĩ thuật lập trình - Chương 10: Thuật toán tổng hợp
- Kỹ thuật lập trình Chương 10: Thuậttoántổng quát 010101010101010110000101010101010101011000010101010101010101100001 StateController010101010010101010010101010101001010101001010101010100101010100101 start() 101001100011001001001010100110001100100100101010011000110010010010 stop() 110010110010001000001011001011001000100000101100101100100010000010 010101010101010110000101010101010101011000010101010101010101100001y = A*x + B*u; 010101010010101010010101010101001010101001010101010100101010100101x = C*x + d*u; 101001100011001001001010100110001100100100101010011000110010010010 110010110010001000001011001011001000100000101100101100100010000010 LQGController010101010101010110000101010101010101011000010101010101010101100001 start() 010101010010101010010101010101001010101001010101010100101010100101 stop() 101001100011001001001010100110001100100100101010011000110010010010 110010110010001000001011001011001000100000101100101100100010000010 12/25/2007
- Nộidung chương 10 10.1 Tổng quát hóa kiểudữ liệuphầntử 10.2 Tổng quát hóa phép toán cơ sở 10.3 Tổng quát hóa phương pháp truy lặpphầntử Chương 10: Thuật toán tổng quát 2
- 10.1 Tổng quát hóa kiểudữ liệuphầntử Thực tế: —Khoảng 80% thời gian làm việc của một người thư ký văn phòng trước ₫ây (và hiện nay ở nhiều nơi) sử dụng cho công việc tìm kiếm, sắp xếp, ₫ối chiếu, so sánh, tài liệu và hồ sơ — Trung bình, khoảng 80% mã chương trình và thời gian thực hiện chương trình dành cho thực hiện các thuật toán ít liên quan trực tiếp tới bài toán ứng dụng cụ thể, mà liên quan tới tìm kiếm, sắp xếp, lựa chọn, so sánh dữ liệu Dữ liệu ₫ược quản lý tốt nhất trong các cấu trúc dạng "container" (vector, list, map, tree, queue, ) Vấn ₫ề xây dựng hàm áp dụng cho các "container": Nhiều hàm chỉ khác nhau về kiểu dữ liệu tham số áp dụng, không khác nhau về thuật toán Giải pháp: Xây dựng khuôn mẫu hàm, tổng quát hóa kiểu dữ liệu phần tử Chương 10: Thuật toán tổng quát 3
- Ví dụ: Thuật toán tìm ₫ịa chỉ phần tử ₫ầu tiên trong một mảng có giá trị lớn hơn một số cho trước: template T* find_elem(T *first, T* last, T k) { while (first != last && !(*first > k)) ++first; return first; } void main() { int a[] = { 1, 3, 5, 2, 7, 9, 6 }; int *p = find_elem(a,a+7,4); if (p != a+7) { cout 4 :" 4:" << *p; } double b[] = { 1.5, 3.2, 5.1, 2.4, 7.6, 9.7, 6.5 }; double *q = find_elem(b+2,b+6,7.0); *q = 7.0; 4 Ch} ương 10: Thuật toán tổng quát
- Ví dụ: Thuậttoáncộng hai vector, kếtquả lưuvàovector thứ ba #include #include "myvector.h" template void addVector(const Vector & a, const Vector & b, Vector & c) { assert(a.size() == b.size() && a.size() == c.size()); for (int i= 0; i Vector operator+(const Vector &a, const Vector & b) { Vector c(a.size()); addVector(a,b,c); return c; } Chương 10: Thuật toán tổng quát 5
- 10.2 Tổng quát hóa phép toán cơ sở Vấn ₫ề: Nhiều thuật toán chỉ khác nhau ở một vài phép toán (cơ sở) trong khi thực hiện hàm Ví dụ: —Các thuật toán tìm ₫ịa chỉ phần tử ₫ầu tiên trong một mảng số nguyên có giá trị lớn hơn, nhỏ hơn, lớn hơn hoặc bằng, nhỏ hơn hoặc bằng, một số cho trước —Các thuật toán cộng, trừ, nhân, chia, từng phần tử của hai mảng số thực, kết quả lưu vào một mảng mới —Các thuật toán cộng, trừ, nhân, chia, từng phần tử của hai vector (hoặc của hai danh sách, hai ma trận, ) Giải pháp: Tổng quát hóa thuật toán cho các phép toán cơ sở khác nhau! Chương 10: Thuật toán tổng quát 6
- template int* find_elem(int* first, int* last, int k, COMP comp) { while (first != last && !comp(*first, k)) ++first; return first; } bool is_greater(int a, int b) { return a > b; } bool is_less(int a, int b) { return a 4 is " > c; Ch}ương 10: Thuật toán tổng quát 7
- Tham số khuôn mẫuchophéptoán Có thể là mộthàm, vídụ bool is_greater(int a, int b){ return a > b; } bool is_less(int a, int b) { return a ₫ốitượng hàm, ví dụ struct Greater { bool operator()(int a, int b) { return a > b; } }; struct Less { bool operator()(int a, int b) { return a < b; } }; struct Add { int operator()(int a, int b) { return a + b; } }; Chương 10: Thuật toán tổng quát 8
- Ví dụ sử dụng ₫ốitượng hàm void main() { int a[] = { 1, 3, 5, 2, 7, 9, 6 }; int* alast = a+7; Greater greater; Less less; int* p1 = find_elem(a,alast,4,greater); int* p2 = find_elem(a,alast,4,less); if (p1 != alast) cout 4 is " > c; } Chương 10: Thuật toán tổng quát 9
- Ưu ₫iểmcủa ₫ốitượng hàm Đốitượng hàm có thể chứatrạng thái Hàm toán tử () có thể₫ịnh nghĩa inline => tăng hiệusuất template void apply(int* first, int* last, OP& op) { while (first != last) { op(*first); ++first; } } class Sum { int val; public: Sum(int init = 0) : val(init) {} void operator()(int k) { val += k; } int value() const { return val; } }; Chương 10: Thuật toán tổng quát 10
- class Prod { int val; public: Prod(int init=1): val(init) {} void operator()(int k) { val *= k; } int value() const { return val; } }; struct Negate {void operator()(int& k) { k = -k;} }; struct Print { void operator()(int& k) { cout > c; } Chương 10: Thuật toán tổng quát 11
- Kếthợp2 bướctổng quát hóa template T* find_elem(T* first, T* last, T k, COMP comp) { while (first != last && !comp(*first, k)) ++first; return first; } template void apply(T* first, T* last, OP& op) { while (first != last) { op(*first); ++first; } } Chương 10: Thuật toán tổng quát 12
- Khuôn mẫulớpchocác₫ốitượng hàm template struct Greater{ bool operator()(const T& a, const T& b) { return a > b; } }; template struct Less{ bool operator()(const T& a, const T& b) { return a > b; } }; template class Sum { T val; public: Sum(const T& init = T(0)) : val(init) {} void operator()(const T& k) { val += k; } T value() const { return val; } }; Chương 10: Thuật toán tổng quát 13
- template struct Negate { void operator()(T& k) { k = -k;} }; template struct Print { void operator()(const T& k) { cout ()); int* p2 = find_elem(a,alast,4,Less ()); if (p1 != alast) cout 4 is " sum_op; apply(a,a+7,sum_op); cout ()); apply(a,a+7,Print ()); char c; cin >> c; }Chương 10: Thuật toán tổng quát 14
- 10.3 Tổng quát hóa truy lặpphầntử Vấn ₫ề 1: Một thuật toán (tìm kiếm, lựa chọn, phân loại, tính tổng, ) áp dụng cho một mảng, một vector, một danh sách họăc một cấu trúc khác thực chất chỉ khác nhau ở cách truy lặp phần tử Vấn ₫ề 2: Theo phương pháp truyền thống, ₫ể truy lặp phần tử của một cấu trúc "container", nói chung ta cần biết cấu trúc ₫ó ₫ược xây dựng như thế nào —Mảng: Truy lặp qua chỉ số hoặc qua con trỏ — Vector: Truy lặp qua chỉ số —List: Truy lặp qua quan hệ móc nối (sử dụng con trỏ) — Chương 10: Thuật toán tổng quát 15
- Ví dụ thuậttoáncopy Áp dụng cho kiểumảng thô template void copy(const T* s, T* d, int n) { while (n ) { *d = *s; ++s; ++d; } } Áp dụng cho kiểuVector template void copy(const Vector & s, Vector & d) { for (int i=0; i void copy(const List & s, List & d) { ListItem *sItem=s.getHead(), *dItem=d.getHead(); while (sItem != 0) { dItem->data = sItem->data; dIem = dItem->getNext(); sItem=sItem->getNext(); } } Chương 10: Thuật toán tổng quát 16
- Ví dụ thuậttoánfind_max Áp dụng cho kiểu mảng thô template T* find_max(T* first, T* last) { T* pMax = first; while (first != last) { if (*first > *pMax) pMax = first; ++first; } return pMax; } Áp dụng cho kiểuVector template T* find_max(const Vector & v) { int iMax = 0; for (int i=0; i v[iMax]) iMax = i; return &v[iMax]; } Chương 10: Thuật toán tổng quát 17
- Áp dụng cho kiểu List (₫ã làm quen): template ListItem * find_max(List & l) { ListItem *pItem = l.getHead(); ListItem *pMaxItem = pItem; while (pItem != 0) { if (pItem->data > pMaxItem->data) pMaxItem = pItem; pItem = pItem->getNext(); } return pMaxItem; } Â Cần tổng quát hóa phương pháp truy lặp phần tử! Chương 10: Thuật toán tổng quát 18
- Bộ truy lặp (iterator) Mục ₫ích: Tạomộtcơ chế thống nhấtchoviệctruylặpphầntử cho các cấutrúcdữ liệumàkhôngcầnbiếtchi tiếtthựcthibên trong từng cấutrúc Ý tưởng: Mỗicấutrúcdữ liệucungcấpmộtkiểubộ truy lặp riêng, có ₫ặctínhtương tự như mộtcon trỏ (trong trường hợp ₫ặcbiệtcóthể là mộtcon trỏ thực) Tổng quát hóa thuậttoáncopy: template void copy(Iterator1 s, Iterator2 d, int n) { while (n ) { *d = *s; ++s; ++d; } Cácphéptoánápdụng } ₫ượctương tự con trỏ Chương 10: Thuật toán tổng quát 19
- Tổng quát hóa thuậttoánfind_max: template ITERATOR find_max(ITERATOR first, ITERATOR last) { ITERATOR pMax = first; while (first != last) { if (*first > *pMax) pMax = first; ++first; } return pMax; Cácphéptoánápdụng } ₫ượctương tự con trỏ Chương 10: Thuật toán tổng quát 20
- Bổ sung bộ truy lặpchokiểuVector KiểuVector lưutrữ dữ liệudướidạng mộtmảng => có thể sử dụng bộ truy lặpdướidạng con trỏ! template class Vector { int nelem; T* data; public: typedef T* Iterator; Iteratator begin() { return data; } Iteratator end() { return data + nElem; } }; void main() { Vector a(5,1.0),b(6); copy(a.begin(),b.begin(),a.size()); } Chương 10: Thuật toán tổng quát 21
- Bổ sung bộ truy lặpchokiểuList template class ListIterator { ListItem *pItem; ListIterator(ListItem * p = 0) : pItem(p) {} friend class List ; public: T& operator*() { return pItem->data; } ListIterator & operator++() { if (pItem != 0) pItem = pItem->getNext(); return *this; } friend bool operator!=(ListIterator a, ListIterator b) { return a.pItem != b.pItem; } }; Chương 10: Thuật toán tổng quát 22
- Khuôn mẫuList cảitiến template class List { ListItem *pHead; public: ListIterator begin() { return ListIterator (pHead); } ListIterator end() { return ListIterator (0); } }; Chương 10: Thuật toán tổng quát 23
- Bài tậpvề nhà Xây dựng thuậttoánsắpxếptổng quát ₫ể có thể áp dụng cho nhiềucấutrúcdữ liệutậphợp khác nhau cũng như nhiềutiêu chuẩnsắpxếp khác nhau. Viếtchương trình minh họa. Xây dựng thuậttoáncộng/trừ/nhân/chia từng phầntử củahai cấutrúcdữ liệutậphợpbấtkỳ. Viếtchương trình minh họa. Chương 10: Thuật toán tổng quát 24